blob: 1cd5e0b509751ab24e47b4b194cab8d9069887cb [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{
developer963da0c2022-09-13 15:58:27 +08001784 char cmd[128]={0};
1785 char buf[128]={0};
1786 char temp_output[128] = {0};
1787 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001788 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001789
1790 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001791 if (NULL == output_string)
1792 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001793
1794 band = wifi_index_to_band(radioIndex);
1795 if (band == band_2_4) {
1796 strcat(temp_output, "b,g,");
1797 } else if (band == band_5) {
1798 strcat(temp_output, "a,");
1799 }
developer033b37b2022-10-18 11:27:46 +08001800 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001801 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001802 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001803 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001804 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001805 strcat(temp_output, "n,");
1806 }
developer06a01d92022-09-07 16:32:39 +08001807
developer963da0c2022-09-13 15:58:27 +08001808 // vht capabilities
1809 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001810 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001811 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001812 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001813 strcat(temp_output, "ac,");
1814 }
1815 }
1816
1817 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001818 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001819 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001820 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001821 strcat(temp_output, "ax,");
1822 }
1823
developer7c4cd202023-03-01 10:56:29 +08001824 // eht capabilities
1825 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'EHT MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
1826 _syscmd(cmd, buf, sizeof(buf));
1827 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
1828 strcat(temp_output, "be,");
1829 }
1830
developer963da0c2022-09-13 15:58:27 +08001831 // Remove the last comma
1832 if (strlen(temp_output) != 0)
1833 temp_output[strlen(temp_output)-1] = '\0';
1834 strncpy(output_string, temp_output, strlen(temp_output));
1835 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001836 return RETURN_OK;
1837}
1838
1839//Get the radio operating mode, and pure mode flag. eg: "ac"
1840//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.
1841INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1842{
1843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1844 if (NULL == output_string)
1845 return RETURN_ERR;
1846
1847 if (radioIndex == 0) {
1848 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1849 *gOnly = FALSE;
1850 *nOnly = TRUE;
1851 *acOnly = FALSE;
1852 } else {
1853 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1854 *gOnly = FALSE;
1855 *nOnly = FALSE;
1856 *acOnly = FALSE;
1857 }
1858 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1859
1860 return RETURN_OK;
1861#if 0
1862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1863 char buf[64] = {0};
1864 char config_file[MAX_BUF_SIZE] = {0};
1865
1866 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1867 return RETURN_ERR;
1868
1869 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1870 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1871
1872 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1873 if (strlen(buf) == 0)
1874 {
1875 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1876 return RETURN_ERR;
1877 }
1878 if(strcmp(buf,"g")==0)
1879 {
1880 wifi_dbg_printf("\nG\n");
1881 *gOnly=TRUE;
1882 *nOnly=FALSE;
1883 *acOnly=FALSE;
1884 }
1885 else if(strcmp(buf,"n")==0)
1886 {
1887 wifi_dbg_printf("\nN\n");
1888 *gOnly=FALSE;
1889 *nOnly=TRUE;
1890 *acOnly=FALSE;
1891 }
1892 else if(strcmp(buf,"ac")==0)
1893 {
1894 wifi_dbg_printf("\nac\n");
1895 *gOnly=FALSE;
1896 *nOnly=FALSE;
1897 *acOnly=TRUE;
1898 }
1899 /* hostapd-5G.conf has "a" as hw_mode */
1900 else if(strcmp(buf,"a")==0)
1901 {
1902 wifi_dbg_printf("\na\n");
1903 *gOnly=FALSE;
1904 *nOnly=FALSE;
1905 *acOnly=FALSE;
1906 }
1907 else
1908 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1909
1910 //for a,n mode
1911 if(radioIndex == 1)
1912 {
1913 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1914 if(strcmp(buf,"1")==0)
1915 {
1916 strncpy(output_string, "n", 1);
1917 *nOnly=FALSE;
1918 }
1919 }
1920
1921 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1922 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1923 return RETURN_OK;
1924#endif
1925}
1926
developerdb744382022-09-13 15:34:54 +08001927INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1928{
1929 char cmd[128] = {0};
1930 char buf[64] = {0};
1931 char config_file[64] = {0};
1932 wifi_band band;
1933
1934 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1935 if(NULL == output_string || NULL == pureMode)
1936 return RETURN_ERR;
1937
1938 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001939 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer7c4cd202023-03-01 10:56:29 +08001940 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 +08001941 _syscmd(cmd, buf, sizeof(buf));
1942
1943 band = wifi_index_to_band(radioIndex);
1944 // puremode is a bit map
1945 *pureMode = 0;
1946 if (band == band_2_4) {
1947 strcat(output_string, "b,g");
1948 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1949 if (strstr(buf, "n") != NULL) {
1950 strcat(output_string, ",n");
1951 *pureMode |= WIFI_MODE_N;
1952 }
1953 if (strstr(buf, "ax") != NULL) {
1954 strcat(output_string, ",ax");
1955 *pureMode |= WIFI_MODE_AX;
1956 }
developer7c4cd202023-03-01 10:56:29 +08001957 if (strstr(buf, "be") != NULL) {
1958 strcat(output_string, ",be");
1959 *pureMode |= WIFI_MODE_BE;
1960 }
developerdb744382022-09-13 15:34:54 +08001961 } else if (band == band_5) {
1962 strcat(output_string, "a");
1963 *pureMode |= WIFI_MODE_A;
1964 if (strstr(buf, "n") != NULL) {
1965 strcat(output_string, ",n");
1966 *pureMode |= WIFI_MODE_N;
1967 }
1968 if (strstr(buf, "ac") != NULL) {
1969 strcat(output_string, ",ac");
1970 *pureMode |= WIFI_MODE_AC;
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_6) {
1981 if (strstr(buf, "ax") != NULL) {
1982 strcat(output_string, "ax");
1983 *pureMode |= WIFI_MODE_AX;
1984 }
developer7c4cd202023-03-01 10:56:29 +08001985 if (strstr(buf, "be") != NULL) {
1986 strcat(output_string, ",be");
1987 *pureMode |= WIFI_MODE_BE;
1988 }
developerdb744382022-09-13 15:34:54 +08001989 }
1990
1991 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1992 return RETURN_OK;
1993}
1994
1995// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001996INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1997{
1998 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1999 if (strcmp (channelMode,"11A") == 0)
2000 {
2001 writeBandWidth(radioIndex,"20MHz");
2002 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2003 printf("\nChannel Mode is 802.11a (5GHz)\n");
2004 }
2005 else if (strcmp (channelMode,"11NAHT20") == 0)
2006 {
2007 writeBandWidth(radioIndex,"20MHz");
2008 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2009 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2010 }
2011 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2012 {
2013 writeBandWidth(radioIndex,"40MHz");
2014 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2015 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2016 }
2017 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2018 {
2019 writeBandWidth(radioIndex,"40MHz");
2020 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2021 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2022 }
2023 else if (strcmp (channelMode,"11ACVHT20") == 0)
2024 {
2025 writeBandWidth(radioIndex,"20MHz");
2026 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2027 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2028 }
2029 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2030 {
2031 writeBandWidth(radioIndex,"40MHz");
2032 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2033 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2034 }
2035 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2036 {
2037 writeBandWidth(radioIndex,"40MHz");
2038 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2039 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2040 }
2041 else if (strcmp (channelMode,"11ACVHT80") == 0)
2042 {
2043 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2044 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2045 }
2046 else if (strcmp (channelMode,"11ACVHT160") == 0)
2047 {
2048 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2049 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2050 }
2051 else if (strcmp (channelMode,"11B") == 0)
2052 {
2053 writeBandWidth(radioIndex,"20MHz");
2054 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2055 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2056 }
2057 else if (strcmp (channelMode,"11G") == 0)
2058 {
2059 writeBandWidth(radioIndex,"20MHz");
2060 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2061 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2062 }
2063 else if (strcmp (channelMode,"11NGHT20") == 0)
2064 {
2065 writeBandWidth(radioIndex,"20MHz");
2066 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2067 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2068 }
2069 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2070 {
2071 writeBandWidth(radioIndex,"40MHz");
2072 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2073 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2074 }
2075 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2076 {
2077 writeBandWidth(radioIndex,"40MHz");
2078 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2079 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2080 }
2081 else
2082 {
2083 return RETURN_ERR;
2084 }
2085 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2086
2087 return RETURN_OK;
2088}
2089
developerdb744382022-09-13 15:34:54 +08002090// Set the radio operating mode, and pure mode flag.
2091INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2092{
developer7c4cd202023-03-01 10:56:29 +08002093 int num_hostapd_support_mode = 4; // n, ac, ax, be
developerdb744382022-09-13 15:34:54 +08002094 struct params list[num_hostapd_support_mode];
2095 char config_file[64] = {0};
2096 char bandwidth[16] = {0};
developer7c4cd202023-03-01 10:56:29 +08002097 char supported_mode[32] = {0};
developerdb744382022-09-13 15:34:54 +08002098 int mode_check_bit = 1 << 3; // n mode
developer7c4cd202023-03-01 10:56:29 +08002099 bool eht_support = FALSE;
developerdb744382022-09-13 15:34:54 +08002100
2101 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2102 // Set radio mode
2103 list[0].name = "ieee80211n";
2104 list[1].name = "ieee80211ac";
2105 list[2].name = "ieee80211ax";
developer7c4cd202023-03-01 10:56:29 +08002106 list[3].name = "ieee80211be";
developerdb744382022-09-13 15:34:54 +08002107 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2108
2109 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002110 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002111 list[0].value = "1";
2112 else
2113 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002114 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002115 list[1].value = "1";
2116 else
2117 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002118 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002119 list[2].value = "1";
2120 else
2121 list[2].value = "0";
developer7c4cd202023-03-01 10:56:29 +08002122 if (pureMode & WIFI_MODE_BE)
2123 list[3].value = "1";
2124 else
2125 list[3].value = "0";
2126
2127 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2128 if (strstr(supported_mode, "be") != NULL)
2129 eht_support = TRUE;
2130
2131 if (eht_support)
2132 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2133 else
2134 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode-1);
developerdb744382022-09-13 15:34:54 +08002135
2136 if (channelMode == NULL || strlen(channelMode) == 0)
2137 return RETURN_OK;
2138 // Set bandwidth
2139 if (strstr(channelMode, "40") != NULL)
2140 strcpy(bandwidth, "40MHz");
2141 else if (strstr(channelMode, "80") != NULL)
2142 strcpy(bandwidth, "80MHz");
2143 else if (strstr(channelMode, "160") != NULL)
2144 strcpy(bandwidth, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002145 else if (strstr(channelMode, "320") != NULL)
2146 strcpy(bandwidth, "320MHz");
developerdb744382022-09-13 15:34:54 +08002147 else // 11A, 11B, 11G....
2148 strcpy(bandwidth, "20MHz");
2149
2150 writeBandWidth(radioIndex, bandwidth);
2151 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2152
2153 wifi_reloadAp(radioIndex);
2154 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2155
2156 return RETURN_OK;
2157}
2158
developer1d12ebf2022-10-04 15:13:38 +08002159INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2160
2161 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002162 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002163 struct params params = {0};
2164 wifi_band band = band_invalid;
2165
2166 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2167
2168 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002169
2170 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002171 return RETURN_ERR;
2172 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2173 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002174 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2175 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002176
2177 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2178 params.name = "hw_mode";
2179 params.value = hw_mode;
2180 wifi_hostapdWrite(config_file, &params, 1);
2181 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2182
developeref938762022-10-19 17:21:01 +08002183 if (band == band_2_4) {
2184 if (strncmp(hw_mode, "b", 1) == 0) {
2185 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2186 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2187 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2188 snprintf(buf, sizeof(buf), "%s", "1,2");
2189 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2190 } else {
2191 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2192
2193 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2194 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2195 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2196 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2197 }
2198 }
2199
developer1d12ebf2022-10-04 15:13:38 +08002200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2201 return RETURN_OK;
2202}
2203
developere8988ba2022-10-18 17:42:30 +08002204INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2205{
2206 char config_file[64] = {0};
2207 struct params params = {0};
2208 wifi_band band = band_invalid;
2209
2210 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2211
2212 band = wifi_index_to_band(radioIndex);
2213
2214 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2215 params.name = "noscan";
2216 params.value = noscan;
2217 wifi_hostapdWrite(config_file, &params, 1);
2218 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2219
2220 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2221 return RETURN_OK;
2222}
2223
developer06a01d92022-09-07 16:32:39 +08002224//Get the list of supported channel. eg: "1-11"
2225//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.
2226INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2227{
developer6318ed52022-09-13 15:17:58 +08002228 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002229 if (NULL == output_string)
2230 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002231 char cmd[256] = {0};
2232 char buf[128] = {0};
2233 BOOL dfs_enable = false;
developer63a1ef02024-05-03 16:59:38 +08002234 int phyId = 0, band_remap = 0, range_remap = 0;
2235 wifi_band band = band_invalid;
developer033b37b2022-10-18 11:27:46 +08002236
developer63a1ef02024-05-03 16:59:38 +08002237 band = wifi_index_to_band(radioIndex);
2238 switch (band) {
2239 case band_2_4:
2240 band_remap = 1;
2241 range_remap = 2;
2242 break;
2243 case band_5:
2244 band_remap = 2;
2245 range_remap = 4;
2246 break;
2247 case band_6:
2248 band_remap = 4;
2249 range_remap = 4;
2250 break;
2251 default:
2252 break;
2253 }
developer6318ed52022-09-13 15:17:58 +08002254 // Parse possible channel number and separate them with commas.
2255 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002256 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002257 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002258 if (dfs_enable)
developer63a1ef02024-05-03 16:59:38 +08002259 snprintf(cmd, sizeof(cmd),
2260 "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/.$//'",
2261 phyId, band_remap, range_remap, band_remap, range_remap);
developer6318ed52022-09-13 15:17:58 +08002262 else
developer63a1ef02024-05-03 16:59:38 +08002263 snprintf(cmd, sizeof(cmd),
2264 "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/.$//'",
2265 phyId, band_remap, range_remap, band_remap, range_remap);
developer6318ed52022-09-13 15:17:58 +08002266
2267 _syscmd(cmd,buf,sizeof(buf));
2268 strncpy(output_string, buf, sizeof(buf));
2269
2270 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2271 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002272}
2273
2274//Get the list for used channel. eg: "1,6,9,11"
2275//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.
2276INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2277{
developerd946fd62022-12-08 18:03:28 +08002278 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002279 char cmd[128] = {0};
2280 char buf[128] = {0};
2281 char config_file[64] = {0};
2282 int channel = 0;
2283 int freq = 0;
2284 int bandwidth = 0;
2285 int center_freq = 0;
2286 int center_channel = 0;
2287 int channel_delta = 0;
2288 wifi_band band = band_invalid;
2289
2290 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2291
developer06a01d92022-09-07 16:32:39 +08002292 if (NULL == output_string)
2293 return RETURN_ERR;
2294
developerac6f1142022-12-20 19:26:35 +08002295 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002296 return RETURN_ERR;
2297 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002298 _syscmd(cmd, buf, sizeof(buf));
2299 if (strlen(buf) == 0) {
2300 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2301 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002302 }
developerf5745ee2022-10-05 16:09:53 +08002303 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2304
2305 if (bandwidth == 20) {
2306 snprintf(output_string, 256, "%d", channel);
2307 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002308 }
developerf5745ee2022-10-05 16:09:53 +08002309
2310 center_channel = ieee80211_frequency_to_channel(center_freq);
2311
2312 band = wifi_index_to_band(radioIndex);
2313 if (band == band_2_4 && bandwidth == 40) {
2314 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2315 memset(buf, 0, sizeof(buf));
2316 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2317
developerf22724d2022-12-22 17:24:14 +08002318 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002319 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002320 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002321 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2322 } else {
2323 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2324 return RETURN_ERR;
2325 }
2326 } else if (band == band_5 || band == band_6){
2327 // 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 +08002328 // 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 +08002329 channel_delta = (bandwidth-20)/10;
developer72ec5572023-01-05 16:27:13 +08002330 memset(output_string, 0, 256);
2331 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2332 // If i is not the last channel, we add a comma.
2333 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2334 strncat(output_string, buf, strlen(buf));
2335 }
developerf5745ee2022-10-05 16:09:53 +08002336 } else
2337 return RETURN_ERR;
2338
2339 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002340 return RETURN_OK;
2341}
2342
2343//Get the running channel number
2344INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2345{
developer5b398df2022-11-17 20:39:48 +08002346 char channel_str[16] = {0};
2347 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002348
developer5b398df2022-11-17 20:39:48 +08002349 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002350 return RETURN_ERR;
2351
developer5b398df2022-11-17 20:39:48 +08002352 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2353 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002354
developer5b398df2022-11-17 20:39:48 +08002355 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002356
developer06a01d92022-09-07 16:32:39 +08002357 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002358}
2359
2360
2361INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2362{
2363 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002364 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002365
2366 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2367 if (NULL == output_ulong)
2368 return RETURN_ERR;
2369
developer06a01d92022-09-07 16:32:39 +08002370 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002371 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2372 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002373 _syscmd(cmd,buf,sizeof(buf));
2374 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2375 if (*output_ulong == 0) {
2376 return RETURN_ERR;
2377 }
2378
2379 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2380 return RETURN_OK;
2381}
2382
2383//Storing the previous channel value
2384INT wifi_storeprevchanval(INT radioIndex)
2385{
2386 char buf[256] = {0};
2387 char output[4]={'\0'};
2388 char config_file[MAX_BUF_SIZE] = {0};
2389 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2390 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2391 if(radioIndex == 0)
2392 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2393 else if(radioIndex == 1)
2394 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2395 system(buf);
2396 Radio_flag = FALSE;
2397 return RETURN_OK;
2398}
2399
2400//Set the running channel number
2401INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2402{
developer76989232022-10-04 14:13:19 +08002403 // We only write hostapd config here
2404 char str_channel[8]={0};
2405 char *list_channel;
2406 char config_file[128] = {0};
2407 char possible_channels[256] = {0};
2408 int max_radio_num = 0;
2409 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002410
developer76989232022-10-04 14:13:19 +08002411 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002412
developer76989232022-10-04 14:13:19 +08002413 // Check valid
2414 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002415
developer76989232022-10-04 14:13:19 +08002416 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2417 list_channel = strtok(possible_channels, ",");
2418 while(true)
developer06a01d92022-09-07 16:32:39 +08002419 {
developer76989232022-10-04 14:13:19 +08002420 if(list_channel == NULL) { // input not in the list
2421 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2422 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002423 }
developer76989232022-10-04 14:13:19 +08002424 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2425 break;
2426 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002427 }
2428
developer76989232022-10-04 14:13:19 +08002429 list.name = "channel";
2430 list.value = str_channel;
2431 wifi_getMaxRadioNumber(&max_radio_num);
2432 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002433 {
developer76989232022-10-04 14:13:19 +08002434 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2435 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002436 }
2437
developer76989232022-10-04 14:13:19 +08002438 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002439 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002440}
developer06a01d92022-09-07 16:32:39 +08002441
2442INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2443{
developer7c4cd202023-03-01 10:56:29 +08002444 struct params list[3];
2445 char str_idx[16] = {0};
2446 char supported_mode[32] = {0};
2447 char config_file[64] = {0};
developer76989232022-10-04 14:13:19 +08002448 int max_num_radios = 0;
2449 wifi_band band = band_invalid;
developer7c4cd202023-03-01 10:56:29 +08002450 bool eht_support = FALSE;
developer76989232022-10-04 14:13:19 +08002451
2452 band = wifi_index_to_band(radioIndex);
2453 if (band == band_2_4)
2454 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002455
developer7c4cd202023-03-01 10:56:29 +08002456 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2457 if (strstr(supported_mode, "be") != NULL)
2458 eht_support = TRUE;
2459
developer30423732022-12-01 16:17:49 +08002460 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002461 list[0].name = "vht_oper_centr_freq_seg0_idx";
2462 list[0].value = str_idx;
2463 list[1].name = "he_oper_centr_freq_seg0_idx";
2464 list[1].value = str_idx;
developer7c4cd202023-03-01 10:56:29 +08002465 list[2].name = "eht_oper_centr_freq_seg0_idx";
2466 list[2].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002467
developer76989232022-10-04 14:13:19 +08002468 wifi_getMaxRadioNumber(&max_num_radios);
2469 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002470 {
developer76989232022-10-04 14:13:19 +08002471 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
developer7c4cd202023-03-01 10:56:29 +08002472 if (eht_support)
2473 wifi_hostapdWrite(config_file, list, 3);
developer76989232022-10-04 14:13:19 +08002474 else
2475 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002476 }
2477
2478 return RETURN_OK;
2479}
2480
2481//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2482//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2483INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2484{
2485 //Set to wifi config only. Wait for wifi reset to apply.
2486 char buf[256] = {0};
2487 char str_channel[256] = {0};
2488 int count = 0;
2489 ULONG Value = 0;
2490 FILE *fp = NULL;
2491 if(enable == TRUE)
2492 {
developer06a01d92022-09-07 16:32:39 +08002493 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002494 }
developer5884e982022-10-06 10:52:50 +08002495 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002496}
2497
developer0b246d12022-09-30 15:24:20 +08002498INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2499{
2500 if (output_bool == NULL)
2501 return RETURN_ERR;
2502
2503 *output_bool = TRUE;
2504
2505 return RETURN_OK;
2506}
2507
developer06a01d92022-09-07 16:32:39 +08002508INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2509{
2510 if (NULL == output_bool)
2511 return RETURN_ERR;
2512 *output_bool=FALSE;
2513 return RETURN_OK;
2514}
2515
2516INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2517{
2518 if (NULL == output_bool)
2519 return RETURN_ERR;
2520 *output_bool=FALSE;
2521 return RETURN_OK;
2522}
2523
2524INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2525{
2526 //Set to wifi config only. Wait for wifi reset to apply.
2527 return RETURN_OK;
2528}
2529
2530INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2531{
2532 return RETURN_OK;
2533}
2534
2535INT wifi_factoryResetAP(int apIndex)
2536{
developer838cca92022-10-03 13:19:57 +08002537 char ap_config_file[64] = {0};
2538 char cmd[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002539 char buf[128] = {0};
developer89df4502023-02-16 20:45:02 +08002540 int max_radio_num = 0;
developer838cca92022-10-03 13:19:57 +08002541
developer06a01d92022-09-07 16:32:39 +08002542 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002543
2544 wifi_setApEnable(apIndex, FALSE);
2545 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2546 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
developer72ec5572023-01-05 16:27:13 +08002547 _syscmd(cmd, buf, sizeof(buf));
developer89df4502023-02-16 20:45:02 +08002548 wifi_getMaxRadioNumber(&max_radio_num);
2549 if (apIndex <= max_radio_num) // The ap is default radio interface, we should default up it.
2550 wifi_setApEnable(apIndex, TRUE);
developer838cca92022-10-03 13:19:57 +08002551
developer06a01d92022-09-07 16:32:39 +08002552 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002553
developer06a01d92022-09-07 16:32:39 +08002554 return RETURN_OK;
2555}
2556
2557//To set Band Steering AP group
2558//To-do
2559INT wifi_setBandSteeringApGroup(char *ApGroup)
2560{
2561 return RETURN_OK;
2562}
2563
developer1e5aa162022-09-13 16:06:24 +08002564INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2565{
2566 char config_file[128] = {'\0'};
2567 char buf[128] = {'\0'};
2568
2569 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2570 if (dtimInterval == NULL)
2571 return RETURN_ERR;
2572
2573 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2574 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2575
2576 if (strlen(buf) == 0) {
2577 *dtimInterval = 2;
2578 } else {
2579 *dtimInterval = strtoul(buf, NULL, 10);
2580 }
2581
2582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2583 return RETURN_OK;
2584}
2585
developer06a01d92022-09-07 16:32:39 +08002586INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2587{
developer5f222492022-09-13 15:21:52 +08002588 struct params params={0};
2589 char config_file[MAX_BUF_SIZE] = {'\0'};
2590 char buf[MAX_BUF_SIZE] = {'\0'};
2591
2592 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2593 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002594 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002595 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002596 }
2597
2598 params.name = "dtim_period";
2599 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2600 params.value = buf;
2601
2602 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2603 wifi_hostapdWrite(config_file, &params, 1);
2604 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2605
2606 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2607 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002608}
2609
2610//Check if the driver support the Dfs
2611INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2612{
developer78a15382022-11-02 10:57:40 +08002613 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002614 if (NULL == output_bool)
2615 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002616 *output_bool=FALSE;
2617
2618 band = wifi_index_to_band(radioIndex);
2619 if (band == band_5)
2620 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002621 return RETURN_OK;
2622}
2623
2624//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.
2625//The value of this parameter is a comma seperated list of channel number
2626INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2627{
2628 if (NULL == output_pool)
2629 return RETURN_ERR;
2630 if (radioIndex==1)
2631 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2632 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2633
2634 return RETURN_OK;
2635}
2636
2637INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2638{
2639 //Set to wifi config. And apply instantly.
2640 return RETURN_OK;
2641}
2642
2643INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2644{
2645 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2646 return RETURN_ERR;
2647 *output_interval_seconds=1800;
2648 *output_dwell_milliseconds=40;
2649
2650 return RETURN_OK;
2651}
2652
2653INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2654{
2655 //Set to wifi config. And apply instantly.
2656 return RETURN_OK;
2657}
2658
developerbfc18512022-10-05 17:54:28 +08002659INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2660{
2661 if (output_bool == NULL)
2662 return RETURN_ERR;
2663 *output_bool = true;
2664 return RETURN_OK;
2665}
2666
2667INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2668{
2669 return RETURN_OK;
2670}
2671
developer06a01d92022-09-07 16:32:39 +08002672//Get the Dfs enable status
2673INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2674{
developer9964b5b2022-09-13 15:59:34 +08002675 char buf[16] = {0};
2676 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002677
2678 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2679
developer30423732022-12-01 16:17:49 +08002680 if (output_bool == NULL)
2681 return RETURN_ERR;
2682
developer9964b5b2022-09-13 15:59:34 +08002683 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002684 f = fopen(DFS_ENABLE_FILE, "r");
2685 if (f != NULL) {
2686 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002687 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002688 *output_bool = FALSE;
2689 fclose(f);
2690 }
2691 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002692 return RETURN_OK;
2693}
2694
2695//Set the Dfs enable status
2696INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2697{
developer9964b5b2022-09-13 15:59:34 +08002698 char config_file[128] = {0};
2699 FILE *f = NULL;
2700 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002701
2702 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2703
developer9964b5b2022-09-13 15:59:34 +08002704 f = fopen(DFS_ENABLE_FILE, "w");
2705 if (f == NULL)
2706 return RETURN_ERR;
2707 fprintf(f, "%d", enable);
2708 fclose(f);
2709
2710 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002711 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002712 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2713 wifi_hostapdWrite(config_file, &params, 1);
2714 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2715
2716 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2717
developer9964b5b2022-09-13 15:59:34 +08002718 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002719 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002720}
2721
2722//Check if the driver support the AutoChannelRefreshPeriod
2723INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2724{
2725 if (NULL == output_bool)
2726 return RETURN_ERR;
2727 *output_bool=FALSE; //not support
2728
2729 return RETURN_OK;
2730}
2731
2732//Get the ACS refresh period in seconds
2733INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2734{
2735 if (NULL == output_ulong)
2736 return RETURN_ERR;
2737 *output_ulong=300;
2738
2739 return RETURN_OK;
2740}
2741
2742//Set the ACS refresh period in seconds
2743INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2744{
2745 return RETURN_ERR;
2746}
2747
developer7c4cd202023-03-01 10:56:29 +08002748INT getEHT320ChannelBandwidthSet(int radioIndex, int *BandwidthSet)
2749{
2750 int center_channel = 0;
2751 char config_file[32] = {0};
2752 char buf[32] = {0};
2753
2754 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2755 wifi_hostapdRead(config_file, "eht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2756
2757 center_channel = strtoul(buf, NULL, 10);
2758 center_channel += 1; // Add 1 to become muiltiple of 16
2759 if (center_channel % 64 == 32)
2760 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_1MHZ;
2761 else if (center_channel % 64 == 0)
2762 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_2MHZ;
2763 else
2764 return RETURN_ERR;
2765 return RETURN_OK;
2766}
2767
developer06a01d92022-09-07 16:32:39 +08002768//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2769//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.
2770INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2771{
developer72ec5572023-01-05 16:27:13 +08002772 char buf[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002773 char extchannel[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002774 char config_file[128] = {0};
developer70490032022-09-13 15:45:20 +08002775 BOOL radio_enable = FALSE;
developerfa41b1f2023-01-06 10:25:51 +08002776 wifi_band band;
developer70490032022-09-13 15:45:20 +08002777
2778 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2779
developer06a01d92022-09-07 16:32:39 +08002780 if (NULL == output_string)
2781 return RETURN_ERR;
2782
developer70490032022-09-13 15:45:20 +08002783 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2784 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002785
developer70490032022-09-13 15:45:20 +08002786 if (radio_enable != TRUE)
2787 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002788
developerfa41b1f2023-01-06 10:25:51 +08002789 band = wifi_index_to_band(radioIndex);
developer72ec5572023-01-05 16:27:13 +08002790 if (band == band_2_4) {
developerfa41b1f2023-01-06 10:25:51 +08002791 wifi_getRadioExtChannel(radioIndex, extchannel);
developer72ec5572023-01-05 16:27:13 +08002792 if (strncmp(extchannel, "Auto", 4) == 0) // Auto means that we did not set ht_capab HT40+/-
2793 snprintf(output_string, 64, "20MHz");
2794 else
2795 snprintf(output_string, 64, "40MHz");
2796
2797 } else {
2798 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2799 wifi_hostapdRead(config_file, "he_oper_chwidth", buf, sizeof(buf));
2800 if (strncmp(buf, "0", 1) == 0) { // Check whether we set central channel
2801 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2802 if (strncmp(buf, "0", 1) == 0)
2803 snprintf(output_string, 64, "20MHz");
2804 else
2805 snprintf(output_string, 64, "40MHz");
2806
2807 } else if (strncmp(buf, "1", 1) == 0)
2808 snprintf(output_string, 64, "80MHz");
developer7c4cd202023-03-01 10:56:29 +08002809 else if (strncmp(buf, "2", 1) == 0) {
developer72ec5572023-01-05 16:27:13 +08002810 snprintf(output_string, 64, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002811 wifi_hostapdRead(config_file, "eht_oper_chwidth", buf, sizeof(buf));
2812 if (strncmp(buf, "9", 1) == 0) {
2813 int BandwidthSet = 0;
2814 if (getEHT320ChannelBandwidthSet(radioIndex, &BandwidthSet) != RETURN_OK)
2815 return RETURN_ERR;
2816 if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_1MHZ)
2817 snprintf(output_string, 64, "320-1MHz");
2818 else if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_2MHZ)
2819 snprintf(output_string, 64, "320-2MHz");
2820 }
2821 }
developer06a01d92022-09-07 16:32:39 +08002822 }
developer72ec5572023-01-05 16:27:13 +08002823
developer06a01d92022-09-07 16:32:39 +08002824 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002825
2826 return RETURN_OK;
2827}
2828
2829//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002830INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002831{
developerf7a466e2022-09-29 11:55:56 +08002832 char config_file[128];
2833 char set_value[16];
developer7c4cd202023-03-01 10:56:29 +08002834 char supported_mode[32] = {0};
2835 struct params params[3];
developerf7a466e2022-09-29 11:55:56 +08002836 int max_radio_num = 0;
developer7c4cd202023-03-01 10:56:29 +08002837 bool eht_support = FALSE;
developerf7a466e2022-09-29 11:55:56 +08002838
developer06a01d92022-09-07 16:32:39 +08002839 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002840
developerf7a466e2022-09-29 11:55:56 +08002841 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002842 return RETURN_ERR;
2843
developer7c4cd202023-03-01 10:56:29 +08002844 if(strstr(bandwidth,"160") != NULL || strstr(bandwidth,"320") != NULL)
developerf7a466e2022-09-29 11:55:56 +08002845 strcpy(set_value, "2");
2846 else if(strstr(bandwidth,"80") != NULL)
2847 strcpy(set_value, "1");
2848 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2849 strcpy(set_value, "0");
developer72ec5572023-01-05 16:27:13 +08002850 else if (strstr(bandwidth, "Auto") != NULL)
2851 return RETURN_OK;
2852 else {
developerf7a466e2022-09-29 11:55:56 +08002853 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002854 return RETURN_ERR;
2855 }
2856
developer7c4cd202023-03-01 10:56:29 +08002857 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2858 if (strstr(supported_mode, "be") != NULL)
2859 eht_support = TRUE;
2860
developerf7a466e2022-09-29 11:55:56 +08002861 params[0].name = "vht_oper_chwidth";
2862 params[0].value = set_value;
2863 params[1].name = "he_oper_chwidth";
2864 params[1].value = set_value;
developer7c4cd202023-03-01 10:56:29 +08002865 params[2].name = "eht_oper_chwidth";
2866 if (strstr(bandwidth,"320") != NULL) // We set oper_chwidth to 9 for EHT320
2867 params[2].value = "9";
2868 else
2869 params[2].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002870
developerf7a466e2022-09-29 11:55:56 +08002871 wifi_getMaxRadioNumber(&max_radio_num);
2872 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002873 {
developer7c4cd202023-03-01 10:56:29 +08002874 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2875 if (eht_support == TRUE)
2876 wifi_hostapdWrite(config_file, params, 3);
2877 else
2878 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002879 }
2880
2881 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2882 return RETURN_OK;
2883}
2884
2885//Getting current radio extension channel
2886INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2887{
2888 CHAR buf[150] = {0};
2889 CHAR cmd[150] = {0};
2890 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2891 _syscmd(cmd, buf, sizeof(buf));
2892 if(NULL != strstr(buf,"HT40+"))
2893 strcpy(Value,"AboveControlChannel");
2894 else if(NULL != strstr(buf,"HT40-"))
2895 strcpy(Value,"BelowControlChannel");
2896 return RETURN_OK;
2897}
2898
2899//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2900//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.
2901INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2902{
developerfa41b1f2023-01-06 10:25:51 +08002903 char config_file[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002904 wifi_band band;
developerfa41b1f2023-01-06 10:25:51 +08002905
2906 if (output_string == NULL)
developer06a01d92022-09-07 16:32:39 +08002907 return RETURN_ERR;
2908
developerfa41b1f2023-01-06 10:25:51 +08002909 band = wifi_index_to_band(radioIndex);
2910 if (band == band_invalid)
developer06a01d92022-09-07 16:32:39 +08002911 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002912
2913 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2914
2915 snprintf(output_string, 64, "Auto");
developer72ec5572023-01-05 16:27:13 +08002916 wifi_halgetRadioExtChannel(config_file, output_string);
developer06a01d92022-09-07 16:32:39 +08002917
2918 return RETURN_OK;
2919}
2920
developer57fa24a2023-03-15 17:25:07 +08002921// This function handle 20MHz to remove HT40+/- in hostapd config, other bandwidths are handled in wifi_setRadioExtChannel.
2922INT wifi_RemoveRadioExtChannel(INT radioIndex, CHAR *ext_str)
2923{
2924 struct params params={0};
2925 char config_file[64] = {0};
2926 char ht_capab[128]={0};
2927 char buf[128] = {0};
2928 char cmd[128] = {0};
2929 int max_radio_num =0;
2930 bool stbcEnable = FALSE;
2931
2932 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2933 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2934 _syscmd(cmd, buf, sizeof(buf));
2935 if (strlen(buf) != 0)
2936 stbcEnable = TRUE;
2937
2938 strcpy(ht_capab, HOSTAPD_HT_CAPAB);
2939 params.value = ht_capab;
2940 params.name = "ht_capab";
2941
2942 wifi_getMaxRadioNumber(&max_radio_num);
2943 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2944 {
2945 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2946 wifi_hostapdWrite(config_file, &params, 1);
developer57fa24a2023-03-15 17:25:07 +08002947 }
developer8d7d0862023-05-18 16:50:23 +08002948 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer57fa24a2023-03-15 17:25:07 +08002949 return RETURN_OK;
2950}
2951
developer06a01d92022-09-07 16:32:39 +08002952//Set the extension channel.
2953INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer72ec5572023-01-05 16:27:13 +08002954{
developer06a01d92022-09-07 16:32:39 +08002955 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfa41b1f2023-01-06 10:25:51 +08002956 struct params params={0};
2957 char config_file[64] = {0};
2958 char ext_channel[128]={0};
2959 char buf[128] = {0};
2960 char cmd[128] = {0};
2961 int max_radio_num =0, ret = 0, bandwidth = 0;
developer72ec5572023-01-05 16:27:13 +08002962 unsigned long channel = 0;
developerfa41b1f2023-01-06 10:25:51 +08002963 bool stbcEnable = FALSE;
developer06a01d92022-09-07 16:32:39 +08002964 params.name = "ht_capab";
developerfa41b1f2023-01-06 10:25:51 +08002965 wifi_band band;
2966
2967 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2968 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2969 _syscmd(cmd, buf, sizeof(buf));
2970 if (strlen(buf) != 0)
2971 stbcEnable = TRUE;
developer57fa24a2023-03-15 17:25:07 +08002972
2973 // readBandWidth get empty file will return error, that means we don't set new bandwidth
2974 if (readBandWidth(radioIndex, buf) != RETURN_OK) {
2975 // Get current bandwidth
2976 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2977 return RETURN_ERR;
2978 }
developerfa41b1f2023-01-06 10:25:51 +08002979 bandwidth = strtol(buf, NULL, 10);
2980 // TDK expected to get error with 20MHz
developer57fa24a2023-03-15 17:25:07 +08002981 // we handle 20MHz in function wifi_RemoveRadioExtChannel().
developerfa41b1f2023-01-06 10:25:51 +08002982 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
2983 return RETURN_ERR;
2984
2985 band = wifi_index_to_band(radioIndex);
2986 if (band == band_invalid)
2987 return RETURN_ERR;
2988
2989 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
2990 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002991
developer72ec5572023-01-05 16:27:13 +08002992 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
2993 ret = util_get_sec_chan_offset(channel, buf);
2994 if (ret == -EINVAL)
2995 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002996
2997 if(NULL!= strstr(string,"Above")) {
developer72ec5572023-01-05 16:27:13 +08002998 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
2999 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08003000 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developerfa41b1f2023-01-06 10:25:51 +08003001 } else if(NULL!= strstr(string,"Below")) {
developer72ec5572023-01-05 16:27:13 +08003002 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == 1))
3003 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08003004 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developerfa41b1f2023-01-06 10:25:51 +08003005 } else {
developer57fa24a2023-03-15 17:25:07 +08003006 fprintf(stderr, "%s: unknow extchannel %s\n", __func__, string);
3007 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08003008 }
developer06a01d92022-09-07 16:32:39 +08003009
3010 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08003011
3012 wifi_getMaxRadioNumber(&max_radio_num);
3013 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08003014 {
developer033b37b2022-10-18 11:27:46 +08003015 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08003016 wifi_hostapdWrite(config_file, &params, 1);
3017 }
developer8d7d0862023-05-18 16:50:23 +08003018 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer06a01d92022-09-07 16:32:39 +08003019
3020 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3021 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3022 return RETURN_OK;
3023}
3024
3025//Get the guard interval value. eg "400nsec" or "800nsec"
3026//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.
3027INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3028{
developer454b9462022-09-13 15:29:16 +08003029 wifi_guard_interval_t GI;
3030
3031 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3032
3033 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08003034 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08003035
3036 if (GI == wifi_guard_interval_400)
3037 strcpy(output_string, "400nsec");
3038 else if (GI == wifi_guard_interval_800)
3039 strcpy(output_string, "800nsec");
3040 else if (GI == wifi_guard_interval_1600)
3041 strcpy(output_string, "1600nsec");
3042 else if (GI == wifi_guard_interval_3200)
3043 strcpy(output_string, "3200nsec");
3044 else
developer78a15382022-11-02 10:57:40 +08003045 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08003046
developer454b9462022-09-13 15:29:16 +08003047 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003048 return RETURN_OK;
3049}
3050
3051//Set the guard interval value.
3052INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3053{
developer454b9462022-09-13 15:29:16 +08003054 wifi_guard_interval_t GI;
3055 int ret = 0;
3056
3057 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3058
3059 if (strcmp(string, "400nsec") == 0)
3060 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08003061 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08003062 GI = wifi_guard_interval_800;
3063 else if (strcmp(string , "1600nsec") == 0)
3064 GI = wifi_guard_interval_1600;
3065 else if (strcmp(string , "3200nsec") == 0)
3066 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08003067 else
3068 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08003069
3070 ret = wifi_setGuardInterval(radioIndex, GI);
3071
3072 if (ret == RETURN_ERR) {
3073 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3074 return RETURN_ERR;
3075 }
3076
3077 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3078 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003079}
3080
3081//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3082INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3083{
developerf49437e2022-09-29 19:58:21 +08003084 char buf[32]={0};
3085 char mcs_file[64] = {0};
3086 char cmd[64] = {0};
3087 int mode_bitmap = 0;
3088
3089 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3090 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08003091 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08003092 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3093
3094 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3095 _syscmd(cmd, buf, sizeof(buf));
3096 if (strlen(buf) > 0)
3097 *output_int = strtol(buf, NULL, 10);
3098 else {
3099 // output the max MCS for the current radio mode
3100 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3101 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3102 return RETURN_ERR;
3103 }
3104 if (mode_bitmap & WIFI_MODE_AX) {
3105 *output_int = 11;
3106 } else if (mode_bitmap & WIFI_MODE_AC) {
3107 *output_int = 9;
3108 } else if (mode_bitmap & WIFI_MODE_N) {
3109 *output_int = 7;
3110 }
3111 }
3112 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003113
3114 return RETURN_OK;
3115}
3116
3117//Set the Modulation Coding Scheme index
3118INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3119{
developerf49437e2022-09-29 19:58:21 +08003120 // 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).
3121 char config_file[64] = {0};
3122 char set_value[16] = {0};
3123 char mcs_file[32] = {0};
3124 wifi_band band = band_invalid;
3125 struct params set_config = {0};
3126 FILE *f = NULL;
3127
3128 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3129
3130 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3131
developer78a15382022-11-02 10:57:40 +08003132 // -1 means auto
3133 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08003134 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3135 return RETURN_ERR;
3136 }
3137
developer78a15382022-11-02 10:57:40 +08003138 if (MCS > 9 || MCS == -1)
3139 strcpy(set_value, "2");
3140 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08003141 strcpy(set_value, "1");
3142 else
developer78a15382022-11-02 10:57:40 +08003143 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08003144
3145 set_config.name = "he_basic_mcs_nss_set";
3146 set_config.value = set_value;
3147
3148 wifi_hostapdWrite(config_file, &set_config, 1);
3149 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3150
3151 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3152 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3153 f = fopen(mcs_file, "w");
3154 if (f == NULL) {
3155 fprintf(stderr, "%s: fopen failed\n", __func__);
3156 return RETURN_ERR;
3157 }
3158 fprintf(f, "%d", MCS);
3159 fclose(f);
3160
3161 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3162 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003163}
3164
3165//Get supported Transmit Power list, eg : "0,25,50,75,100"
3166//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.
3167INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3168{
3169 if (NULL == output_list)
3170 return RETURN_ERR;
developer5c97d532023-09-28 11:19:30 +08003171 snprintf(output_list, 64,"0,12,25,50,75,100");
developer06a01d92022-09-07 16:32:39 +08003172 return RETURN_OK;
3173}
3174
developer5c97d532023-09-28 11:19:30 +08003175// Get current Transmit Power in percent
developer06a01d92022-09-07 16:32:39 +08003176INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3177{
developer5c97d532023-09-28 11:19:30 +08003178 char cmd[128]={'\0'};
3179 char buf[128]={'\0'};
3180 int phyIndex = -1;
3181 bool enabled = false;
3182 int cur_tx_dbm = 0;
3183
developera5005b62022-09-13 15:43:35 +08003184 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003185
developera5005b62022-09-13 15:43:35 +08003186 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003187 return RETURN_ERR;
3188
developer5c97d532023-09-28 11:19:30 +08003189 phyIndex = radio_index_to_phy(radioIndex);
3190
3191 // Get the maximum tx power of the device
3192 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
developer439baa32024-05-02 15:54:58 +08003193 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", single_wiphy ? radioIndex : phyIndex);
developer06a01d92022-09-07 16:32:39 +08003194 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003195 if (strcmp(buf, "enable") == 0)
3196 enabled = true;
developer06a01d92022-09-07 16:32:39 +08003197
developer5c97d532023-09-28 11:19:30 +08003198 if (!enabled) {
3199 *output_ulong = 100;
3200 return RETURN_OK;
3201 }
developera5005b62022-09-13 15:43:35 +08003202
developer5c97d532023-09-28 11:19:30 +08003203 memset(cmd, 0, sizeof(cmd));
3204 memset(buf, 0, sizeof(buf));
3205 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
developer439baa32024-05-02 15:54:58 +08003206 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", single_wiphy ? radioIndex : phyIndex);
developer5c97d532023-09-28 11:19:30 +08003207 _syscmd(cmd, buf, sizeof(buf));
3208 cur_tx_dbm = strtol(buf, NULL, 10);
3209
3210 switch (cur_tx_dbm) {
3211 case 0:
3212 *output_ulong = 100; // range 91-100
3213 break;
3214 case 1:
3215 *output_ulong = 75; // range 61-90
3216 break;
3217 case 3:
3218 *output_ulong = 50; // range 31-60
3219 break;
3220 case 6:
3221 *output_ulong = 25; // range 16-30
3222 break;
3223 case 9:
3224 *output_ulong = 12; // range 10-15
3225 break;
3226 case 12:
3227 *output_ulong = 6; // range 1-9
3228 break;
3229 default:
3230 *output_ulong = 100; // 0
3231 }
3232
developer06a01d92022-09-07 16:32:39 +08003233 return RETURN_OK;
3234}
3235
developer5c97d532023-09-28 11:19:30 +08003236// TransmitPower: the the percentage relative to the maximum power,
3237// only support 0,12,25,50,75,100, But 0 means disable Power limit,
3238// so the power is 100%
developer06a01d92022-09-07 16:32:39 +08003239INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3240{
developerd946fd62022-12-08 18:03:28 +08003241 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003242 char *support;
developer06a01d92022-09-07 16:32:39 +08003243 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003244 char buf[128]={0};
3245 char txpower_str[64] = {0};
developer033b37b2022-10-18 11:27:46 +08003246 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003247
3248 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003249
developerac6f1142022-12-20 19:26:35 +08003250 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003251 return RETURN_ERR;
developera5005b62022-09-13 15:43:35 +08003252
3253 // Get the Tx power supported list and check that is the input in the list
3254 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3255 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3256 support = strtok(buf, ",");
3257 while(true)
3258 {
3259 if(support == NULL) { // input not in the list
3260 wifi_dbg_printf("Input value is invalid.\n");
3261 return RETURN_ERR;
3262 }
3263 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3264 break;
3265 }
3266 support = strtok(NULL, ",");
3267 }
developer5c97d532023-09-28 11:19:30 +08003268
developer033b37b2022-10-18 11:27:46 +08003269 phyId = radio_index_to_phy(radioIndex);
developer5c97d532023-09-28 11:19:30 +08003270 snprintf(cmd, sizeof(cmd), "echo %lu > /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_level",
developer439baa32024-05-02 15:54:58 +08003271 TransmitPower, single_wiphy ? radioIndex : phyId);
developera5005b62022-09-13 15:43:35 +08003272 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003273
developera5005b62022-09-13 15:43:35 +08003274 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003275
3276 return RETURN_OK;
3277}
3278
3279//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3280INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3281{
3282 if (NULL == Supported)
3283 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003284 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003285
3286 return RETURN_OK;
3287}
3288
3289//Get 80211h feature enable
3290INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3291{
developer3885fec2022-09-13 15:13:47 +08003292 char buf[64]={'\0'};
3293 char config_file[64] = {'\0'};
3294
3295 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3296 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003297 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003298
3299 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3300 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003301
developer3885fec2022-09-13 15:13:47 +08003302 if (strncmp(buf, "1", 1) == 0)
3303 *enable = TRUE;
3304 else
3305 *enable = FALSE;
3306
3307 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003308 return RETURN_OK;
3309}
3310
3311//Set 80211h feature enable
3312INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3313{
developer3885fec2022-09-13 15:13:47 +08003314 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3315 struct params params={'\0'};
3316 char config_file[MAX_BUF_SIZE] = {0};
3317
3318 params.name = "ieee80211h";
3319
3320 if (enable) {
3321 params.value = "1";
3322 } else {
3323 params.value = "0";
3324 }
3325
3326 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3327 wifi_hostapdWrite(config_file, &params, 1);
3328
3329 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3330 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3331 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003332}
3333
3334//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.
3335INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3336{
3337 if (NULL == output)
3338 return RETURN_ERR;
3339 *output=100;
3340
3341 return RETURN_OK;
3342}
3343
3344//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.
3345INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3346{
3347 if (NULL == output)
3348 return RETURN_ERR;
3349 *output = -99;
3350
3351 return RETURN_OK;
3352}
3353
3354INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3355{
3356 return RETURN_ERR;
3357}
3358
3359
3360//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3361INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3362{
developerd946fd62022-12-08 18:03:28 +08003363 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003364 char cmd[MAX_BUF_SIZE]={'\0'};
3365 char buf[MAX_CMD_SIZE]={'\0'};
3366
3367 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3368 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003369 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003370
developerac6f1142022-12-20 19:26:35 +08003371 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003372 return RETURN_ERR;
3373 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 +08003374 _syscmd(cmd, buf, sizeof(buf));
3375 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003376
developer5f222492022-09-13 15:21:52 +08003377 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003378 return RETURN_OK;
3379}
3380
3381INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3382{
developer5f222492022-09-13 15:21:52 +08003383 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3384 struct params params={'\0'};
3385 char buf[MAX_BUF_SIZE] = {'\0'};
3386 char config_file[MAX_BUF_SIZE] = {'\0'};
3387
developer5b398df2022-11-17 20:39:48 +08003388 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3389 return RETURN_ERR;
3390
developer5f222492022-09-13 15:21:52 +08003391 params.name = "beacon_int";
3392 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3393 params.value = buf;
3394
3395 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3396 wifi_hostapdWrite(config_file, &params, 1);
3397
3398 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3399 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3400 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003401}
3402
3403//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.
3404INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3405{
developer06a01d92022-09-07 16:32:39 +08003406 //TODO: need to revisit below implementation
3407 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003408 char temp_output[128] = {0};
3409 char temp_TransmitRates[64] = {0};
3410 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003411
3412 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3413 if (NULL == output)
3414 return RETURN_ERR;
3415 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003416 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3417
3418 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3419 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3420 } else {
3421 temp = strtok(temp_TransmitRates," ");
3422 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003423 {
developere9d0abd2022-09-13 15:40:57 +08003424 // Convert 100 kbps to Mbps
3425 temp[strlen(temp)-1]=0;
3426 if((temp[0]=='5') && (temp[1]=='\0'))
3427 {
3428 temp="5.5";
3429 }
3430 strcat(temp_output,temp);
3431 temp = strtok(NULL," ");
3432 if(temp!=NULL)
3433 {
3434 strcat(temp_output,",");
3435 }
developer06a01d92022-09-07 16:32:39 +08003436 }
developere9d0abd2022-09-13 15:40:57 +08003437 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003438 }
developer06a01d92022-09-07 16:32:39 +08003439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003440 return RETURN_OK;
3441}
3442
3443INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3444{
3445 char *temp;
3446 char temp1[128];
3447 char temp_output[128];
3448 char temp_TransmitRates[128];
3449 char set[128];
3450 char sub_set[128];
3451 int set_count=0,subset_count=0;
3452 int set_index=0,subset_index=0;
3453 char *token;
3454 int flag=0, i=0;
3455 struct params params={'\0'};
3456 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003457 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003458
3459 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3460 if(NULL == TransmitRates)
3461 return RETURN_ERR;
3462 strcpy(sub_set,TransmitRates);
3463
3464 //Allow only supported Data transmit rate to be set
3465 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3466 token = strtok(sub_set,",");
3467 while( token != NULL ) /* split the basic rate to be set, by comma */
3468 {
3469 sub_set[subset_count]=atoi(token);
3470 subset_count++;
3471 token=strtok(NULL,",");
3472 }
3473 token=strtok(set,",");
3474 while(token!=NULL) /* split the supported rate by comma */
3475 {
3476 set[set_count]=atoi(token);
3477 set_count++;
3478 token=strtok(NULL,",");
3479 }
3480 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3481 {
3482 for(set_index=0;set_index < set_count;set_index++)
3483 {
3484 flag=0;
3485 if(sub_set[subset_index]==set[set_index])
3486 break;
3487 else
3488 flag=1; /* No match found */
3489 }
3490 if(flag==1)
3491 return RETURN_ERR; //If value not found return Error
3492 }
3493 strcpy(temp_TransmitRates,TransmitRates);
3494
3495 for(i=0;i<strlen(temp_TransmitRates);i++)
3496 {
3497 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003498 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003499 {
3500 continue;
3501 }
3502 else
3503 {
3504 return RETURN_ERR;
3505 }
3506 }
3507 strcpy(temp_output,"");
3508 temp = strtok(temp_TransmitRates,",");
3509 while(temp!=NULL)
3510 {
3511 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003512 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003513 {
developeref938762022-10-19 17:21:01 +08003514 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003515 {
3516 return RETURN_ERR;
3517 }
3518 }
3519
3520 if(strcmp(temp,"5.5")==0)
3521 {
3522 strcpy(temp1,"55");
3523 }
3524 else
3525 {
3526 strcat(temp1,"0");
3527 }
3528 strcat(temp_output,temp1);
3529 temp = strtok(NULL,",");
3530 if(temp!=NULL)
3531 {
3532 strcat(temp_output," ");
3533 }
3534 }
3535 strcpy(TransmitRates,temp_output);
3536
3537 params.name= "basic_rates";
3538 params.value =TransmitRates;
3539
3540 wifi_dbg_printf("\n%s:",__func__);
3541 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3542 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3543 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3544 wifi_hostapdWrite(config_file,&params,1);
3545 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3546 return RETURN_OK;
3547}
3548
3549//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003550INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003551{
3552 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3553 FILE *fp = NULL;
3554 char path[256] = {0}, output_string[256] = {0};
3555 int count = 0;
3556 char *interface = NULL;
3557
3558 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3559 if (fp == NULL)
3560 {
3561 printf("Failed to run command in Function %s\n", __FUNCTION__);
3562 return RETURN_ERR;
3563 }
3564 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3565 {
3566 interface = strchr(path, '=');
3567
3568 if (interface != NULL)
3569 {
3570 strcpy(output_string, interface + 1);
developer72ec5572023-01-05 16:27:13 +08003571 for (count = 0; output_string[count] != '\n' && output_string[count] != '\0'; count++)
developer06a01d92022-09-07 16:32:39 +08003572 interface_name[count] = output_string[count];
3573
3574 interface_name[count] = '\0';
3575 }
3576 }
3577 pclose(fp);
3578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3579 return RETURN_OK;
3580}
3581
3582INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3583{
3584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3585 output_struct->radio_BytesSent = 0;
3586 output_struct->radio_BytesReceived = 0;
3587 output_struct->radio_PacketsSent = 0;
3588 output_struct->radio_PacketsReceived = 0;
3589 output_struct->radio_ErrorsSent = 0;
3590 output_struct->radio_ErrorsReceived = 0;
3591 output_struct->radio_DiscardPacketsSent = 0;
3592 output_struct->radio_DiscardPacketsReceived = 0;
3593 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3594 return RETURN_OK;
3595}
3596
3597
3598INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3599{
3600 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer214b0592023-10-31 10:59:05 +08003601 CHAR buf[MAX_CMD_SIZE] = {0};
3602 CHAR Value[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08003603 FILE *fp = NULL;
3604
3605 if (ifname == NULL || strlen(ifname) <= 1)
3606 return RETURN_OK;
3607
developer214b0592023-10-31 10:59:05 +08003608 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
developer06a01d92022-09-07 16:32:39 +08003609 system(buf);
3610
3611 fp = fopen("/tmp/Radio_Stats.txt", "r");
3612 if(fp == NULL)
3613 {
3614 printf("/tmp/Radio_Stats.txt not exists \n");
3615 return RETURN_ERR;
3616 }
3617 fclose(fp);
3618
developer214b0592023-10-31 10:59:05 +08003619 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3620 File_Reading(buf, Value);
3621 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003622
developer214b0592023-10-31 10:59:05 +08003623 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3624 File_Reading(buf, Value);
3625 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003626
developer214b0592023-10-31 10:59:05 +08003627 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3628 File_Reading(buf, Value);
3629 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003630
developer214b0592023-10-31 10:59:05 +08003631 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3632 File_Reading(buf, Value);
3633 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003634
developer214b0592023-10-31 10:59:05 +08003635 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3636 File_Reading(buf, Value);
3637 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003638
developer214b0592023-10-31 10:59:05 +08003639 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3640 File_Reading(buf, Value);
3641 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003642
developer214b0592023-10-31 10:59:05 +08003643 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3644 File_Reading(buf, Value);
3645 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003646
developer214b0592023-10-31 10:59:05 +08003647 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3648 File_Reading(buf, Value);
3649 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003650
3651 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3652 return RETURN_OK;
3653}
3654
3655INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3656{
3657 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3658 CHAR buf[MAX_CMD_SIZE] = {0};
3659 FILE *fp = NULL;
3660 INT count = 0;
3661
3662 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3663 {
3664 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3665 File_Reading(buf, status);
3666 }
3667 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3668 return RETURN_OK;
3669}
3670
3671//Get detail radio traffic static info
3672INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3673{
3674
3675#if 0
3676 //ifconfig radio_x
3677 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3678 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3679 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3680 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3681
3682 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3683 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3684 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.
3685 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.
3686
3687 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3688 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].
3689 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3690 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.
3691 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
3692 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
3693 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
3694 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
3695 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
3696
3697 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
3698 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
3699 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
3700 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.
3701
3702 return RETURN_OK;
3703#endif
3704
developera91d99f2022-09-29 15:59:10 +08003705 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003706 BOOL iface_status = FALSE;
3707 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer7c4c40e2023-10-25 10:17:04 +08003708 INT max_radio_num = 0, apIndex = 0;
developer06a01d92022-09-07 16:32:39 +08003709
3710 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3711 if (NULL == output_struct)
3712 return RETURN_ERR;
3713
developer7c4c40e2023-10-25 10:17:04 +08003714 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08003715
developer7c4c40e2023-10-25 10:17:04 +08003716 memset(output_struct, 0, sizeof(wifi_radioTrafficStats2_t));
developer06a01d92022-09-07 16:32:39 +08003717
developer7c4c40e2023-10-25 10:17:04 +08003718 for(apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
3719 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
3720 continue;
3721 wifi_getApEnable(radioIndex, &iface_status);
3722
3723 if (iface_status == TRUE)
3724 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3725 else
3726 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003727
developer7c4c40e2023-10-25 10:17:04 +08003728 output_struct->radio_BytesSent += radioTrafficStats.radio_BytesSent;
3729 output_struct->radio_BytesReceived += radioTrafficStats.radio_BytesReceived;
3730 output_struct->radio_PacketsSent += radioTrafficStats.radio_PacketsSent;
3731 output_struct->radio_PacketsReceived += radioTrafficStats.radio_PacketsReceived;
3732 output_struct->radio_ErrorsSent += radioTrafficStats.radio_ErrorsSent;
3733 output_struct->radio_ErrorsReceived += radioTrafficStats.radio_ErrorsReceived;
3734 output_struct->radio_DiscardPacketsSent += radioTrafficStats.radio_DiscardPacketsSent;
3735 output_struct->radio_DiscardPacketsReceived += radioTrafficStats.radio_DiscardPacketsReceived;
3736 }
developer06a01d92022-09-07 16:32:39 +08003737
3738 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3739 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].
3740 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3741 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.
3742 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
3743 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
3744 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
3745 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
3746 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
3747
3748 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
3749 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
3750 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
3751 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.
3752
3753 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3754
3755 return RETURN_OK;
3756}
3757
3758//Set radio traffic static Measureing rules
3759INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3760{
3761 //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
3762 // Else, save the MeasuringRate and MeasuringInterval for future usage
3763
3764 return RETURN_OK;
3765}
3766
3767//To start or stop RadioTrafficStats
3768INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3769{
3770 //zqiu: If the RadioTrafficStats process running
3771 // if(enable)
3772 // return RETURN_OK.
3773 // else
3774 // Stop RadioTrafficStats process
3775 // Else
3776 // if(enable)
3777 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3778 // else
3779 // return RETURN_OK.
3780
3781 return RETURN_OK;
3782}
3783
3784//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
3785INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3786{
3787 //zqiu: Please ignor signalIndex.
3788 if (NULL == SignalLevel)
3789 return RETURN_ERR;
3790 *SignalLevel=(radioIndex==0)?-19:-19;
3791
3792 return RETURN_OK;
3793}
3794
3795//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3796INT wifi_applyRadioSettings(INT radioIndex)
3797{
3798 return RETURN_OK;
3799}
3800
3801//Get the radio index assocated with this SSID entry
3802INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3803{
developer5b398df2022-11-17 20:39:48 +08003804 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003805 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003806 int max_radio_num = 0;
3807 wifi_getMaxRadioNumber(&max_radio_num);
3808 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003809 return RETURN_OK;
3810}
3811
3812//Device.WiFi.SSID.{i}.Enable
3813//Get SSID enable configuration parameters (not the SSID enable status)
3814INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3815{
3816 if (NULL == output_bool)
3817 return RETURN_ERR;
3818
developer06a01d92022-09-07 16:32:39 +08003819 return wifi_getApEnable(ssidIndex, output_bool);
3820}
3821
3822//Device.WiFi.SSID.{i}.Enable
3823//Set SSID enable configuration parameters
3824INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3825{
developer06a01d92022-09-07 16:32:39 +08003826 return wifi_setApEnable(ssidIndex, enable);
3827}
3828
3829//Device.WiFi.SSID.{i}.Status
3830//Get the SSID enable status
3831INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3832{
3833 char cmd[MAX_CMD_SIZE]={0};
3834 char buf[MAX_BUF_SIZE]={0};
3835 BOOL output_bool;
3836
3837 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3838 if (NULL == output_string)
3839 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003840
developer06a01d92022-09-07 16:32:39 +08003841 wifi_getApEnable(ssidIndex,&output_bool);
3842 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3843
3844 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3845 return RETURN_OK;
3846}
3847
3848// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3849INT wifi_getSSIDName(INT apIndex, CHAR *output)
3850{
3851 char config_file[MAX_BUF_SIZE] = {0};
3852
3853 if (NULL == output)
3854 return RETURN_ERR;
3855
developerefb790a2023-12-26 18:58:32 +08003856 if (!syn_flag) {
3857 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3858 wifi_hostapdRead(config_file,"ssid",output,32);
3859 } else
developer07ded1f2024-01-10 10:30:15 +08003860 snprintf(output, 32, "%s", vap_info[apIndex].ssid);
developer06a01d92022-09-07 16:32:39 +08003861
3862 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3863 return RETURN_OK;
3864}
3865
3866// Set a max 32 byte string and sets an internal variable to the SSID name
3867INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3868{
3869 char str[MAX_BUF_SIZE]={'\0'};
3870 char cmd[MAX_CMD_SIZE]={'\0'};
3871 struct params params;
3872 char config_file[MAX_BUF_SIZE] = {0};
3873
3874 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer89df4502023-02-16 20:45:02 +08003875 if(NULL == ssid_string || strlen(ssid_string) > 32 || strlen(ssid_string) == 0 )
developer06a01d92022-09-07 16:32:39 +08003876 return RETURN_ERR;
3877
3878 params.name = "ssid";
3879 params.value = ssid_string;
3880 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3881 wifi_hostapdWrite(config_file, &params, 1);
3882 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3883 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3884
3885 return RETURN_OK;
3886}
3887
3888//Get the BSSID
3889INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3890{
3891 char cmd[MAX_CMD_SIZE]="";
3892
3893 if (NULL == output_string)
3894 return RETURN_ERR;
3895
3896 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3897 {
developer1d57d002022-10-12 18:03:15 +08003898 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 +08003899 _syscmd(cmd, output_string, 64);
3900 return RETURN_OK;
3901 }
3902 strncpy(output_string, "\0", 1);
3903
3904 return RETURN_ERR;
3905}
3906
3907//Get the MAC address associated with this Wifi SSID
3908INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3909{
3910 wifi_getBaseBSSID(ssidIndex,output_string);
3911 return RETURN_OK;
3912}
3913
3914//Get the basic SSID traffic static info
3915//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3916//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3917INT wifi_applySSIDSettings(INT ssidIndex)
3918{
developerd946fd62022-12-08 18:03:28 +08003919 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003920 BOOL status = false;
3921 char cmd[MAX_CMD_SIZE] = {0};
3922 char buf[MAX_CMD_SIZE] = {0};
3923 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003924 int max_radio_num = 0;
3925 int radioIndex = 0;
3926
3927 wifi_getMaxRadioNumber(&max_radio_num);
3928
3929 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003930
3931 wifi_getApEnable(ssidIndex,&status);
3932 // Do not apply when ssid index is disabled
3933 if (status == false)
3934 return RETURN_OK;
3935
3936 /* Doing full remove and add for ssid Index
3937 * Not all hostapd options are supported with reload
3938 * for example macaddr_acl
3939 */
3940 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3941 return RETURN_ERR;
3942
3943 ret = wifi_setApEnable(ssidIndex,true);
3944
3945 /* Workaround for hostapd issue with multiple bss definitions
3946 * when first created interface will be removed
3947 * then all vaps other vaps on same phy are removed
3948 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003949 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003950 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003951 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08003952 continue;
developer643b28f2023-04-04 10:26:01 +08003953 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003954 _syscmd(cmd, buf, sizeof(buf));
3955 if(*buf == '1')
3956 wifi_setApEnable(apIndex, true);
3957 }
3958
3959 return ret;
3960}
3961
developera3c68b92022-09-13 15:27:29 +08003962struct channels_noise {
3963 int channel;
3964 int noise;
3965};
3966
3967// Return noise array for each channel
3968int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3969{
developerd946fd62022-12-08 18:03:28 +08003970 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003971 FILE *f = NULL;
3972 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003973 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003974 size_t len = 0;
3975 ssize_t read = 0;
3976 int tmp = 0, arr_index = -1;
3977
developerac6f1142022-12-20 19:26:35 +08003978 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003979 return RETURN_ERR;
3980 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003981
3982 if ((f = popen(cmd, "r")) == NULL) {
3983 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3984 return RETURN_ERR;
3985 }
developer5550e242022-09-30 09:59:32 +08003986
3987 while(fgets(line, sizeof(line), f) != NULL) {
3988 if(arr_index < channels_num){
3989 sscanf(line, "%d", &tmp);
3990 if (tmp > 0) { // channel frequency, the first line must be frequency
3991 arr_index++;
3992 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3993 } else { // noise
3994 channels_noise_arr[arr_index].noise = tmp;
3995 }
3996 }else{
3997 break;
developera3c68b92022-09-13 15:27:29 +08003998 }
3999 }
developera3c68b92022-09-13 15:27:29 +08004000 pclose(f);
4001 return RETURN_OK;
4002}
4003
developer06a01d92022-09-07 16:32:39 +08004004//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
4005//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
4006INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
4007{
developera3c68b92022-09-13 15:27:29 +08004008 int index = -1;
4009 wifi_neighbor_ap2_t *scan_array = NULL;
4010 char cmd[256]={0};
4011 char buf[128]={0};
4012 char file_name[32] = {0};
4013 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08004014 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004015 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08004016 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08004017 int freq=0;
4018 FILE *f = NULL;
4019 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08004020 int channels_num = 0;
4021 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08004022 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08004023 bool filter_enable = false;
4024 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08004025 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004026
developer615510b2022-09-27 10:14:35 +08004027 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004028
developerac6f1142022-12-20 19:26:35 +08004029 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004030 return RETURN_ERR;
4031
developera3c68b92022-09-13 15:27:29 +08004032 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4033 f = fopen(file_name, "r");
4034 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08004035 fgets(buf, sizeof(file_name), f);
4036 if ((strncmp(buf, "0", 1)) != 0) {
4037 fgets(filter_SSID, sizeof(file_name), f);
4038 if (strlen(filter_SSID) != 0)
4039 filter_enable = true;
4040 }
developera3c68b92022-09-13 15:27:29 +08004041 fclose(f);
4042 }
4043
developer033b37b2022-10-18 11:27:46 +08004044 phyId = radio_index_to_phy(radioIndex);
4045 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08004046 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08004047 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004048
developer5550e242022-09-30 09:59:32 +08004049
developer06a01d92022-09-07 16:32:39 +08004050
developerd946fd62022-12-08 18:03:28 +08004051 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4052 // 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 +08004053 fprintf(stderr, "cmd: %s\n", cmd);
4054 if ((f = popen(cmd, "r")) == NULL) {
4055 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4056 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004057 }
developer5550e242022-09-30 09:59:32 +08004058
4059 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4060 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
4061
developer615510b2022-09-27 10:14:35 +08004062 ret = fgets(line, sizeof(line), f);
4063 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08004064 if(strstr(line, "BSS") != NULL) { // new neighbor info
4065 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
4066 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4067 // 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 +08004068
developera3c68b92022-09-13 15:27:29 +08004069 if (!filter_BSS) {
4070 index++;
4071 wifi_neighbor_ap2_t *tmp;
4072 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4073 if (tmp == NULL) { // no more memory to use
4074 index--;
4075 wifi_dbg_printf("%s: realloc failed\n", __func__);
4076 break;
4077 }
4078 scan_array = tmp;
4079 }
4080 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4081
4082 filter_BSS = false;
4083 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4084 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4085 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4086 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4087 } else if (strstr(line, "freq") != NULL) {
4088 sscanf(line," freq: %d", &freq);
4089 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4090
4091 if (freq >= 2412 && freq <= 2484) {
4092 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4093 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4094 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4095 }
4096 else if (freq >= 5160 && freq <= 5805) {
4097 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4098 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4099 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4100 }
4101
4102 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08004103 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08004104 for (int i = 0; i < channels_num; i++) {
4105 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4106 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4107 break;
4108 }
4109 }
4110 }
4111 } else if (strstr(line, "beacon interval") != NULL) {
4112 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4113 } else if (strstr(line, "signal") != NULL) {
4114 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4115 } else if (strstr(line,"SSID") != NULL) {
4116 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4117 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4118 filter_BSS = true;
4119 }
4120 } else if (strstr(line, "Supported rates") != NULL) {
4121 char SRate[80] = {0}, *tmp = NULL;
4122 memset(buf, 0, sizeof(buf));
4123 strcpy(SRate, line);
4124 tmp = strtok(SRate, ":");
4125 tmp = strtok(NULL, ":");
4126 strcpy(buf, tmp);
4127 memset(SRate, 0, sizeof(SRate));
4128
4129 tmp = strtok(buf, " \n");
4130 while (tmp != NULL) {
4131 strcat(SRate, tmp);
4132 if (SRate[strlen(SRate) - 1] == '*') {
4133 SRate[strlen(SRate) - 1] = '\0';
4134 }
4135 strcat(SRate, ",");
4136
4137 tmp = strtok(NULL, " \n");
4138 }
4139 SRate[strlen(SRate) - 1] = '\0';
4140 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4141 } else if (strstr(line, "DTIM") != NULL) {
4142 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4143 } else if (strstr(line, "VHT capabilities") != NULL) {
4144 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4145 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4146 } else if (strstr(line, "HT capabilities") != NULL) {
4147 strcat(scan_array[index].ap_SupportedStandards, ",n");
4148 strcpy(scan_array[index].ap_OperatingStandards, "n");
4149 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004150 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004151 sscanf(line," * channel width: %d", &vht_channel_width);
4152 if(vht_channel_width == 1) {
4153 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4154 } else {
4155 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4156 }
4157 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4158 continue;
4159 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004160 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004161 sscanf(line," * secondary channel offset: %s", &buf);
4162 if (!strcmp(buf, "above")) {
4163 //40Mhz +
4164 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4165 }
4166 else if (!strcmp(buf, "below")) {
4167 //40Mhz -
4168 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4169 } else {
4170 //20Mhz
4171 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4172 }
4173 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4174 continue;
4175 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08004176 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4177 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4178 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004179 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4180 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004181 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08004182 else
developer615510b2022-09-27 10:14:35 +08004183 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08004184 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08004185 if (strstr(line, "HE80/5GHz") != NULL) {
4186 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4187 ret = fgets(line, sizeof(line), f);
4188 } else
4189 continue;
developera3c68b92022-09-13 15:27:29 +08004190 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004191 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08004192 }
developer615510b2022-09-27 10:14:35 +08004193 continue;
developera3c68b92022-09-13 15:27:29 +08004194 } else if (strstr(line, "WPA") != NULL) {
4195 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4196 } else if (strstr(line, "RSN") != NULL) {
4197 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4198 } else if (strstr(line, "Group cipher") != NULL) {
4199 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4200 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4201 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4202 }
4203 }
developer615510b2022-09-27 10:14:35 +08004204 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004205 }
4206
4207 if (!filter_BSS) {
4208 *output_array_size = index + 1;
4209 } else {
4210 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4211 *output_array_size = index;
4212 }
4213 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08004214 pclose(f);
developer5550e242022-09-30 09:59:32 +08004215 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08004216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004217 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004218}
4219
4220//>> Deprecated: used for old RDKB code.
4221INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4222{
4223 INT status = RETURN_ERR;
4224
4225 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4226 output_struct->wifi_PLCPErrorCount = 0;
4227 output_struct->wifi_FCSErrorCount = 0;
4228 output_struct->wifi_InvalidMACCount = 0;
4229 output_struct->wifi_PacketsOtherReceived = 0;
4230 output_struct->wifi_Noise = 0;
4231 status = RETURN_OK;
4232 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4233 return status;
4234}
4235
4236INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4237{
developerd946fd62022-12-08 18:03:28 +08004238 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004239 char cmd[128] = {0};
4240 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004241 char *pos = NULL;
4242
4243 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4244 if (NULL == output_struct)
4245 return RETURN_ERR;
4246
developerac6f1142022-12-20 19:26:35 +08004247 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004248 return RETURN_ERR;
4249
developer06a01d92022-09-07 16:32:39 +08004250 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4251
developerd946fd62022-12-08 18:03:28 +08004252 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004253 _syscmd(cmd, buf, sizeof(buf));
4254
4255 pos = buf;
4256 if ((pos = strstr(pos, "RX packets:")) == NULL)
4257 return RETURN_ERR;
4258 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4259
4260 if ((pos = strstr(pos, "TX packets:")) == NULL)
4261 return RETURN_ERR;
4262 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4263
4264 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4265 return RETURN_ERR;
4266 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4267
4268 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4269 return RETURN_ERR;
4270 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4271
developerd946fd62022-12-08 18:03:28 +08004272 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004273 _syscmd(cmd, buf, sizeof(buf));
4274 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4275
4276#if 0
4277 //TODO: need to revisit below implementation
4278 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4279 char interface_name[MAX_BUF_SIZE] = {0};
4280 char interface_status[MAX_BUF_SIZE] = {0};
4281 char Value[MAX_BUF_SIZE] = {0};
4282 char buf[MAX_CMD_SIZE] = {0};
4283 char cmd[MAX_CMD_SIZE] = {0};
4284 FILE *fp = NULL;
4285
4286 if (NULL == output_struct) {
4287 return RETURN_ERR;
4288 }
4289
4290 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4291
4292 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4293 {
4294 if(apIndex == 0) //private_wifi for 2.4G
4295 {
developerac6f1142022-12-20 19:26:35 +08004296 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004297 }
4298 else if(apIndex == 1) //private_wifi for 5G
4299 {
developerac6f1142022-12-20 19:26:35 +08004300 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004301 }
4302 else if(apIndex == 4) //public_wifi for 2.4G
4303 {
4304 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4305 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4306 {
4307 return RETURN_ERR;
4308 }
4309 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004310 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004311 else//tenda
developerac6f1142022-12-20 19:26:35 +08004312 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004313 }
4314 else if(apIndex == 5) //public_wifi for 5G
4315 {
developerac6f1142022-12-20 19:26:35 +08004316 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004317 }
4318
4319 GetIfacestatus(interface_name, interface_status);
4320
4321 if(0 != strcmp(interface_status, "1"))
4322 return RETURN_ERR;
4323
4324 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4325 system(cmd);
4326
4327 fp = fopen("/tmp/SSID_Stats.txt", "r");
4328 if(fp == NULL)
4329 {
4330 printf("/tmp/SSID_Stats.txt not exists \n");
4331 return RETURN_ERR;
4332 }
4333 fclose(fp);
4334
4335 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4336 File_Reading(buf, Value);
4337 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4338
4339 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4340 File_Reading(buf, Value);
4341 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4342
4343 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4344 File_Reading(buf, Value);
4345 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4346
4347 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4348 File_Reading(buf, Value);
4349 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4350
4351 /* There is no specific parameter from caller to associate the value wifi_Associations */
4352 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4353 //_syscmd(cmd, buf, sizeof(buf));
4354 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4355 }
4356#endif
4357 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4358 return RETURN_OK;
4359}
4360
4361INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4362{
4363 char interface_name[MAX_BUF_SIZE] = {0};
4364 char interface_status[MAX_BUF_SIZE] = {0};
4365 char Value[MAX_BUF_SIZE] = {0};
4366 char buf[MAX_CMD_SIZE] = {0};
4367 char cmd[MAX_CMD_SIZE] = {0};
4368 FILE *fp = NULL;
4369
4370 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4371 if (NULL == output_struct)
4372 return RETURN_ERR;
4373
4374 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4375
developerac6f1142022-12-20 19:26:35 +08004376 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004377 return RETURN_ERR;
4378 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004379
developerd946fd62022-12-08 18:03:28 +08004380 if(0 != strcmp(interface_status, "1"))
4381 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004382
developerd946fd62022-12-08 18:03:28 +08004383 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4384 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004385
developerd946fd62022-12-08 18:03:28 +08004386 fp = fopen("/tmp/SSID_Stats.txt", "r");
4387 if(fp == NULL)
4388 {
4389 printf("/tmp/SSID_Stats.txt not exists \n");
4390 return RETURN_ERR;
4391 }
4392 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004393
developerd946fd62022-12-08 18:03:28 +08004394 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4395 File_Reading(buf, Value);
4396 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004397
developerd946fd62022-12-08 18:03:28 +08004398 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4399 File_Reading(buf, Value);
4400 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004401
developerd946fd62022-12-08 18:03:28 +08004402 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4403 File_Reading(buf, Value);
4404 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004405
developerd946fd62022-12-08 18:03:28 +08004406 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4407 File_Reading(buf, Value);
4408 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004409
4410 output_struct->wifi_UnicastPacketsSent = 0;
4411 output_struct->wifi_UnicastPacketsReceived = 0;
4412 output_struct->wifi_MulticastPacketsSent = 0;
4413 output_struct->wifi_MulticastPacketsReceived = 0;
4414 output_struct->wifi_BroadcastPacketsSent = 0;
4415 output_struct->wifi_BroadcastPacketsRecevied = 0;
4416 output_struct->wifi_UnknownPacketsReceived = 0;
4417
4418 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4419 return RETURN_OK;
4420}
4421
4422INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4423{
4424 INT status = RETURN_ERR;
4425
4426 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4427 //Below values should get updated from hal
4428 output_struct->wifi_RetransCount=0;
4429 output_struct->wifi_FailedRetransCount=0;
4430 output_struct->wifi_RetryCount=0;
4431 output_struct->wifi_MultipleRetryCount=0;
4432 output_struct->wifi_ACKFailureCount=0;
4433 output_struct->wifi_AggregatedPacketCount=0;
4434
4435 status = RETURN_OK;
4436 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4437
4438 return status;
4439}
4440
4441INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4442{
4443 INT status = RETURN_ERR;
4444 UINT index;
4445 wifi_neighbor_ap_t *pt=NULL;
4446
4447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4448 *output_array_size=2;
4449 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4450 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4451 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4452 strcpy(pt->ap_Radio,"");
4453 strcpy(pt->ap_SSID,"");
4454 strcpy(pt->ap_BSSID,"");
4455 strcpy(pt->ap_Mode,"");
4456 pt->ap_Channel=1;
4457 pt->ap_SignalStrength=0;
4458 strcpy(pt->ap_SecurityModeEnabled,"");
4459 strcpy(pt->ap_EncryptionMode,"");
4460 strcpy(pt->ap_OperatingFrequencyBand,"");
4461 strcpy(pt->ap_SupportedStandards,"");
4462 strcpy(pt->ap_OperatingStandards,"");
4463 strcpy(pt->ap_OperatingChannelBandwidth,"");
4464 pt->ap_BeaconPeriod=1;
4465 pt->ap_Noise=0;
4466 strcpy(pt->ap_BasicDataTransferRates,"");
4467 strcpy(pt->ap_SupportedDataTransferRates,"");
4468 pt->ap_DTIMPeriod=1;
4469 pt->ap_ChannelUtilization = 1;
4470 }
4471
4472 status = RETURN_OK;
4473 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4474
4475 return status;
4476}
4477
4478//----------------- AP HAL -------------------------------
4479
4480//>> Deprecated: used for old RDKB code.
4481INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4482{
4483 if (NULL == output_ulong || NULL == output_struct)
4484 return RETURN_ERR;
4485 *output_ulong = 0;
4486 *output_struct = NULL;
4487 return RETURN_OK;
4488}
4489
4490#ifdef HAL_NETLINK_IMPL
4491static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4492 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4493 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4494 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4495 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4496 char mac_addr[20];
4497 static int count=0;
4498 int rate=0;
4499
4500 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4501
4502 nla_parse(tb,
4503 NL80211_ATTR_MAX,
4504 genlmsg_attrdata(gnlh, 0),
4505 genlmsg_attrlen(gnlh, 0),
4506 NULL);
4507
4508 if(!tb[NL80211_ATTR_STA_INFO]) {
4509 fprintf(stderr, "sta stats missing!\n");
4510 return NL_SKIP;
4511 }
4512
4513
4514 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4515 fprintf(stderr, "failed to parse nested attributes!\n");
4516 return NL_SKIP;
4517 }
4518
4519 //devIndex starts from 1
4520 if( ++count == out->wifi_devIndex )
4521 {
4522 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4523 //Getting the mac addrress
4524 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4525
4526 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4527 fprintf(stderr, "failed to parse nested rate attributes!");
4528 return NL_SKIP;
4529 }
4530
4531 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4532 if(rinfo[NL80211_RATE_INFO_BITRATE])
4533 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4534 out->wifi_devTxRate = rate/10;
4535 }
4536
4537 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4538 fprintf(stderr, "failed to parse nested rate attributes!");
4539 return NL_SKIP;
4540 }
4541
4542 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4543 if(rinfo[NL80211_RATE_INFO_BITRATE])
4544 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4545 out->wifi_devRxRate = rate/10;
4546 }
4547 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4548 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4549
4550 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4551 count = 0; //starts the count for next cycle
4552 return NL_STOP;
4553 }
4554
4555 return NL_SKIP;
4556
4557}
4558#endif
4559
4560INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4561{
4562#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004563 Netlink nl = {0};
4564 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004565 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004566
developer30423732022-12-01 16:17:49 +08004567 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004568 info.wifi_devIndex = devIndex;
4569
developerac6f1142022-12-20 19:26:35 +08004570 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004571 return RETURN_ERR;
4572
4573 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004574
4575 nl.id = initSock80211(&nl);
4576
4577 if (nl.id < 0) {
4578 fprintf(stderr, "Error initializing netlink \n");
4579 return -1;
4580 }
4581
4582 struct nl_msg* msg = nlmsg_alloc();
4583
4584 if (!msg) {
4585 fprintf(stderr, "Failed to allocate netlink message.\n");
4586 nlfree(&nl);
4587 return -2;
4588 }
4589
4590 genlmsg_put(msg,
4591 NL_AUTO_PORT,
4592 NL_AUTO_SEQ,
4593 nl.id,
4594 0,
4595 NLM_F_DUMP,
4596 NL80211_CMD_GET_STATION,
4597 0);
4598
4599 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4600 nl_send_auto(nl.socket, msg);
4601 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4602 nl_recvmsgs(nl.socket, nl.cb);
4603 nlmsg_free(msg);
4604 nlfree(&nl);
4605
4606 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4607 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4608 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4609 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4610 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4611 return RETURN_OK;
4612#else
4613 //iw utility to retrieve station information
4614#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4615#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4616#define MACFILE "/tmp/wifi_AssoMac.txt"
4617#define TXRATEFILE "/tmp/wifi_txrate.txt"
4618#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4619 FILE *file = NULL;
4620 char if_name[10] = {'\0'};
4621 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004622 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004623 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004624 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004625
developerac6f1142022-12-20 19:26:35 +08004626 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004627 return RETURN_ERR;
4628
4629 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004630
4631 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4632 file = popen(pipeCmd, "r");
4633
4634 if(file == NULL)
4635 return RETURN_ERR; //popen failed
4636
4637 fgets(line, sizeof line, file);
4638 device = atoi(line);
4639 pclose(file);
4640
4641 if(device == 0)
4642 return RETURN_ERR; //No devices are connected
4643
4644 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4645 system(pipeCmd);
4646
4647 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4648
4649 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4650
4651 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4652
4653 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4654
4655 //devIndex starts from 1, ++count
4656 if((file = fopen(SIGNALFILE, "r")) != NULL )
4657 {
4658 for(count =0;fgets(line, sizeof line, file) != NULL;)
4659 {
4660 if (++count == devIndex)
4661 {
4662 output_struct->wifi_devSignalStrength = atoi(line);
4663 break;
4664 }
4665 }
4666 fclose(file);
4667 }
4668 else
4669 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4670
4671 if((file = fopen(MACFILE, "r")) != NULL )
4672 {
4673 for(count =0;fgets(line, sizeof line, file) != NULL;)
4674 {
4675 if (++count == devIndex)
4676 {
4677 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]);
4678 break;
4679 }
4680 }
4681 fclose(file);
4682 }
4683 else
4684 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4685
4686 if((file = fopen(TXRATEFILE, "r")) != NULL )
4687 {
4688 for(count =0;fgets(line, sizeof line, file) != NULL;)
4689 {
4690 if (++count == devIndex)
4691 {
4692 output_struct->wifi_devTxRate = atoi(line);
4693 break;
4694 }
4695 }
4696 fclose(file);
4697 }
4698 else
4699 fprintf(stderr,"fopen wifi_txrate.txt failed");
4700
4701 if((file = fopen(RXRATEFILE, "r")) != NULL)
4702 {
4703 for(count =0;fgets(line, sizeof line, file) != NULL;)
4704 {
4705 if (++count == devIndex)
4706 {
4707 output_struct->wifi_devRxRate = atoi(line);
4708 break;
4709 }
4710 }
4711 fclose(file);
4712 }
4713 else
4714 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4715
4716 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4717
4718 return RETURN_OK;
4719#endif
4720}
4721
4722INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4723{
4724 if (NULL == device)
4725 return RETURN_ERR;
4726 return RETURN_OK;
4727}
4728//<<
4729
4730
4731//--------------wifi_ap_hal-----------------------------
4732//enables CTS protection for the radio used by this AP
4733INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4734{
4735 //save config and Apply instantly
4736 return RETURN_ERR;
4737}
4738
4739// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4740INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4741{
developer463d39a2022-09-13 15:32:51 +08004742 char config_file[64] = {'\0'};
4743 char buf[64] = {'\0'};
4744 struct params list;
4745
4746 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4747 list.name = "ht_coex";
4748 snprintf(buf, sizeof(buf), "%d", enable);
4749 list.value = buf;
4750
4751 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4752 wifi_hostapdWrite(config_file, &list, 1);
4753 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4754
4755 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4756
4757 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004758}
4759
4760//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4761INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4762{
developerea4bcce2022-09-13 15:26:13 +08004763 char config_file[MAX_BUF_SIZE] = {'\0'};
4764 char buf[MAX_BUF_SIZE] = {'\0'};
4765 struct params list;
4766
4767 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4768 if (threshold < 256 || threshold > 2346 )
4769 return RETURN_ERR;
4770 list.name = "fragm_threshold";
4771 snprintf(buf, sizeof(buf), "%d", threshold);
4772 list.value = buf;
4773
4774 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4775 wifi_hostapdWrite(config_file, &list, 1);
4776 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004777
developerea4bcce2022-09-13 15:26:13 +08004778 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004779
4780 return RETURN_OK;
4781}
4782
4783// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4784INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4785{
developer51a927d2022-09-13 15:42:22 +08004786 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004787 char cmd[512] = {'\0'};
4788 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004789 char stbc_config[16] = {'\0'};
4790 wifi_band band;
4791 int iterator = 0;
4792 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004793 int ant_count = 0;
4794 int ant_bitmap = 0;
4795 struct params list;
developer51a927d2022-09-13 15:42:22 +08004796
4797 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4798
4799 band = wifi_index_to_band(radioIndex);
4800 if (band == band_invalid)
4801 return RETURN_ERR;
4802
4803 if (band == band_2_4)
4804 iterator = 1;
4805 else if (band == band_5)
4806 iterator = 2;
4807 else
4808 return RETURN_OK;
4809
developer110b8a32022-12-26 15:56:44 +08004810 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4811 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4812 ant_count += ant_bitmap & 1;
4813
4814 if (ant_count == 1 && STBC_Enable == TRUE) {
4815 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4816 return RETURN_OK;
4817 }
4818
developer51a927d2022-09-13 15:42:22 +08004819 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4820
4821 // set ht and vht config
4822 for (int i = 0; i < iterator; i++) {
4823 memset(stbc_config, 0, sizeof(stbc_config));
4824 memset(cmd, 0, sizeof(cmd));
4825 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004826 list.name = (i == 0)?"ht_capab":"vht_capab";
4827 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004828 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4829 _syscmd(cmd, buf, sizeof(buf));
4830 if (strlen(buf) != 0)
4831 current_stbc = TRUE;
4832 if (current_stbc == STBC_Enable)
4833 continue;
4834
4835 if (STBC_Enable == TRUE) {
4836 // Append the STBC flags in capab config
4837 memset(cmd, 0, sizeof(cmd));
4838 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004839 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004840 else
developer6372c2b2022-10-27 17:39:51 +08004841 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 +08004842 _syscmd(cmd, buf, sizeof(buf));
4843 } else if (STBC_Enable == FALSE) {
4844 // Remove the STBC flags and remain other flags in capab
4845 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004846 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004847 _syscmd(cmd, buf, sizeof(buf));
4848 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004849 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004850 _syscmd(cmd, buf, sizeof(buf));
4851 }
developer110b8a32022-12-26 15:56:44 +08004852 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4853 list.value = buf;
4854 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004855 }
4856
4857 wifi_reloadAp(radioIndex);
4858
4859 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4860 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004861}
4862
4863// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4864INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4865{
developerfe7aefc2022-12-23 17:13:37 +08004866 char cmd[128] = {0};
4867 char buf[128] = {0};
4868 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004869
4870 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4871
4872 if(output_bool == NULL)
4873 return RETURN_ERR;
4874
developerfe7aefc2022-12-23 17:13:37 +08004875 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4876 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004877
developerfe7aefc2022-12-23 17:13:37 +08004878 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4879 _syscmd(cmd, buf, sizeof(buf));
4880
4881 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004882 *output_bool = TRUE;
4883 else
4884 *output_bool = FALSE;
4885
4886 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4887 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004888}
4889
4890// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4891INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4892{
developerfe7aefc2022-12-23 17:13:37 +08004893 char config_file[128] = {0};
4894 struct params list = {0};
4895 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004896
4897 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4898
developerfe7aefc2022-12-23 17:13:37 +08004899 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004900 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004901
developerfe7aefc2022-12-23 17:13:37 +08004902 if (amsduEnable == enable)
4903 return RETURN_OK;
4904
4905 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4906 list.name = "amsdu";
4907 list.value = amsduEnable? "1":"0";
4908 wifi_hostapdWrite(config_file, &list, 1);
4909 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4910 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004911
4912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4913 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004914}
4915
4916//P2 // outputs the number of Tx streams
4917INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4918{
developer2de97692022-09-26 14:00:03 +08004919 char buf[8] = {0};
4920 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004921 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004922
4923 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4924
developer033b37b2022-10-18 11:27:46 +08004925 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004926 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004927 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004928
developer110b8a32022-12-26 15:56:44 +08004929 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004930
4931 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4932
4933 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004934}
4935
developer110b8a32022-12-26 15:56:44 +08004936INT fitChainMask(INT radioIndex, int antcount)
4937{
4938 char buf[128] = {0};
4939 char cmd[128] = {0};
4940 char config_file[64] = {0};
4941 wifi_band band;
4942 struct params list[2] = {0};
4943
4944 band = wifi_index_to_band(radioIndex);
4945 if (band == band_invalid)
4946 return RETURN_ERR;
4947
4948 list[0].name = "he_mu_beamformer";
4949 list[1].name = "he_su_beamformer";
4950
4951 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4952 if (antcount == 1) {
4953 // remove config about multiple antennas
4954 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4955 _syscmd(cmd, buf, sizeof(buf));
4956
4957 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4958 _syscmd(cmd, buf, sizeof(buf));
4959
4960 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4961 _syscmd(cmd, buf, sizeof(buf));
4962
4963 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4964 _syscmd(cmd, buf, sizeof(buf));
4965
4966 list[0].value = "0";
4967 list[1].value = "0";
4968 } else {
4969 // 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.
4970 if (band == band_2_4 || band == band_5) {
4971 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4972 _syscmd(cmd, buf, sizeof(buf));
4973 if (strlen(buf) > 0) {
4974 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4975 _syscmd(cmd, buf, sizeof(buf));
4976 }
4977 }
4978 if (band == band_5) {
4979 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4980 _syscmd(cmd, buf, sizeof(buf));
4981 if (strlen(buf) > 0) {
4982 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4983 _syscmd(cmd, buf, sizeof(buf));
4984 }
4985 }
4986
4987 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4988 _syscmd(cmd, buf, sizeof(buf));
4989 if (strlen(buf) == 0) {
4990 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4991 _syscmd(cmd, buf, sizeof(buf));
4992 }
4993
4994 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4995 _syscmd(cmd, buf, sizeof(buf));
4996 if (strlen(buf) == 0) {
4997 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4998 _syscmd(cmd, buf, sizeof(buf));
4999 }
5000
5001 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
5002 _syscmd(cmd, buf, sizeof(buf));
5003 if (strlen(buf) == 0) {
5004 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
5005 } else {
5006 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
5007 }
5008 _syscmd(cmd, buf, sizeof(buf));
5009
5010 list[0].value = "1";
5011 list[1].value = "1";
5012 }
5013 wifi_hostapdWrite(config_file, list, 2);
5014}
5015
developer06a01d92022-09-07 16:32:39 +08005016//P2 // sets the number of Tx streams to an enviornment variable
5017INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5018{
developer2de97692022-09-26 14:00:03 +08005019 char cmd[128] = {0};
5020 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08005021 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08005022 int cur_mask = 0;
5023 int antcount = 0;
5024 wifi_band band;
developer2de97692022-09-26 14:00:03 +08005025
5026 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5027
developer110b8a32022-12-26 15:56:44 +08005028 if (numStreams <= 0) {
5029 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08005030 return RETURN_ERR;
5031 }
developer110b8a32022-12-26 15:56:44 +08005032
5033 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
5034 if (cur_mask == numStreams)
5035 return RETURN_OK;
5036
developer2de97692022-09-26 14:00:03 +08005037 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08005038
5039 phyId = radio_index_to_phy(radioIndex);
5040 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08005041 _syscmd(cmd, buf, sizeof(buf));
5042
5043 if (strlen(buf) > 0) {
5044 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5045 return RETURN_ERR;
5046 }
developer2de97692022-09-26 14:00:03 +08005047
developer110b8a32022-12-26 15:56:44 +08005048 // if chain mask changed, we need to make the hostapd config valid.
5049 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
5050 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08005051 }
developer110b8a32022-12-26 15:56:44 +08005052 fitChainMask(radioIndex, antcount);
5053
5054 wifi_setRadioEnable(radioIndex, TRUE);
5055
developer2de97692022-09-26 14:00:03 +08005056 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5057 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005058}
5059
5060//P2 // outputs the number of Rx streams
5061INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5062{
developer110b8a32022-12-26 15:56:44 +08005063 char buf[8] = {0};
5064 char cmd[128] = {0};
5065 int phyId = 0;
5066
developer2de97692022-09-26 14:00:03 +08005067 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005068
5069 phyId = radio_index_to_phy(radioIndex);
5070 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5071 _syscmd(cmd, buf, sizeof(buf));
5072
5073 *output_int = (INT)strtol(buf, NULL, 16);
5074
developer2de97692022-09-26 14:00:03 +08005075 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005076
developer06a01d92022-09-07 16:32:39 +08005077 return RETURN_OK;
5078}
5079
5080//P2 // sets the number of Rx streams to an enviornment variable
5081INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5082{
developer2de97692022-09-26 14:00:03 +08005083 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5084 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5085 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5086 return RETURN_ERR;
5087 }
5088 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005089 return RETURN_ERR;
5090}
5091
5092//Get radio RDG enable setting
5093INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5094{
5095 if (NULL == output_bool)
5096 return RETURN_ERR;
5097 *output_bool = TRUE;
5098 return RETURN_OK;
5099}
5100
5101//Get radio RDG enable setting
5102INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5103{
5104 if (NULL == output_bool)
5105 return RETURN_ERR;
5106 *output_bool = TRUE;
5107 return RETURN_OK;
5108}
5109
5110//Set radio RDG enable setting
5111INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5112{
5113 return RETURN_ERR;
5114}
5115
5116//Get radio ADDBA enable setting
5117INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5118{
5119 if (NULL == output_bool)
5120 return RETURN_ERR;
5121 *output_bool = TRUE;
5122 return RETURN_OK;
5123}
5124
5125//Set radio ADDBA enable setting
5126INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5127{
5128 return RETURN_ERR;
5129}
5130
5131//Get radio auto block ack enable setting
5132INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5133{
5134 if (NULL == output_bool)
5135 return RETURN_ERR;
5136 *output_bool = TRUE;
5137 return RETURN_OK;
5138}
5139
5140//Set radio auto block ack enable setting
5141INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5142{
5143 return RETURN_ERR;
5144}
5145
5146//Get radio 11n pure mode enable support
5147INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5148{
5149 if (NULL == output_bool)
5150 return RETURN_ERR;
5151 *output_bool = TRUE;
5152 return RETURN_OK;
5153}
5154
5155//Get radio 11n pure mode enable setting
5156INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5157{
5158 if (NULL == output_bool)
5159 return RETURN_ERR;
5160 *output_bool = TRUE;
5161 return RETURN_OK;
5162}
5163
5164//Set radio 11n pure mode enable setting
5165INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5166{
5167 return RETURN_ERR;
5168}
5169
5170//Get radio IGMP snooping enable setting
5171INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5172{
developerd946fd62022-12-08 18:03:28 +08005173 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005174 char cmd[128]={0};
5175 char buf[4]={0};
5176 bool bridge = FALSE, mac80211 = FALSE;
5177 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5178
5179 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08005180 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08005181
5182 *output_bool = FALSE;
5183
5184 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5185 _syscmd(cmd, buf, sizeof(buf));
5186 if (strncmp(buf, "1", 1) == 0)
5187 bridge = TRUE;
5188
developerac6f1142022-12-20 19:26:35 +08005189 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005190 return RETURN_ERR;
5191 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 +08005192 _syscmd(cmd, buf, sizeof(buf));
5193 if (strncmp(buf, "1", 1) == 0)
5194 mac80211 = TRUE;
5195
5196 if (bridge && mac80211)
5197 *output_bool = TRUE;
5198
5199 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005200 return RETURN_OK;
5201}
5202
5203//Set radio IGMP snooping enable setting
5204INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5205{
developerd946fd62022-12-08 18:03:28 +08005206 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005207 char cmd[128]={0};
5208 char buf[4]={0};
developer894affa2023-05-10 18:13:19 +08005209 int max_num_radios = 0;
5210 int apIndex = 0;
developer81bf2ed2022-09-13 15:31:14 +08005211 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5212
5213 // bridge
developerfb09ba62023-06-09 17:03:21 +08005214 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
developer81bf2ed2022-09-13 15:31:14 +08005215 _syscmd(cmd, buf, sizeof(buf));
5216
developer804c64f2022-10-19 13:54:40 +08005217 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08005218 // mac80211
developer894affa2023-05-10 18:13:19 +08005219 for (int i = 0; i < MAX_NUM_VAP_PER_RADIO; i++) {
5220 apIndex = radioIndex + i*max_num_radios;
5221 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5222 continue;
developerfb09ba62023-06-09 17:03:21 +08005223 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 +08005224 _syscmd(cmd, buf, sizeof(buf));
5225 }
5226 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5227 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005228}
5229
5230//Get the Reset count of radio
5231INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5232{
5233 if (NULL == output_int)
5234 return RETURN_ERR;
5235 *output_int = (radioIndex==0)? 1: 3;
5236
5237 return RETURN_OK;
5238}
5239
5240
5241//---------------------------------------------------------------------------------------------------
5242//
5243// Additional Wifi AP level APIs used for Access Point devices
5244//
5245//---------------------------------------------------------------------------------------------------
5246
5247// creates a new ap and pushes these parameters to the hardware
5248INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5249{
developer7930d352022-12-21 17:55:42 +08005250 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005251 return RETURN_OK;
5252}
5253
5254// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5255INT wifi_deleteAp(INT apIndex)
5256{
developerd946fd62022-12-08 18:03:28 +08005257 char interface_name[16] = {0};
developer89df4502023-02-16 20:45:02 +08005258 char buf[128] = {0};
5259 char cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08005260
developerac6f1142022-12-20 19:26:35 +08005261 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005262 return RETURN_ERR;
developera77d84b2023-02-22 16:10:50 +08005263
developer89df4502023-02-16 20:45:02 +08005264 if (wifi_setApEnable(apIndex, FALSE) != RETURN_OK)
5265 return RETURN_ERR;
5266
developer7930d352022-12-21 17:55:42 +08005267 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005268 _syscmd(cmd, buf, sizeof(buf));
5269
5270 wifi_removeApSecVaribles(apIndex);
developer06a01d92022-09-07 16:32:39 +08005271 return RETURN_OK;
5272}
5273
5274// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5275INT wifi_getApName(INT apIndex, CHAR *output_string)
5276{
developerd946fd62022-12-08 18:03:28 +08005277 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005278 if(NULL == output_string)
5279 return RETURN_ERR;
5280
developerac6f1142022-12-20 19:26:35 +08005281 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005282 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005283 else
5284 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005285 return RETURN_OK;
5286}
5287
5288// Outputs the index number in that corresponds to the SSID string
5289INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5290{
developerd946fd62022-12-08 18:03:28 +08005291 char cmd [128] = {0};
5292 char buf[32] = {0};
5293 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005294 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005295
developerefb790a2023-12-26 18:58:32 +08005296#ifdef DYNAMIC_IF_NAME
developerd946fd62022-12-08 18:03:28 +08005297 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5298 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005299
developerac6f1142022-12-20 19:26:35 +08005300 if (strlen(buf) != 0) {
5301 apIndex_str = strtok(buf, "\n");
5302 *output_int = strtoul(apIndex_str, NULL, 10);
5303 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005304 }
developerefb790a2023-12-26 18:58:32 +08005305#endif
developer67b8ee92022-12-20 10:48:43 +08005306 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5307 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5308 if (apIndex_str) {
5309 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5310 return RETURN_OK;
5311 }
developerd946fd62022-12-08 18:03:28 +08005312 *output_int = -1;
5313 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005314}
5315
5316INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5317{
5318 return wifi_getIndexFromName(inputSsidString, output_int);
5319}
5320
5321// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5322INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5323{
5324 char buf[MAX_BUF_SIZE] = {0};
5325 char cmd[MAX_CMD_SIZE] = {0};
5326 char config_file[MAX_BUF_SIZE] = {0};
5327
5328 if(NULL == output_string)
5329 return RETURN_ERR;
5330
5331 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005332 if (!syn_flag)
5333 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5334 else
developer07ded1f2024-01-10 10:30:15 +08005335 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08005336 if((strcmp(buf,"3")==0))
5337 snprintf(output_string, 32, "WPAand11i");
5338 else if((strcmp(buf,"2")==0))
5339 snprintf(output_string, 32, "11i");
5340 else if((strcmp(buf,"1")==0))
5341 snprintf(output_string, 32, "WPA");
5342 else
5343 snprintf(output_string, 32, "None");
5344
5345 return RETURN_OK;
5346}
5347
5348// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5349INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5350{
5351 char config_file[MAX_BUF_SIZE] = {0};
5352 struct params list;
5353
5354 if (NULL == beaconTypeString)
5355 return RETURN_ERR;
5356 list.name = "wpa";
5357 list.value = "0";
5358
5359 if((strcmp(beaconTypeString,"WPAand11i")==0))
5360 list.value="3";
5361 else if((strcmp(beaconTypeString,"11i")==0))
5362 list.value="2";
5363 else if((strcmp(beaconTypeString,"WPA")==0))
5364 list.value="1";
5365
5366 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5367 wifi_hostapdWrite(config_file, &list, 1);
5368 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developerefb790a2023-12-26 18:58:32 +08005369 snprintf(vap_info[apIndex].wpa, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08005370 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5371 return RETURN_OK;
5372}
5373
5374// sets the beacon interval on the hardware for this AP
5375INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5376{
developer5f222492022-09-13 15:21:52 +08005377 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5378 struct params params={'\0'};
5379 char buf[MAX_BUF_SIZE] = {'\0'};
5380 char config_file[MAX_BUF_SIZE] = {'\0'};
5381
5382 params.name = "beacon_int";
5383 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5384 params.value = buf;
5385
5386 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5387 wifi_hostapdWrite(config_file, &params, 1);
5388
5389 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5390 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5391 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005392}
5393
5394INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5395{
developer5b398df2022-11-17 20:39:48 +08005396 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5397 return RETURN_ERR;
5398 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005399}
5400
5401// Get the packet size threshold supported.
5402INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5403{
5404 //save config and apply instantly
5405 if (NULL == output_bool)
5406 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005407 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005408 return RETURN_OK;
5409}
5410
5411// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5412INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5413{
developer514406b2022-12-05 17:20:21 +08005414 char buf[16] = {0};
5415 char config_file[128] = {0};
5416 struct params param = {0};
5417
5418 if (threshold > 65535) {
5419 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5420 return RETURN_ERR;
5421 }
developer06a01d92022-09-07 16:32:39 +08005422
developer23e71282023-01-18 10:25:19 +08005423 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer514406b2022-12-05 17:20:21 +08005424 snprintf(buf, sizeof(buf), "%u", threshold);
5425 param.name = "rts_threshold";
5426 param.value = buf;
5427 wifi_hostapdWrite(config_file, &param, 1);
5428 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5429 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005430
5431 return RETURN_OK;
5432}
5433
5434// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5435INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5436{
5437 if (NULL == output_string)
5438 return RETURN_ERR;
5439 snprintf(output_string, 32, "TKIPandAESEncryption");
5440 return RETURN_OK;
5441
5442}
5443
5444// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5445INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5446{
5447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005448 char *param_name = NULL;
5449 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005450
5451 if(NULL == output_string)
5452 return RETURN_ERR;
5453
5454 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005455 if (!syn_flag)
5456 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5457 else
developer07ded1f2024-01-10 10:30:15 +08005458 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08005459
5460 if(strcmp(buf,"0")==0)
5461 {
5462 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5463 snprintf(output_string, 32, "None");
5464 return RETURN_OK;
5465 }
5466 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5467 param_name = "rsn_pairwise";
5468 else if((strcmp(buf,"1")==0))
5469 param_name = "wpa_pairwise";
5470 else
5471 return RETURN_ERR;
5472 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005473 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005474 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5475 param_name = "wpa_pairwise";
5476 memset(output_string, '\0', 32);
5477 wifi_hostapdRead(config_file, param_name, output_string, 32);
5478 }
developer06a01d92022-09-07 16:32:39 +08005479 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5480
developer72ec5572023-01-05 16:27:13 +08005481 if(strcmp(output_string,"TKIP CCMP") == 0)
5482 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5483 else if(strcmp(output_string,"TKIP") == 0)
developer06a01d92022-09-07 16:32:39 +08005484 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5485 else if(strcmp(output_string,"CCMP") == 0)
5486 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer06a01d92022-09-07 16:32:39 +08005487
5488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5489 return RETURN_OK;
5490}
5491
5492// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5493INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5494{
5495 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5496 struct params params={'\0'};
5497 char output_string[32];
developer72ec5572023-01-05 16:27:13 +08005498 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08005499
5500 memset(output_string,'\0',32);
developer72ec5572023-01-05 16:27:13 +08005501 wifi_getApBeaconType(apIndex,output_string);
developer06a01d92022-09-07 16:32:39 +08005502
5503 if(strcmp(encMode, "TKIPEncryption") == 0)
5504 params.value = "TKIP";
5505 else if(strcmp(encMode,"AESEncryption") == 0)
5506 params.value = "CCMP";
5507 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5508 params.value = "TKIP CCMP";
5509
5510 if((strcmp(output_string,"WPAand11i")==0))
5511 {
5512 params.name = "wpa_pairwise";
5513 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5514 wifi_hostapdWrite(config_file, &params, 1);
5515 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5516
developer30423732022-12-01 16:17:49 +08005517 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005518 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5519 wifi_hostapdWrite(config_file, &params, 1);
5520 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5521
5522 return RETURN_OK;
5523 }
5524 else if((strcmp(output_string,"11i")==0))
5525 {
5526 params.name = "rsn_pairwise";
5527 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5528 wifi_hostapdWrite(config_file, &params, 1);
5529 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5530 return RETURN_OK;
5531 }
5532 else if((strcmp(output_string,"WPA")==0))
5533 {
5534 params.name = "wpa_pairwise";
5535 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5536 wifi_hostapdWrite(config_file, &params, 1);
5537 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5538 return RETURN_OK;
5539 }
5540
5541 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5542 return RETURN_OK;
5543}
5544
5545// deletes internal security varable settings for this ap
5546INT wifi_removeApSecVaribles(INT apIndex)
5547{
5548 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005549 //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 +08005550 //_syscmd(cmd, buf, sizeof(buf));
5551
developerd946fd62022-12-08 18:03:28 +08005552 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005553 //_syscmd(cmd, buf, sizeof(buf));
5554 return RETURN_ERR;
5555}
5556
5557// changes the hardware settings to disable encryption on this ap
5558INT wifi_disableApEncryption(INT apIndex)
5559{
5560 //Apply instantly
5561 return RETURN_ERR;
5562}
5563
5564// set the authorization mode on this ap
5565// mode mapping as: 1: open, 2: shared, 4:auto
5566INT wifi_setApAuthMode(INT apIndex, INT mode)
5567{
developeraf95c502022-09-13 16:18:22 +08005568 struct params params={0};
5569 char config_file[64] = {0};
5570 int ret;
5571
5572 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5573
5574 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5575 params.name = "auth_algs";
5576
developer72ec5572023-01-05 16:27:13 +08005577 if ((mode & 1 && mode & 2) || mode & 4)
developeraf95c502022-09-13 16:18:22 +08005578 params.value = "3";
5579 else if (mode & 2)
5580 params.value = "2";
5581 else if (mode & 1)
5582 params.value = "1";
5583 else
5584 params.value = "0";
5585
5586 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5587 wifi_hostapdWrite(config_file, &params, 1);
5588 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer72ec5572023-01-05 16:27:13 +08005589 wifi_reloadAp(apIndex);
developeraf95c502022-09-13 16:18:22 +08005590 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5591
5592 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005593}
5594
5595// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5596INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5597{
5598 //save to wifi config, and wait for wifi restart to apply
5599 struct params params={'\0'};
5600 char config_file[MAX_BUF_SIZE] = {0};
5601 int ret;
5602
5603 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5604 if(authMode == NULL)
5605 return RETURN_ERR;
5606
5607 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5608 params.name = "wpa_key_mgmt";
5609
5610 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5611 params.value = "WPA-PSK";
5612 else if(strcmp(authMode,"EAPAuthentication") == 0)
5613 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005614 else if (strcmp(authMode, "SAEAuthentication") == 0)
5615 params.value = "SAE";
5616 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5617 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005618 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5619 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005620 else if (strcmp(authMode, "Enhanced_Open") == 0)
5621 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005622 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5623 return RETURN_OK; //This is taken careof in beaconType
5624
5625 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5626 ret=wifi_hostapdWrite(config_file,&params,1);
5627 if(!ret)
5628 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
developerefb790a2023-12-26 18:58:32 +08005629 snprintf(vap_info[apIndex].wpa_key_mgmt, MAX_BUF_SIZE, "%s", params.value);
developer06a01d92022-09-07 16:32:39 +08005630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5631
5632 return ret;
5633}
5634
5635// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5636INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5637{
5638 //save to wifi config, and wait for wifi restart to apply
5639 char BeaconType[50] = {0};
5640 char config_file[MAX_BUF_SIZE] = {0};
5641
5642 *authMode = 0;
5643 wifi_getApBeaconType(apIndex,BeaconType);
5644 printf("%s____%s \n",__FUNCTION__,BeaconType);
5645
5646 if(strcmp(BeaconType,"None") == 0)
5647 strcpy(authMode,"None");
5648 else
5649 {
5650 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08005651 if (!syn_flag)
5652 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5653 else
developer07ded1f2024-01-10 10:30:15 +08005654 snprintf(authMode, 32, "%s", vap_info[apIndex].wpa_key_mgmt);
developer06a01d92022-09-07 16:32:39 +08005655 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5656 if(strcmp(authMode,"WPA-PSK") == 0)
5657 strcpy(authMode,"SharedAuthentication");
5658 else if(strcmp(authMode,"WPA-EAP") == 0)
5659 strcpy(authMode,"EAPAuthentication");
5660 }
5661
5662 return RETURN_OK;
5663}
5664
5665// Outputs the number of stations associated per AP
5666INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5667{
developerd946fd62022-12-08 18:03:28 +08005668 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005669 char cmd[128]={0};
5670 char buf[128]={0};
5671 BOOL status = false;
5672
5673 if(apIndex > MAX_APS)
5674 return RETURN_ERR;
5675
5676 wifi_getApEnable(apIndex,&status);
5677 if (!status)
5678 return RETURN_OK;
5679
developerd946fd62022-12-08 18:03:28 +08005680 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005681 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005682 return RETURN_ERR;
5683 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005684 _syscmd(cmd, buf, sizeof(buf));
5685 sscanf(buf,"%lu", output_ulong);
5686
5687 return RETURN_OK;
5688}
5689
5690// manually removes any active wi-fi association with the device specified on this ap
5691INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5692{
developerd946fd62022-12-08 18:03:28 +08005693 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005694 char buf[126]={'\0'};
5695
developerac6f1142022-12-20 19:26:35 +08005696 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005697 return RETURN_ERR;
5698 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005699 system(buf);
5700
5701 return RETURN_OK;
5702}
5703
5704// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5705INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5706{
5707 if(NULL == output_int)
5708 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005709 int max_radio_num = 0;
5710 wifi_getMaxRadioNumber(&max_radio_num);
5711 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005712 return RETURN_OK;
5713}
5714
5715// sets the radio index for the specific ap
5716INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5717{
5718 //set to config only and wait for wifi reset to apply settings
5719 return RETURN_ERR;
5720}
5721
5722// Get the ACL MAC list per AP
5723INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5724{
developerd946fd62022-12-08 18:03:28 +08005725 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005726 char cmd[MAX_CMD_SIZE]={'\0'};
5727 int ret = 0;
5728
developerac6f1142022-12-20 19:26:35 +08005729 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005730 return RETURN_ERR;
5731 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005732 ret = _syscmd(cmd,macArray,buf_size);
5733 if (ret != 0)
5734 return RETURN_ERR;
5735
5736 return RETURN_OK;
5737}
5738
developere6aafda2022-09-13 14:59:28 +08005739INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5740{
developerd946fd62022-12-08 18:03:28 +08005741 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005742 char cmd[MAX_CMD_SIZE]={'\0'};
5743 int ret = 0;
5744
developerac6f1142022-12-20 19:26:35 +08005745 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005746 return RETURN_ERR;
5747 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005748 ret = _syscmd(cmd,macArray,buf_size);
5749 if (ret != 0)
5750 return RETURN_ERR;
5751
5752 return RETURN_OK;
5753}
5754
developer06a01d92022-09-07 16:32:39 +08005755// Get the list of stations associated per AP
5756INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5757{
developerd946fd62022-12-08 18:03:28 +08005758 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005759 char cmd[128];
5760
5761 if(apIndex > 3) //Currently supporting apIndex upto 3
5762 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005763 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005764 return RETURN_ERR;
5765 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5766 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005767 _syscmd(cmd, macArray, buf_size);
5768
5769 return RETURN_OK;
5770}
5771
developer2f995fb2023-02-24 10:40:44 +08005772INT getAddressControlMode(INT apIndex, INT *mode)
5773{
5774 char buf [16] = {0};
5775 char config_file[64] = {0};
5776
5777 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08005778 if (!syn_flag)
5779 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
5780 else
developer07ded1f2024-01-10 10:30:15 +08005781 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].macaddr_acl);
developer2f995fb2023-02-24 10:40:44 +08005782
5783 *mode = -1;
5784 // 0 use deny file, 1 use accept file
5785 if (strncmp(buf, "0", 1) == 0 || strncmp(buf, "1", 1) == 0)
5786 *mode = (INT)strtol(buf, NULL, 10);
5787
5788 return RETURN_OK;
5789}
5790
developer06a01d92022-09-07 16:32:39 +08005791// adds the mac address to the filter list
5792//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5793INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5794{
5795 char cmd[MAX_CMD_SIZE]={'\0'};
5796 char buf[MAX_BUF_SIZE]={'\0'};
5797
developer2f995fb2023-02-24 10:40:44 +08005798 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +08005799 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005800
developer06a01d92022-09-07 16:32:39 +08005801 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5802 if(_syscmd(cmd,buf,sizeof(buf)))
5803 return RETURN_ERR;
5804
5805 return RETURN_OK;
5806}
5807
developer2f995fb2023-02-24 10:40:44 +08005808INT wifi_addApDenyAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5809{
5810 char cmd[MAX_CMD_SIZE]={'\0'};
5811 char buf[MAX_BUF_SIZE]={'\0'};
5812
5813 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
5814 return RETURN_ERR;
5815
5816 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5817 if(_syscmd(cmd,buf,sizeof(buf)))
5818 return RETURN_ERR;
5819
5820 return RETURN_OK;
5821}
5822
developer06a01d92022-09-07 16:32:39 +08005823// deletes the mac address from the filter list
5824//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5825INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5826{
5827 char cmd[MAX_CMD_SIZE]={'\0'};
5828 char buf[MAX_BUF_SIZE]={'\0'};
5829
5830#if 0
developerd946fd62022-12-08 18:03:28 +08005831 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005832 if(_syscmd(cmd,buf,sizeof(buf)))
5833 return RETURN_ERR;
5834
5835#endif
developer2f995fb2023-02-24 10:40:44 +08005836 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005837 if(_syscmd(cmd,buf,sizeof(buf)))
5838 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005839 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5840 if(_syscmd(cmd,buf,sizeof(buf)))
5841 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005842
5843 return RETURN_OK;
5844}
5845
5846// outputs the number of devices in the filter list
5847INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5848{
developere6aafda2022-09-13 14:59:28 +08005849 char cmd[MAX_BUF_SIZE]={0};
5850 char buf[MAX_CMD_SIZE]={0};
developer2f995fb2023-02-24 10:40:44 +08005851 int mode = -1;
developere6aafda2022-09-13 14:59:28 +08005852
5853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5854 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005855 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005856
developer2f995fb2023-02-24 10:40:44 +08005857 getAddressControlMode(apIndex, &mode);
5858 if (mode == -1)
5859 return RETURN_OK;
5860
5861 if (mode == 0)
5862 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", DENY_PREFIX, apIndex);
5863 else if (mode == 1)
5864 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +08005865 _syscmd(cmd, buf, sizeof(buf));
5866
developer2f995fb2023-02-24 10:40:44 +08005867 *output_uint = strtol(buf, NULL, 10);
developere6aafda2022-09-13 14:59:28 +08005868
5869 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5870 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005871}
5872
5873INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5874{
5875 char cmd[128]={'\0'};
5876 char buf[128]={'\0'};
5877
5878 if(strcmp(action,"DENY")==0)
5879 {
5880 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5881 system(buf);
5882 return RETURN_OK;
5883 }
5884
5885 if(strcmp(action,"ALLOW")==0)
5886 {
5887 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5888 system(buf);
5889 return RETURN_OK;
5890 }
5891
5892 return RETURN_ERR;
5893
5894}
5895
5896// enable kick for devices on acl black list
5897INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5898{
5899 char aclArray[512] = {0}, *acl = NULL;
5900 char assocArray[512] = {0}, *asso = NULL;
5901
developere6aafda2022-09-13 14:59:28 +08005902 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005903 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5904
5905 // if there are no devices connected there is nothing to do
5906 if (strlen(assocArray) < 17)
5907 return RETURN_OK;
5908
5909 if (enable == TRUE)
5910 {
5911 //kick off the MAC which is in ACL array (deny list)
5912 acl = strtok(aclArray, "\r\n");
5913 while (acl != NULL) {
5914 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5915 wifi_kickApAssociatedDevice(apIndex, acl);
5916
5917 acl = strtok(NULL, "\r\n");
5918 }
developere6aafda2022-09-13 14:59:28 +08005919 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005920 }
5921 else
5922 {
developere6aafda2022-09-13 14:59:28 +08005923 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005924 }
5925
5926#if 0
5927 //TODO: need to revisit below implementation
5928 char aclArray[512]={0}, *acl=NULL;
5929 char assocArray[512]={0}, *asso=NULL;
5930 char buf[256]={'\0'};
5931 char action[10]={'\0'};
5932 FILE *fr=NULL;
5933 char interface[10]={'\0'};
5934 char config_file[MAX_BUF_SIZE] = {0};
5935
5936 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5937 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5938 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5939 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5940
5941 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5942 system(buf);
5943 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5944 system(buf);
5945 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5946 system(buf);
5947 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5948 system(buf);
5949 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5950 system(buf);
5951
5952 if ( enable == TRUE )
5953 {
5954 int device_count=0;
5955 strcpy(action,"DENY");
5956 //kick off the MAC which is in ACL array (deny list)
5957 acl = strtok (aclArray,",");
5958 while (acl != NULL) {
5959 if(strlen(acl)>=17)
5960 {
5961 apply_rules(apIndex, acl,action,interface);
5962 device_count++;
5963 //Register mac to be blocked ,in syscfg.db persistent storage
5964 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5965 system(buf);
5966 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5967 system(buf);
5968 system("syscfg commit");
5969
5970 wifi_kickApAssociatedDevice(apIndex, acl);
5971 }
5972 acl = strtok (NULL, ",");
5973 }
5974 }
5975 else
5976 {
5977 int device_count=0;
5978 char cmdmac[20]={'\0'};
5979 strcpy(action,"ALLOW");
5980 //kick off the MAC which is not in ACL array (allow list)
5981 acl = strtok (aclArray,",");
5982 while (acl != NULL) {
5983 if(strlen(acl)>=17)
5984 {
5985 apply_rules(apIndex, acl,action,interface);
5986 device_count++;
5987 //Register mac to be Allowed ,in syscfg.db persistent storage
5988 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5989 system(buf);
5990 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5991 system(buf);
5992 sprintf(cmdmac,"%s",acl);
5993 }
5994 acl = strtok (NULL, ",");
5995 }
5996 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5997 system(buf);
5998
5999 //Disconnect the mac which is not in ACL
6000 asso = strtok (assocArray,",");
6001 while (asso != NULL) {
6002 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
6003 wifi_kickApAssociatedDevice(apIndex, asso);
6004 asso = strtok (NULL, ",");
6005 }
6006 }
6007#endif
6008 return RETURN_OK;
6009}
6010
6011INT wifi_setPreferPrivateConnection(BOOL enable)
6012{
developer06a01d92022-09-07 16:32:39 +08006013 return RETURN_OK;
6014}
6015
6016// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
6017INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
6018{
developerd946fd62022-12-08 18:03:28 +08006019 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006020 int items = 1;
6021 struct params list[2];
6022 char buf[MAX_BUF_SIZE] = {0};
6023 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08006024 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08006025
6026 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08006027
developer10adcc12022-09-13 14:39:17 +08006028 if (filterMode == 0) {
6029 sprintf(buf, "%d", 0);
6030 list[0].value = buf;
6031
developer2f995fb2023-02-24 10:40:44 +08006032 char cmd[128] = {0};
developerac6f1142022-12-20 19:26:35 +08006033 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006034 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08006035 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR 2> /dev/null", interface_name);
6036 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08006037 memset(cmd,0,sizeof(cmd));
6038 // Delete deny_mac_file in hostapd configuration
6039 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
developer2f995fb2023-02-24 10:40:44 +08006040 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08006041 }
6042 else if (filterMode == 1) {
6043 sprintf(buf, "%d", filterMode);
6044 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08006045 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
6046 list[1].name = "accept_mac_file";
6047 list[1].value = acl_file;
6048 items = 2;
developer10adcc12022-09-13 14:39:17 +08006049 } else if (filterMode == 2) {
6050 //TODO: deny_mac_file
6051 sprintf(buf, "%d", 0);
6052 list[0].value = buf;
6053 list[1].name = "deny_mac_file";
6054 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
6055 list[1].value = deny_file;
6056 items = 2;
6057 } else {
6058 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006059 }
developer10adcc12022-09-13 14:39:17 +08006060
developer06a01d92022-09-07 16:32:39 +08006061 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6062 wifi_hostapdWrite(config_file, list, items);
developer2f995fb2023-02-24 10:40:44 +08006063 if (multiple_set == FALSE) {
6064 wifi_setApEnable(apIndex, FALSE);
6065 wifi_setApEnable(apIndex, TRUE);
6066 }
developerefb790a2023-12-26 18:58:32 +08006067 snprintf(vap_info[apIndex].macaddr_acl, MAX_BUF_SIZE, "%s", list[0].value);
developer06a01d92022-09-07 16:32:39 +08006068
6069 return RETURN_OK;
6070
6071#if 0
6072 if(apIndex==0 || apIndex==1)
6073 {
6074 //set the filtermode
6075 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
6076 system(buf);
6077 system("syscfg commit");
6078
6079 if(filterMode==0)
6080 {
6081 sprintf(buf,"iptables -F WifiServices%d",apIndex);
6082 system(buf);
6083 return RETURN_OK;
6084 }
6085 }
6086 return RETURN_OK;
6087#endif
6088}
6089
6090// 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.
6091INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6092{
6093 return RETURN_ERR;
6094}
6095
6096// gets the vlan ID for this ap from an internal enviornment variable
6097INT wifi_getApVlanID(INT apIndex, INT *output_int)
6098{
developer30423732022-12-01 16:17:49 +08006099 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08006100 {
6101 *output_int=100;
6102 return RETURN_OK;
6103 }
6104
6105 return RETURN_ERR;
6106}
6107
6108// sets the vlan ID for this ap to an internal enviornment variable
6109INT wifi_setApVlanID(INT apIndex, INT vlanId)
6110{
6111 //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)
6112 return RETURN_ERR;
6113}
6114
6115// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6116INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6117{
6118 snprintf(bridgeName, 32, "brlan0");
6119 snprintf(IP, 32, "10.0.0.1");
6120 snprintf(subnet, 32, "255.255.255.0");
6121
6122 return RETURN_OK;
6123}
6124
6125//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6126INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6127{
6128 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6129 return RETURN_ERR;
6130}
6131
6132// reset the vlan configuration for this ap
6133INT wifi_resetApVlanCfg(INT apIndex)
6134{
developerf5fef612022-09-20 19:38:26 +08006135 char original_config_file[64] = {0};
6136 char current_config_file[64] = {0};
6137 char buf[64] = {0};
6138 char cmd[64] = {0};
6139 char vlan_file[64] = {0};
6140 char vlan_tagged_interface[16] = {0};
6141 char vlan_bridge[16] = {0};
6142 char vlan_naming[16] = {0};
6143 struct params list[4] = {0};
6144 wifi_band band;
6145
6146 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6147
6148 band = wifi_index_to_band(apIndex);
6149 if (band == band_2_4)
6150 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006151 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08006152 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006153 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08006154 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6155
6156 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6157
6158 if (strlen(vlan_file) == 0)
6159 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08006160
developerf5fef612022-09-20 19:38:26 +08006161 // The file should exist or this vap would not work.
6162 if (access(vlan_file, F_OK) != 0) {
6163 sprintf(cmd, "touch %s", vlan_file);
6164 _syscmd(cmd, buf, sizeof(buf));
6165 }
6166 list[0].name = "vlan_file";
6167 list[0].value = vlan_file;
6168
6169 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6170 list[1].name = "vlan_tagged_interface";
6171 list[1].value = vlan_tagged_interface;
6172
6173 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6174 list[2].name = "vlan_bridge";
6175 list[2].value = vlan_bridge;
6176
6177 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6178 list[3].name = "vlan_naming";
6179 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08006180
developerf5fef612022-09-20 19:38:26 +08006181 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6182 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08006183 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08006184 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08006185
developerf5fef612022-09-20 19:38:26 +08006186 // restart this ap
6187 wifi_setApEnable(apIndex, FALSE);
6188 wifi_setApEnable(apIndex, TRUE);
6189
6190 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6191
6192 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006193}
6194
6195// 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.
6196INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6197{
6198 return RETURN_ERR;
6199}
6200
6201// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6202INT wifi_startHostApd()
6203{
6204 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6205 system("systemctl start hostapd.service");
6206 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6207 return RETURN_OK;
6208 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6209}
6210
6211// stops hostapd
6212INT wifi_stopHostApd()
6213{
6214 char cmd[128] = {0};
6215 char buf[128] = {0};
6216
6217 sprintf(cmd,"systemctl stop hostapd");
6218 _syscmd(cmd, buf, sizeof(buf));
6219
6220 return RETURN_OK;
6221}
6222
6223// restart hostapd dummy function
6224INT wifi_restartHostApd()
6225{
6226 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6227 system("systemctl restart hostapd-global");
6228 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6229
6230 return RETURN_OK;
6231}
6232
6233static int align_hostapd_config(int index)
6234{
6235 ULONG lval;
6236 wifi_getRadioChannel(index%2, &lval);
6237 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08006238 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006239}
6240
6241// sets the AP enable status variable for the specified ap.
6242INT wifi_setApEnable(INT apIndex, BOOL enable)
6243{
developerd946fd62022-12-08 18:03:28 +08006244 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006245 char config_file[MAX_BUF_SIZE] = {0};
6246 char cmd[MAX_CMD_SIZE] = {0};
6247 char buf[MAX_BUF_SIZE] = {0};
6248 BOOL status;
developer033b37b2022-10-18 11:27:46 +08006249 int max_radio_num = 0;
6250 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08006251
6252 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08006253
6254 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08006255 if (enable == status)
6256 return RETURN_OK;
6257
developerac6f1142022-12-20 19:26:35 +08006258 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006259 return RETURN_ERR;
6260
developer06a01d92022-09-07 16:32:39 +08006261 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08006262 int radioIndex = apIndex % max_radio_num;
6263 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08006264 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6265 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08006266 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006267 _syscmd(cmd, buf, sizeof(buf));
developer2f18b9f2023-03-17 19:32:57 +08006268 if (!(apIndex/max_radio_num)) {
6269 sprintf(cmd, "iw %s del", interface_name);
6270 _syscmd(cmd, buf, sizeof(buf));
6271 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6272 _syscmd(cmd, buf, sizeof(buf));
6273 }
developer439baa32024-05-02 15:54:58 +08006274 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 +08006275 _syscmd(cmd, buf, sizeof(buf));
6276 }
6277 else {
developerd946fd62022-12-08 18:03:28 +08006278 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006279 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006280 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006281 _syscmd(cmd, buf, sizeof(buf));
6282 }
developera77d84b2023-02-22 16:10:50 +08006283
developer431128d2022-12-16 15:30:41 +08006284 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006285 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006286 _syscmd(cmd, buf, sizeof(buf));
6287 //Wait for wifi up/down to apply
6288 return RETURN_OK;
6289}
6290
6291// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6292INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6293{
developerd946fd62022-12-08 18:03:28 +08006294 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006295 char cmd[MAX_CMD_SIZE] = {'\0'};
6296 char buf[MAX_BUF_SIZE] = {'\0'};
6297
6298 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6299 return RETURN_ERR;
6300
6301 *output_bool = 0;
6302
6303 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6304 {
developerac6f1142022-12-20 19:26:35 +08006305 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006306 *output_bool = FALSE;
6307 return RETURN_OK;
6308 }
6309 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006310 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6311 }
6312
6313 return RETURN_OK;
6314}
6315
6316// Outputs the AP "Enabled" "Disabled" status from driver
6317INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6318{
6319 char cmd[128] = {0};
6320 char buf[128] = {0};
6321 BOOL output_bool;
6322
6323 if ( NULL == output_string)
6324 return RETURN_ERR;
6325 wifi_getApEnable(apIndex,&output_bool);
6326
6327 if(output_bool == 1)
6328 snprintf(output_string, 32, "Up");
6329 else
6330 snprintf(output_string, 32, "Disable");
6331
6332 return RETURN_OK;
6333}
6334
6335//Indicates whether or not beacons include the SSID name.
6336// outputs a 1 if SSID on the AP is enabled, else outputs 0
6337INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6338{
6339 //get the running status
6340 char config_file[MAX_BUF_SIZE] = {0};
6341 char buf[16] = {0};
6342
6343 if (!output)
6344 return RETURN_ERR;
6345
6346 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006347 if (!syn_flag)
6348 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6349 else
developer07ded1f2024-01-10 10:30:15 +08006350 snprintf(buf, sizeof(buf), "%s",vap_info[apIndex].ignore_broadcast_ssid);
developer1d57d002022-10-12 18:03:15 +08006351 // default is enable
6352 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6353 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006354
6355 return RETURN_OK;
6356}
6357
6358// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6359INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6360{
6361 //store the config, apply instantly
6362 char config_file[MAX_BUF_SIZE] = {0};
6363 struct params list;
6364
6365 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6366 list.name = "ignore_broadcast_ssid";
6367 list.value = enable?"0":"1";
6368
6369 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6370 wifi_hostapdWrite(config_file, &list, 1);
6371 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6372 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006373 wifi_reloadAp(apIndex);
developerefb790a2023-12-26 18:58:32 +08006374 snprintf(vap_info[apIndex].ignore_broadcast_ssid, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08006375 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6376
6377 return RETURN_OK;
6378}
6379
6380//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6381INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6382{
6383 //get the running status
6384 if(!output_uint)
6385 return RETURN_ERR;
6386 *output_uint=16;
6387 return RETURN_OK;
6388}
6389
6390INT wifi_setApRetryLimit(INT apIndex, UINT number)
6391{
6392 //apply instantly
6393 return RETURN_ERR;
6394}
6395
6396//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6397INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6398{
6399 if(!output)
6400 return RETURN_ERR;
6401 *output=TRUE;
6402 return RETURN_OK;
6403}
6404
6405//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6406INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6407{
6408 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006409 char cmd[128] = {0};
6410 char buf[128] = {0};
6411 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006412 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006413
developer0b246d12022-09-30 15:24:20 +08006414 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006415
developer0b246d12022-09-30 15:24:20 +08006416 wifi_getMaxRadioNumber(&max_radio_num);
6417 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006418 phyId = radio_index_to_phy(radioIndex);
6419 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006420 _syscmd(cmd,buf, sizeof(buf));
6421
6422 if (strlen(buf) > 0)
6423 *output = true;
6424
6425 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006426
developer06a01d92022-09-07 16:32:39 +08006427 return RETURN_OK;
6428}
6429
6430//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6431INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6432{
6433 //get the running status from driver
6434 if(!output)
6435 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006436
6437 char config_file[MAX_BUF_SIZE] = {0};
6438 char buf[16] = {0};
6439
6440 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6441 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006442 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006443 *output = TRUE;
6444 else
6445 *output = FALSE;
6446
developer06a01d92022-09-07 16:32:39 +08006447 return RETURN_OK;
6448}
6449
6450// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6451INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6452{
6453 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006454 char config_file[MAX_BUF_SIZE] = {0};
6455 struct params list;
6456
6457 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6458 list.name = "wmm_enabled";
6459 list.value = enable?"1":"0";
6460
6461 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6462 wifi_hostapdWrite(config_file, &list, 1);
6463 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6464 wifi_reloadAp(apIndex);
6465 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6466
6467 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006468}
6469
6470//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.
6471INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6472{
6473 //get the running status from driver
6474 if(!output)
6475 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006476
6477 char config_file[128] = {0};
6478 char buf[16] = {0};
6479
6480 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6481 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6482 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6483 *output = TRUE;
6484 else
6485 *output = FALSE;
6486
developer06a01d92022-09-07 16:32:39 +08006487 return RETURN_OK;
6488}
6489
6490// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6491INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6492{
6493 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006494 char config_file[MAX_BUF_SIZE] = {0};
6495 struct params list;
6496
6497 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6498 list.name = "uapsd_advertisement_enabled";
6499 list.value = enable?"1":"0";
6500
6501 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6502 wifi_hostapdWrite(config_file, &list, 1);
6503 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6504 wifi_reloadAp(apIndex);
6505 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6506
6507 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006508}
6509
developer6daeb3f2022-09-30 13:36:39 +08006510// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006511INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6512{
developerd946fd62022-12-08 18:03:28 +08006513 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006514 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6515 char cmd[128] = {0};
6516 char buf[128] = {0};
6517 char ack_filepath[128] = {0};
6518 uint16_t bitmap = 0;
6519 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6520 FILE *f = NULL;
6521
6522 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6523
6524 // Get current setting
6525 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6526 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6527 _syscmd(cmd, buf, sizeof(buf));
6528 if (strlen(buf) > 0)
6529 bitmap = strtoul(buf, NULL, 10);
6530
6531 bitmap = strtoul(buf, NULL, 10);
6532
6533 if (ackPolicy == TRUE) { // True, unset this class
6534 bitmap &= ~class_map[class];
6535 } else { // False, set this class
6536 bitmap |= class_map[class];
6537 }
6538
6539 f = fopen(ack_filepath, "w");
6540 if (f == NULL) {
6541 fprintf(stderr, "%s: fopen failed\n", __func__);
6542 return RETURN_ERR;
6543 }
6544 fprintf(f, "%hu", bitmap);
6545 fclose(f);
6546
developerac6f1142022-12-20 19:26:35 +08006547 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006548 return RETURN_ERR;
6549 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006550 _syscmd(cmd, buf, sizeof(buf));
6551
6552 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6553 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006554}
6555
6556//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.
6557INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6558{
6559 //get the running status from driver
6560 if(!output_uint)
6561 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006562
6563 char output[16]={'\0'};
6564 char config_file[MAX_BUF_SIZE] = {0};
6565
6566 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08006567 if (!syn_flag)
6568 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6569 else
developer07ded1f2024-01-10 10:30:15 +08006570 snprintf(output, sizeof(output), "%s", vap_info[apIndex].max_sta);
developer0947e1a2022-09-13 14:15:25 +08006571 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6572 else {
6573 int device_num = atoi(output);
6574 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6575 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6576 return RETURN_ERR;
6577 }
6578 else {
6579 *output_uint = device_num;
6580 }
6581 }
6582
developer06a01d92022-09-07 16:32:39 +08006583 return RETURN_OK;
6584}
6585
6586INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6587{
6588 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006589 char str[MAX_BUF_SIZE]={'\0'};
6590 char cmd[MAX_CMD_SIZE]={'\0'};
6591 struct params params;
6592 char config_file[MAX_BUF_SIZE] = {0};
6593
6594 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006595 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006596 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006597 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006598 }
6599 sprintf(str, "%d", number);
6600 params.name = "max_num_sta";
6601 params.value = str;
6602
6603 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6604 int ret = wifi_hostapdWrite(config_file, &params, 1);
6605 if (ret) {
6606 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6607 ,__func__, ret);
6608 }
6609
6610 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6611 if (ret) {
6612 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6613 ,__func__, ret);
6614 }
6615 wifi_reloadAp(apIndex);
6616 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6617
6618 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006619}
6620
6621//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.
6622INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6623{
6624 //get the current threshold
6625 if(!output_uint)
6626 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006627 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6628 if (*output_uint == 0)
6629 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006630 return RETURN_OK;
6631}
6632
6633INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6634{
6635 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006636 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6637 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006638 return RETURN_ERR;
6639}
6640
6641//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.
6642INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6643{
6644 if(!output_uint)
6645 return RETURN_ERR;
6646 *output_uint = 3;
6647 return RETURN_OK;
6648}
6649
6650//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6651INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6652{
6653 if(!output_uint)
6654 return RETURN_ERR;
6655 *output_uint = 3;
6656 return RETURN_OK;
6657}
6658
6659//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.
6660INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6661{
6662 if(!output_in_seconds)
6663 return RETURN_ERR;
6664 *output_in_seconds = 0;
6665 return RETURN_OK;
6666}
6667
6668//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
6669INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6670{
6671 if(!output || apIndex>=MAX_APS)
6672 return RETURN_ERR;
6673 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006674 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006675 return RETURN_OK;
6676}
6677
6678//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6679INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6680{
developer587c1b62022-09-27 15:58:59 +08006681 char config_file[128] = {0};
6682 char wpa[16] = {0};
6683 char key_mgmt[64] = {0};
6684 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006685 if (!output)
6686 return RETURN_ERR;
6687
6688 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08006689 if (!syn_flag)
6690 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6691 else
developer07ded1f2024-01-10 10:30:15 +08006692 snprintf(wpa, sizeof(wpa), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006693
developer587c1b62022-09-27 15:58:59 +08006694 strcpy(output, "None");//Copying "None" to output string for default case
developerefb790a2023-12-26 18:58:32 +08006695 if (!syn_flag)
6696 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6697 else
developer07ded1f2024-01-10 10:30:15 +08006698 snprintf(key_mgmt, sizeof(key_mgmt), "%s", vap_info[apIndex].wpa_key_mgmt);
developer4a359672022-10-13 15:30:46 +08006699 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006700 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006701 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006702 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006703 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006704 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006705 snprintf(output, 32, "WPA-WPA2-Personal");
6706
developer72ec5572023-01-05 16:27:13 +08006707 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6708 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006709 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006710 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006711 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006712 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006713 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006714 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006715 snprintf(output, 32, "WPA-WPA2-Enterprise");
6716 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006717 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006718 snprintf(output, 32, "WPA3-Personal");
6719 else
developer4a359672022-10-13 15:30:46 +08006720 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006721 }
developer06a01d92022-09-07 16:32:39 +08006722
6723 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6724 return RETURN_OK;
6725#if 0
6726 //TODO: need to revisit below implementation
6727 char securityType[32], authMode[32];
6728 int enterpriseMode=0;
6729
6730 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6731 if(!output)
6732 return RETURN_ERR;
6733
6734 wifi_getApBeaconType(apIndex, securityType);
6735 strcpy(output,"None");//By default, copying "None" to output string
6736 if (strncmp(securityType,"None", strlen("None")) == 0)
6737 return RETURN_OK;
6738
6739 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6740 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6741
6742 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6743 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6744 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6745 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6746 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6747 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6748 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6749
6750 return RETURN_OK;
6751#endif
6752}
6753
6754INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6755{
6756 char securityType[32];
6757 char authMode[32];
6758
6759 //store settings and wait for wifi up to apply
6760 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6761 if(!encMode)
6762 return RETURN_ERR;
6763
developer06a01d92022-09-07 16:32:39 +08006764 if (strcmp(encMode, "None")==0)
6765 {
6766 strcpy(securityType,"None");
6767 strcpy(authMode,"None");
6768 }
6769 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6770 {
6771 strcpy(securityType,"WPAand11i");
6772 strcpy(authMode,"PSKAuthentication");
6773 }
6774 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6775 {
6776 strcpy(securityType,"WPAand11i");
6777 strcpy(authMode,"EAPAuthentication");
6778 }
6779 else if (strcmp(encMode, "WPA-Personal")==0)
6780 {
6781 strcpy(securityType,"WPA");
6782 strcpy(authMode,"PSKAuthentication");
6783 }
6784 else if (strcmp(encMode, "WPA-Enterprise")==0)
6785 {
6786 strcpy(securityType,"WPA");
6787 strcpy(authMode,"EAPAuthentication");
6788 }
6789 else if (strcmp(encMode, "WPA2-Personal")==0)
6790 {
6791 strcpy(securityType,"11i");
6792 strcpy(authMode,"PSKAuthentication");
6793 }
6794 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6795 {
6796 strcpy(securityType,"11i");
6797 strcpy(authMode,"EAPAuthentication");
6798 }
developer587c1b62022-09-27 15:58:59 +08006799 else if (strcmp(encMode, "WPA3-Personal") == 0)
6800 {
6801 strcpy(securityType,"11i");
6802 strcpy(authMode,"SAEAuthentication");
6803 }
developer4a359672022-10-13 15:30:46 +08006804 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006805 {
6806 strcpy(securityType, "11i");
6807 strcpy(authMode, "PSK-SAEAuthentication");
6808 }
developer587c1b62022-09-27 15:58:59 +08006809 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6810 {
6811 strcpy(securityType,"11i");
6812 strcpy(authMode,"EAP_192-bit_Authentication");
6813 }
developer5c9fee82023-01-13 14:44:16 +08006814 else if (strcmp(encMode, "OWE") == 0)
6815 {
6816 strcpy(securityType,"11i");
6817 strcpy(authMode,"Enhanced_Open");
6818 }
developer06a01d92022-09-07 16:32:39 +08006819 else
6820 {
6821 strcpy(securityType,"None");
6822 strcpy(authMode,"None");
6823 }
6824 wifi_setApBeaconType(apIndex, securityType);
6825 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6826 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6827
6828 return RETURN_OK;
6829}
6830
6831
developer4b102122023-02-15 10:53:03 +08006832// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006833//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006834INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6835{
developer30423732022-12-01 16:17:49 +08006836 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006837 char config_file[MAX_BUF_SIZE] = {0};
6838
6839 if(output_string==NULL)
6840 return RETURN_ERR;
6841
6842 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006843 if (!syn_flag)
6844 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6845 else
developer07ded1f2024-01-10 10:30:15 +08006846 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006847 if(strcmp(buf,"0")==0)
6848 {
6849 printf("wpa_mode is %s ......... \n",buf);
6850 return RETURN_ERR;
6851 }
6852
6853 wifi_dbg_printf("\nFunc=%s\n",__func__);
6854 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006855 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006856 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6857
6858 return RETURN_OK;
6859}
6860
developer4b102122023-02-15 10:53:03 +08006861// Set PreSharedKey associated with a Access Point.
6862// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006863INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6864{
6865 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6866 struct params params={'\0'};
6867 int ret;
6868 char config_file[MAX_BUF_SIZE] = {0};
6869
6870 if(NULL == preSharedKey)
6871 return RETURN_ERR;
6872
developer4b102122023-02-15 10:53:03 +08006873 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006874
developer4b102122023-02-15 10:53:03 +08006875 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006876 {
developer4b102122023-02-15 10:53:03 +08006877 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006878 return RETURN_ERR;
6879 }
6880 params.value = preSharedKey;
6881 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6882 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006883 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006884 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006885 wifi_reloadAp(apIndex);
6886 }
developer06a01d92022-09-07 16:32:39 +08006887 return ret;
6888 //TODO: call hostapd_cli for dynamic_config_control
6889}
6890
6891//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6892// outputs the passphrase, maximum 63 characters
6893INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6894{
6895 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6896
6897 wifi_dbg_printf("\nFunc=%s\n",__func__);
6898 if (NULL == output_string)
6899 return RETURN_ERR;
6900
6901 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08006902 if (!syn_flag)
6903 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6904 else
developer07ded1f2024-01-10 10:30:15 +08006905 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].wpa);
developer06a01d92022-09-07 16:32:39 +08006906 if(strcmp(buf,"0")==0)
6907 {
6908 printf("wpa_mode is %s ......... \n",buf);
6909 return RETURN_ERR;
6910 }
6911
developerefb790a2023-12-26 18:58:32 +08006912 if (!syn_flag)
6913 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6914 else
developer07ded1f2024-01-10 10:30:15 +08006915 snprintf(output_string, 64, "%s", vap_info[apIndex].wpa_passphrase);
developer06a01d92022-09-07 16:32:39 +08006916 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6917
6918 return RETURN_OK;
6919}
6920
6921// sets the passphrase enviornment variable, max 63 characters
6922INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6923{
6924 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6925 struct params params={'\0'};
6926 char config_file[MAX_BUF_SIZE] = {0};
6927 int ret;
6928
6929 if(NULL == passPhrase)
6930 return RETURN_ERR;
6931
6932 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6933 {
6934 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6935 return RETURN_ERR;
6936 }
6937 params.name = "wpa_passphrase";
6938 params.value = passPhrase;
6939 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6940 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006941 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006942 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006943 wifi_reloadAp(apIndex);
6944 }
developerefb790a2023-12-26 18:58:32 +08006945 snprintf(vap_info[apIndex].wpa_passphrase, MAX_BUF_SIZE, "%s", passPhrase);
developer06a01d92022-09-07 16:32:39 +08006946
6947 return ret;
6948}
6949
6950//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.
6951INT wifi_setApSecurityReset(INT apIndex)
6952{
developer8d583982022-09-20 11:28:22 +08006953 char original_config_file[64] = {0};
6954 char current_config_file[64] = {0};
6955 char buf[64] = {0};
6956 char cmd[64] = {0};
6957 char wpa[4] = {0};
6958 char wpa_psk[64] = {0};
6959 char wpa_passphrase[64] = {0};
6960 char wpa_psk_file[128] = {0};
6961 char wpa_key_mgmt[64] = {0};
6962 char wpa_pairwise[32] = {0};
6963 wifi_band band;
6964 struct params list[6];
6965
6966 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6967
6968 band = wifi_index_to_band(apIndex);
6969 if (band == band_2_4)
6970 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006971 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006972 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006973 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006974 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6975 else
6976 return RETURN_ERR;
6977
6978 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6979 list[0].name = "wpa";
6980 list[0].value = wpa;
6981
6982 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6983 list[1].name = "wpa_psk";
6984 list[1].value = wpa_psk;
6985
6986 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6987 list[2].name = "wpa_passphrase";
6988 list[2].value = wpa_passphrase;
6989
6990 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6991
6992 if (strlen(wpa_psk_file) == 0)
6993 strcpy(wpa_psk_file, PSK_FILE);
6994
6995 if (access(wpa_psk_file, F_OK) != 0) {
6996 sprintf(cmd, "touch %s", wpa_psk_file);
6997 _syscmd(cmd, buf, sizeof(buf));
6998 }
6999 list[3].name = "wpa_psk_file";
7000 list[3].value = wpa_psk_file;
7001
7002 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
7003 list[4].name = "wpa_key_mgmt";
7004 list[4].value = wpa_key_mgmt;
7005
7006 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
7007 list[5].name = "wpa_pairwise";
7008 list[5].value = wpa_pairwise;
7009
7010 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7011 wifi_hostapdWrite(current_config_file, list, 6);
7012
7013 wifi_setApEnable(apIndex, FALSE);
7014 wifi_setApEnable(apIndex, TRUE);
7015
7016 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7017 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007018}
7019
7020//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).
7021INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7022{
developer8f2ddd52022-09-13 15:39:24 +08007023 char config_file[64] = {0};
7024 char buf[64] = {0};
7025 char cmd[256] = {0};
7026
7027 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7028
developer06a01d92022-09-07 16:32:39 +08007029 if(!IP_output || !Port_output || !RadiusSecret_output)
7030 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08007031
developer8f2ddd52022-09-13 15:39:24 +08007032 // Read the first matched config
7033 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7034 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7035 _syscmd(cmd, buf, sizeof(buf));
7036 strncpy(IP_output, buf, 64);
7037
7038 memset(buf, 0, sizeof(buf));
7039 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7040 _syscmd(cmd, buf, sizeof(buf));
7041 *Port_output = atoi(buf);
7042
7043 memset(buf, 0, sizeof(buf));
7044 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7045 _syscmd(cmd, buf, sizeof(buf));
7046 strncpy(RadiusSecret_output, buf, 64);
7047
7048 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007049 return RETURN_OK;
7050}
7051
7052INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7053{
developer8f2ddd52022-09-13 15:39:24 +08007054 char config_file[64] = {0};
7055 char port_str[8] = {0};
7056 char cmd[256] = {0};
7057 char buf[128] = {0};
7058
7059 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007060 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7061 return RETURN_ERR;
7062
7063 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7064 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007065
7066 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7067
7068 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7069 _syscmd(cmd, buf, sizeof(buf));
7070 memset(cmd, 0, sizeof(cmd));
7071
7072 snprintf(port_str, sizeof(port_str), "%d", port);
7073 if (strlen(buf) == 0)
7074 // Append
7075 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7076 "auth_server_addr=%s\\n"
7077 "auth_server_port=%s\\n"
7078 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7079 else {
7080 // Delete the three lines setting after the "# radius 1" comment
7081 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7082 _syscmd(cmd, buf, sizeof(buf));
7083 memset(cmd, 0, sizeof(cmd));
7084 // Use "# radius 1" comment to find the location to insert the radius setting
7085 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7086 "# radius 1\\n"
7087 "auth_server_addr=%s\\n"
7088 "auth_server_port=%s\\n"
7089 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7090 }
7091 if(_syscmd(cmd, buf, sizeof(buf))) {
7092 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7093 return RETURN_ERR;
7094 }
7095
7096 wifi_reloadAp(apIndex);
7097 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7098 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007099}
7100
7101INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7102{
developer8f2ddd52022-09-13 15:39:24 +08007103 char config_file[64] = {0};
7104 char buf[64] = {0};
7105 char cmd[256] = {0};
7106
7107 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7108
developer06a01d92022-09-07 16:32:39 +08007109 if(!IP_output || !Port_output || !RadiusSecret_output)
7110 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007111
7112 // Read the second matched config
7113 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7114 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7115 _syscmd(cmd, buf, sizeof(buf));
7116 strncpy(IP_output, buf, 64);
7117
7118 memset(buf, 0, sizeof(buf));
7119 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7120 _syscmd(cmd, buf, sizeof(buf));
7121 *Port_output = atoi(buf);
7122
7123 memset(buf, 0, sizeof(buf));
7124 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7125 _syscmd(cmd, buf, sizeof(buf));
7126 strncpy(RadiusSecret_output, buf, 64);
7127
7128 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007129 return RETURN_OK;
7130}
7131
7132INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7133{
developer8f2ddd52022-09-13 15:39:24 +08007134 char config_file[64] = {0};
7135 char port_str[8] = {0};
7136 char cmd[256] = {0};
7137 char buf[128] = {0};
7138
7139 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007140 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7141 return RETURN_ERR;
7142
7143 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7144 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007145
7146 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7147
7148 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7149 _syscmd(cmd, buf, sizeof(buf));
7150 memset(cmd, 0, sizeof(cmd));
7151
7152 snprintf(port_str, sizeof(port_str), "%d", port);
7153 if (strlen(buf) == 0)
7154 // Append
7155 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7156 "auth_server_addr=%s\\n"
7157 "auth_server_port=%s\\n"
7158 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7159 else {
7160 // Delete the three lines setting after the "# radius 2" comment
7161 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7162 _syscmd(cmd, buf, sizeof(buf));
7163 memset(cmd, 0, sizeof(cmd));
7164 // Use "# radius 2" comment to find the location to insert the radius setting
7165 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7166 "# radius 2\\n"
7167 "auth_server_addr=%s\\n"
7168 "auth_server_port=%s\\n"
7169 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7170 }
7171 if(_syscmd(cmd, buf, sizeof(buf))) {
7172 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7173 return RETURN_ERR;
7174 }
7175
7176 wifi_reloadAp(apIndex);
7177 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7178 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007179}
7180
7181//RadiusSettings
7182INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7183{
7184 if(!output)
7185 return RETURN_ERR;
7186
7187 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7188 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7189 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7190 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7191 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7192 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.
7193 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7194 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7195 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7196 //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.
7197
7198 return RETURN_OK;
7199}
7200
7201INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7202{
7203 //store the paramters, and apply instantly
7204 return RETURN_ERR;
7205}
7206
7207//Device.WiFi.AccessPoint.{i}.WPS.Enable
7208//Enables or disables WPS functionality for this access point.
7209// outputs the WPS enable state of this ap in output_bool
7210INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7211{
developerd946fd62022-12-08 18:03:28 +08007212 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007213 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer613892e2023-09-21 16:33:35 +08007214
7215 *output_bool=FALSE;
developer5b398df2022-11-17 20:39:48 +08007216 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08007217 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08007218 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer613892e2023-09-21 16:33:35 +08007219 return RETURN_OK;
developerd946fd62022-12-08 18:03:28 +08007220 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007221 _syscmd(cmd, buf, sizeof(buf));
7222 if(strstr(buf, "configured"))
7223 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08007224
7225 return RETURN_OK;
developer613892e2023-09-21 16:33:35 +08007226}
developer06a01d92022-09-07 16:32:39 +08007227
7228//Device.WiFi.AccessPoint.{i}.WPS.Enable
7229// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7230INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7231{
7232 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08007233 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08007234 struct params params;
7235
developer06a01d92022-09-07 16:32:39 +08007236 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7237 //store the paramters, and wait for wifi up to apply
7238 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08007239 if (enable == TRUE) {
7240 wifi_getApBeaconType(apIndex, buf);
7241 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7242 params.value = "1";
7243 else // If ap set encryption
7244 params.value = "2";
7245 } else {
7246 params.value = "0";
7247 }
developer06a01d92022-09-07 16:32:39 +08007248
7249 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7250 wifi_hostapdWrite(config_file, &params, 1);
7251 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7252 wifi_reloadAp(apIndex);
7253
7254 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7255 return RETURN_OK;
7256}
7257
7258//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
7259INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7260{
7261 if(!output)
7262 return RETURN_ERR;
7263 snprintf(output, 128, "PushButton,PIN");
7264 return RETURN_OK;
7265}
7266
7267//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7268//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.
7269// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7270INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7271{
7272 if(!output)
7273 return RETURN_ERR;
7274 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7275
7276 return RETURN_OK;
7277}
7278
7279//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7280// 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
7281INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7282{
7283 //apply instantly. No setting need to be stored.
7284 char methods[MAX_BUF_SIZE], *token, *next_token;
7285 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7286 struct params params;
7287
developer5b398df2022-11-17 20:39:48 +08007288 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08007289 return RETURN_ERR;
7290 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7291 //store the paramters, and wait for wifi up to apply
7292
7293 snprintf(methods, sizeof(methods), "%s", methodString);
7294 for(token=methods; *token; token=next_token)
7295 {
7296 strtok_r(token, ",", &next_token);
7297 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7298 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7299 else if(*token=='E')
7300 {
7301 if(!strcmp(methods, "Ethernet"))
7302 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7303 else if(!strcmp(methods, "ExternalNFCToken"))
7304 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7305 else
7306 printf("%s: Unknown WpsConfigMethod\n", __func__);
7307 }
7308 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7309 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7310 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7311 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7312 else if(*token=='P' )
7313 {
7314 if(!strcmp(token, "PushButton"))
developer894affa2023-05-10 18:13:19 +08007315 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer06a01d92022-09-07 16:32:39 +08007316 else if(!strcmp(token, "PIN"))
7317 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7318 else
7319 printf("%s: Unknown WpsConfigMethod\n", __func__);
7320 }
7321 else
7322 printf("%s: Unknown WpsConfigMethod\n", __func__);
7323 }
7324 params.name = "config_methods";
7325 params.value = config_methods;
7326 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7327 wifi_hostapdWrite(config_file, &params, 1);
7328 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7330
7331 return RETURN_OK;
7332}
7333
7334// outputs the pin value, ulong_pin must be allocated by the caller
7335INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7336{
7337 char buf[MAX_BUF_SIZE] = {0};
7338 char cmd[MAX_CMD_SIZE] = {0};
7339
developer5b398df2022-11-17 20:39:48 +08007340 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007341 return RETURN_ERR;
7342 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7343 _syscmd(cmd, buf, sizeof(buf));
7344 if(strlen(buf) > 0)
7345 *output_ulong=strtoul(buf, NULL, 10);
7346
7347 return RETURN_OK;
7348}
7349
7350// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7351INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7352{
7353 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7354 char ap_pin[16] = {0};
7355 char buf[MAX_BUF_SIZE] = {0};
7356 char config_file[MAX_BUF_SIZE] = {0};
7357 ULONG prev_pin = 0;
7358 struct params params;
7359
developer06a01d92022-09-07 16:32:39 +08007360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7361 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7362 params.name = "ap_pin";
7363 params.value = ap_pin;
7364 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7365 wifi_hostapdWrite(config_file, &params, 1);
7366 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7367 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7368
7369 return RETURN_OK;
7370}
7371
7372// Output string is either Not configured or Configured, max 32 characters
7373INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7374{
developerd946fd62022-12-08 18:03:28 +08007375 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007376 char cmd[MAX_CMD_SIZE];
7377 char buf[MAX_BUF_SIZE]={0};
7378
developer5b398df2022-11-17 20:39:48 +08007379 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007380 return RETURN_ERR;
7381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7382 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007383 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007384 return RETURN_ERR;
7385 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007386 _syscmd(cmd, buf, sizeof(buf));
7387
developer348e3d92022-09-13 14:48:41 +08007388 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007389 snprintf(output_string, 32, "Configured");
7390 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7391
7392 return RETURN_OK;
7393}
7394
7395// sets the WPS pin for this AP
7396INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7397{
developerd946fd62022-12-08 18:03:28 +08007398 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007399 char cmd[MAX_CMD_SIZE];
7400 char buf[MAX_BUF_SIZE]={0};
7401 BOOL enable;
7402
developer06a01d92022-09-07 16:32:39 +08007403 wifi_getApEnable(apIndex, &enable);
7404 if (!enable)
7405 return RETURN_ERR;
7406 wifi_getApWpsEnable(apIndex, &enable);
7407 if (!enable)
7408 return RETURN_ERR;
7409
developerac6f1142022-12-20 19:26:35 +08007410 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007411 return RETURN_ERR;
7412 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007413 _syscmd(cmd, buf, sizeof(buf));
7414 if((strstr(buf, "OK"))!=NULL)
7415 return RETURN_OK;
7416
7417 return RETURN_ERR;
7418}
7419
7420// This function is called when the WPS push button has been pressed for this AP
7421INT wifi_setApWpsButtonPush(INT apIndex)
7422{
7423 char cmd[MAX_CMD_SIZE];
7424 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007425 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007426 BOOL enable=FALSE;
7427
developer06a01d92022-09-07 16:32:39 +08007428 wifi_getApEnable(apIndex, &enable);
7429 if (!enable)
7430 return RETURN_ERR;
7431
7432 wifi_getApWpsEnable(apIndex, &enable);
7433 if (!enable)
7434 return RETURN_ERR;
7435
developerac6f1142022-12-20 19:26:35 +08007436 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007437 return RETURN_ERR;
7438
developer900e2b72023-05-23 10:23:48 +08007439 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 +08007440 _syscmd(cmd, buf, sizeof(buf));
7441
7442 if((strstr(buf, "OK"))!=NULL)
7443 return RETURN_OK;
7444 return RETURN_ERR;
7445}
7446
7447// cancels WPS mode for this AP
7448INT wifi_cancelApWPS(INT apIndex)
7449{
developerd946fd62022-12-08 18:03:28 +08007450 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007451 char cmd[MAX_CMD_SIZE];
7452 char buf[MAX_BUF_SIZE]={0};
7453
developerac6f1142022-12-20 19:26:35 +08007454 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007455 return RETURN_ERR;
7456 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007457 _syscmd(cmd,buf, sizeof(buf));
7458
7459 if((strstr(buf, "OK"))!=NULL)
7460 return RETURN_OK;
7461 return RETURN_ERR;
7462}
7463
7464//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7465//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7466INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7467{
developerd946fd62022-12-08 18:03:28 +08007468 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007469 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007470 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007471 char cmd[256] = {0}, buf[2048] = {0};
7472 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007473 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007474 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007475 wifi_associated_dev_t *dev=NULL;
7476
7477 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7478 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007479 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007480 return RETURN_ERR;
7481 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007482 _syscmd(cmd,buf,sizeof(buf));
7483 *output_array_size = atoi(buf);
7484
7485 if (*output_array_size <= 0)
7486 return RETURN_OK;
7487
7488 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7489 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007490 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007491 _syscmd(cmd,buf,sizeof(buf));
7492 f = fopen("/tmp/connected_devices.txt", "r");
7493 if (f==NULL)
7494 {
7495 *output_array_size=0;
7496 return RETURN_ERR;
7497 }
developer30423732022-12-01 16:17:49 +08007498 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007499 {
7500 param = strtok(line,"=");
7501 value = strtok(NULL,"=");
7502
7503 if( strcmp("flags",param) == 0 )
7504 {
7505 value[strlen(value)-1]='\0';
7506 if(strstr (value,"AUTHORIZED") != NULL )
7507 {
7508 dev[auth_temp].cli_AuthenticationState = 1;
7509 dev[auth_temp].cli_Active = 1;
7510 auth_temp++;
7511 read_flag=1;
7512 }
7513 }
7514 if(read_flag==1)
7515 {
7516 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7517 {
7518 value[strlen(value)-1]='\0';
7519 sscanf(value, "%x:%x:%x:%x:%x:%x",
7520 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7521 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7522 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7523 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7524 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7525 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7526 mac_temp++;
7527 read_flag=0;
7528 }
7529 }
7530 }
7531 *output_array_size = auth_temp;
7532 auth_temp=0;
7533 mac_temp=0;
7534 free(line);
7535 fclose(f);
7536 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7537 return RETURN_OK;
7538}
7539
7540#define MACADDRESS_SIZE 6
7541
7542INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7543{
7544 FILE *fp = NULL;
7545 char str[MAX_BUF_SIZE] = {0};
7546 int wificlientindex = 0 ;
7547 int count = 0;
7548 int signalstrength = 0;
7549 int arr[MACADDRESS_SIZE] = {0};
7550 unsigned char mac[MACADDRESS_SIZE] = {0};
7551 UINT wifi_count = 0;
7552 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7553 char pipeCmd[MAX_CMD_SIZE] = {0};
7554
7555 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7556 *output_array_size = 0;
7557 *associated_dev_array = NULL;
7558
7559 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7560 fp = popen(pipeCmd, "r");
7561 if (fp == NULL)
7562 {
7563 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7564 return RETURN_ERR;
7565 }
7566
7567 /* Read the output a line at a time - output it. */
7568 fgets(str, sizeof(str)-1, fp);
7569 wifi_count = (unsigned int) atoi ( str );
7570 *output_array_size = wifi_count;
7571 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7572 pclose(fp);
7573
7574 if(wifi_count == 0)
7575 {
7576 return RETURN_OK;
7577 }
7578 else
7579 {
7580 wifi_associated_dev3_t* temp = NULL;
7581 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7582 if(temp == NULL)
7583 {
7584 printf("Error Statement. Insufficient memory \n");
7585 return RETURN_ERR;
7586 }
7587
7588 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7589 system(pipeCmd);
7590 memset(pipeCmd,0,sizeof(pipeCmd));
7591 if(apIndex == 0)
7592 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7593 else if(apIndex == 1)
7594 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7595 system(pipeCmd);
7596
7597 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7598 if(fp == NULL)
7599 {
7600 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007601 free(temp);
developer06a01d92022-09-07 16:32:39 +08007602 return RETURN_ERR;
7603 }
7604 fclose(fp);
7605
developer30423732022-12-01 16:17:49 +08007606 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007607 fp = popen(pipeCmd, "r");
7608 if(fp)
7609 {
7610 for(count =0 ; count < wifi_count; count++)
7611 {
7612 fgets(str, MAX_BUF_SIZE, fp);
7613 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7614 {
7615 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7616 {
7617 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7618
7619 }
7620 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7621 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]);
7622 }
7623 temp[count].cli_AuthenticationState = 1; //TODO
7624 temp[count].cli_Active = 1; //TODO
7625 }
7626 pclose(fp);
7627 }
7628
developer30423732022-12-01 16:17:49 +08007629 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 +08007630 fp = popen(pipeCmd, "r");
7631 if(fp)
7632 {
7633 pclose(fp);
7634 }
7635 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7636 if(fp)
7637 {
7638 for(count =0 ; count < wifi_count ;count++)
7639 {
7640 fgets(str, MAX_BUF_SIZE, fp);
7641 signalstrength = atoi(str);
7642 temp[count].cli_SignalStrength = signalstrength;
7643 temp[count].cli_RSSI = signalstrength;
7644 temp[count].cli_SNR = signalstrength + 95;
7645 }
7646 pclose(fp);
7647 }
7648
7649
7650 if((apIndex == 0) || (apIndex == 4))
7651 {
7652 for(count =0 ; count < wifi_count ;count++)
7653 {
7654 strcpy(temp[count].cli_OperatingStandard,"g");
7655 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7656 }
7657
7658 //BytesSent
developer30423732022-12-01 16:17:49 +08007659 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 +08007660 fp = popen(pipeCmd, "r");
7661 if(fp)
7662 {
7663 pclose(fp);
7664 }
7665 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7666 if(fp)
7667 {
7668 for (count = 0; count < wifi_count; count++)
7669 {
7670 fgets(str, MAX_BUF_SIZE, fp);
7671 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7672 }
7673 pclose(fp);
7674 }
7675
7676 //BytesReceived
developer30423732022-12-01 16:17:49 +08007677 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 +08007678 fp = popen(pipeCmd, "r");
7679 if (fp)
7680 {
7681 pclose(fp);
7682 }
7683 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7684 if (fp)
7685 {
7686 for (count = 0; count < wifi_count; count++)
7687 {
7688 fgets(str, MAX_BUF_SIZE, fp);
7689 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7690 }
7691 pclose(fp);
7692 }
7693
7694 //PacketsSent
developer30423732022-12-01 16:17:49 +08007695 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 +08007696 fp = popen(pipeCmd, "r");
7697 if (fp)
7698 {
7699 pclose(fp);
7700 }
7701
7702 fp = popen("cat /tmp/Ass_Packets_Send.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_PacketsSent = strtoul(str, NULL, 10);
7709 }
7710 pclose(fp);
7711 }
7712
7713 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007714 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 +08007715 fp = popen(pipeCmd, "r");
7716 if (fp)
7717 {
7718 pclose(fp);
7719 }
7720 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7721 if (fp)
7722 {
7723 for (count = 0; count < wifi_count; count++)
7724 {
7725 fgets(str, MAX_BUF_SIZE, fp);
7726 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7727 }
7728 pclose(fp);
7729 }
7730
7731 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007732 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 +08007733 fp = popen(pipeCmd, "r");
7734 if (fp)
7735 {
7736 pclose(fp);
7737 }
7738 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7739 if (fp)
7740 {
7741 for (count = 0; count < wifi_count; count++)
7742 {
7743 fgets(str, MAX_BUF_SIZE, fp);
7744 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7745 }
7746 pclose(fp);
7747 }
7748
7749 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007750 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 +08007751 fp = popen(pipeCmd, "r");
7752 if (fp)
7753 {
7754 pclose(fp);
7755 }
7756 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7757 if (fp)
7758 {
7759 for (count = 0; count < wifi_count; count++)
7760 {
7761 fgets(str, MAX_BUF_SIZE, fp);
7762 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7763 }
7764 pclose(fp);
7765 }
7766
7767 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007768 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 +08007769 fp = popen(pipeCmd, "r");
7770 if (fp)
7771 {
7772 pclose(fp);
7773 }
7774 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7775 if (fp)
7776 {
7777 for (count = 0; count < wifi_count; count++)
7778 {
7779 fgets(str, MAX_BUF_SIZE, fp);
7780 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7781 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7782 }
7783 pclose(fp);
7784 }
7785
7786 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007787 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 +08007788 fp = popen(pipeCmd, "r");
7789 if (fp)
7790 {
7791 pclose(fp);
7792 }
7793 fp = popen("cat /tmp/Ass_Bitrate_Received.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_LastDataUplinkRate = strtoul(str, NULL, 10);
7800 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7801 }
7802 pclose(fp);
7803 }
7804
7805 }
7806 else if ((apIndex == 1) || (apIndex == 5))
7807 {
7808 for (count = 0; count < wifi_count; count++)
7809 {
7810 strcpy(temp[count].cli_OperatingStandard, "a");
7811 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7812 temp[count].cli_BytesSent = 0;
7813 temp[count].cli_BytesReceived = 0;
7814 temp[count].cli_LastDataUplinkRate = 0;
7815 temp[count].cli_LastDataDownlinkRate = 0;
7816 temp[count].cli_PacketsSent = 0;
7817 temp[count].cli_PacketsReceived = 0;
7818 temp[count].cli_ErrorsSent = 0;
7819 }
7820 }
7821
7822 for (count = 0; count < wifi_count; count++)
7823 {
7824 temp[count].cli_Retransmissions = 0;
7825 temp[count].cli_DataFramesSentAck = 0;
7826 temp[count].cli_DataFramesSentNoAck = 0;
7827 temp[count].cli_MinRSSI = 0;
7828 temp[count].cli_MaxRSSI = 0;
7829 strncpy(temp[count].cli_InterferenceSources, "", 64);
7830 memset(temp[count].cli_IPAddress, 0, 64);
7831 temp[count].cli_RetransCount = 0;
7832 temp[count].cli_FailedRetransCount = 0;
7833 temp[count].cli_RetryCount = 0;
7834 temp[count].cli_MultipleRetryCount = 0;
7835 }
7836 *associated_dev_array = temp;
7837 }
7838 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7839 return RETURN_OK;
7840}
7841
7842int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7843{
7844 FILE *fp = NULL;
7845 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7846 char cmd[MAX_CMD_SIZE];
7847 int count = 0;
7848
7849 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7850 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7851 fp = popen(cmd,"r");
7852 if(fp == NULL)
7853 {
7854 printf("Failed to run command in Function %s\n",__FUNCTION__);
7855 return 0;
7856 }
7857 if(fgets(path, sizeof(path)-1, fp) != NULL)
7858 {
7859 for(count=0;path[count]!='\n';count++)
7860 status[count]=path[count];
7861 status[count]='\0';
7862 }
7863 strcpy(wifi_status,status);
7864 pclose(fp);
7865 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7866 return RETURN_OK;
7867}
7868
7869/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7870struct hostapd_sta_param {
7871 char key[50];
7872 char value[100];
7873}
7874
7875static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7876 int i = 0;
7877
7878 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7879 if (strncmp(params[i].key,key,50) == 0){
7880 return &params[i].value;
7881 }
7882 i++;
7883 }
7884 return NULL;
7885
7886} */
7887
7888static unsigned int count_occurences(const char *buf, const char *word)
7889{
7890 unsigned int n = 0;
7891 char *ptr = strstr(buf, word);
7892
7893 while (ptr++) {
7894 n++;
7895 ptr = strstr(ptr, word);
7896 }
7897
7898 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7899 return n;
7900}
7901
7902static const char *get_line_from_str_buf(const char *buf, char *line)
7903{
7904 int i;
7905 int n = strlen(buf);
7906
7907 for (i = 0; i < n; i++) {
7908 line[i] = buf[i];
7909 if (buf[i] == '\n') {
7910 line[i] = '\0';
7911 return &buf[i + 1];
7912 }
7913 }
7914
7915 return NULL;
7916}
7917
developer9a9f46e2023-11-09 09:22:42 +08007918static INT wifi_getAssocConnectMode(INT apIndex, CHAR *input_string, CHAR *OperatingStandard)
7919{
7920 wifi_band band;
7921 int ieee80211_mode = 0;
7922
7923 if (!input_string || !OperatingStandard)
7924 return RETURN_ERR;
7925
7926 band = wifi_index_to_band(apIndex);
7927
7928 if (strstr(input_string, "HE"))
7929 ieee80211_mode = WIFI_MODE_AX;
7930 else if (strstr(input_string, "VHT"))
7931 ieee80211_mode = WIFI_MODE_AC;
7932 else if (strstr(input_string, "EHT"))
7933 ieee80211_mode = WIFI_MODE_BE;
7934
7935 switch (ieee80211_mode) {
7936 case WIFI_MODE_AC:
7937 strncpy(OperatingStandard, "ac", 2);
7938 break;
7939 case WIFI_MODE_AX:
7940 strncpy(OperatingStandard, "ax", 2);
7941 break;
7942 case WIFI_MODE_BE:
7943 strncpy(OperatingStandard, "be", 2);
7944 break;
7945 default:
7946 if(band == band_2_4)
7947 strncpy(OperatingStandard,"b,g,n", 5);
7948 else if(band == band_5)
7949 strncpy(OperatingStandard,"a,n", 3);
7950 else if(band == band_6)
7951 strncpy(OperatingStandard,"ax", 2);
7952 else {
7953 wifi_dbg_printf("%s: failed to parse band %d\n", __FUNCTION__, band);
7954 return RETURN_ERR;
7955 }
7956 }
7957
7958
7959 return RETURN_OK;
7960}
7961
developer06a01d92022-09-07 16:32:39 +08007962INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7963{
7964 unsigned int assoc_cnt = 0;
7965 char interface_name[50] = {0};
7966 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7967 char cmd[MAX_CMD_SIZE] = {'\0'};
7968 char line[256] = {'\0'};
7969 int i = 0;
7970 int ret = 0;
7971 const char *ptr = NULL;
7972 char *key = NULL;
7973 char *val = NULL;
7974 wifi_associated_dev3_t *temp = NULL;
7975 int rssi;
7976
7977 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7978
7979 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7980 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7981 return RETURN_ERR;
7982 }
7983
7984 // Example filtered output of 'iw dev' command:
7985 // Station 0a:69:72:10:d2:fa (on wifi0)
7986 // signal avg:-67 [-71, -71] dBm
7987 // Station 28:c2:1f:25:5f:99 (on wifi0)
7988 // signal avg:-67 [-71, -70] dBm
developer9a9f46e2023-11-09 09:22:42 +08007989 if (sprintf(cmd,"iw dev %s station dump | tr -d '\t' | grep -E 'Station|signal avg"
7990 "|tx bitrate|rx bitrate'", interface_name) < 0) {
7991 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
developer06a01d92022-09-07 16:32:39 +08007992 return RETURN_ERR;
7993 }
7994
7995 ret = _syscmd(cmd, buf, sizeof(buf));
7996 if (ret == RETURN_ERR) {
7997 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7998 return RETURN_ERR;
7999 }
8000
8001 *output_array_size = count_occurences(buf, "Station");
8002 if (*output_array_size == 0) return RETURN_OK;
8003
8004 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
8005 if (temp == NULL) {
8006 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
8007 return RETURN_ERR;
8008 }
8009 *associated_dev_array = temp;
8010
8011 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
8012 ptr = get_line_from_str_buf(buf, line);
8013 i = -1;
8014 while (ptr) {
8015 if (strstr(line, "Station")) {
8016 i++;
8017 key = strtok(line, " ");
8018 val = strtok(NULL, " ");
8019 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
8020 &temp[i].cli_MACAddress[0],
8021 &temp[i].cli_MACAddress[1],
8022 &temp[i].cli_MACAddress[2],
8023 &temp[i].cli_MACAddress[3],
8024 &temp[i].cli_MACAddress[4],
8025 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
8026 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
8027 free(*associated_dev_array);
8028 return RETURN_ERR;
8029 }
8030 }
8031 else if (i < 0) {
developer9a9f46e2023-11-09 09:22:42 +08008032 wifi_dbg_printf("%s: not find station\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +08008033 ptr = get_line_from_str_buf(ptr, line);
8034 continue; // We didn't detect 'station' entry yet
8035 }
8036 else if (strstr(line, "signal avg")) {
8037 key = strtok(line, ":");
8038 val = strtok(NULL, " ");
8039 if (sscanf(val, "%d", &rssi) <= 0 ) {
8040 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
8041 free(*associated_dev_array);
8042 return RETURN_ERR;
8043 }
8044 temp[i].cli_RSSI = rssi;
8045 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
8046 }
developer9a9f46e2023-11-09 09:22:42 +08008047 else if (strstr(line, "tx bitrate")) {
8048 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
8049 if (ret == RETURN_ERR) {
8050 wifi_dbg_printf("%s: failed to execute tx get assoc connect mode command.\n", __FUNCTION__);
8051 return ret;
8052 }
8053 }
8054 else if (strstr(line, "rx bitrate")) {
8055 /* if tx get ac, ax, be mode, need not get mode from rx */
8056 if (strncmp(temp[i].cli_OperatingStandard,"ac", 2) &&
8057 strncmp(temp[i].cli_OperatingStandard,"ax", 2) &&
8058 strncmp(temp[i].cli_OperatingStandard,"be", 2)) {
8059 ret = wifi_getAssocConnectMode(apIndex, line, temp[i].cli_OperatingStandard);
8060 if (ret == RETURN_ERR) {
8061 wifi_dbg_printf("%s: failed to execute rx get assoc connect mode command.\n", __FUNCTION__);
8062 return ret;
8063 }
8064 }
8065 }
developer06a01d92022-09-07 16:32:39 +08008066 // Here other fields can be parsed if added to filter of 'iw dev' command
developer06a01d92022-09-07 16:32:39 +08008067 ptr = get_line_from_str_buf(ptr, line);
developer9a9f46e2023-11-09 09:22:42 +08008068 }
developer06a01d92022-09-07 16:32:39 +08008069
8070 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008071 return RETURN_OK;
8072}
8073
8074#if 0
8075//To-do
8076INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8077{
8078 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8079
8080 //Using different approach to get required WiFi Parameters from system available commands
8081#if 0
8082 FILE *f;
8083 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8084 char cmd[256], buf[2048];
8085 char *param , *value, *line=NULL;
8086 size_t len = 0;
8087 ssize_t nread;
8088 wifi_associated_dev3_t *dev=NULL;
8089 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08008090 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08008091 _syscmd(cmd,buf,sizeof(buf));
8092 *output_array_size = atoi(buf);
8093
8094 if (*output_array_size <= 0)
8095 return RETURN_OK;
8096
8097 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8098 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08008099 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08008100 _syscmd(cmd,buf,sizeof(buf));
8101 f = fopen("/tmp/connected_devices.txt", "r");
8102 if (f==NULL)
8103 {
8104 *output_array_size=0;
8105 return RETURN_ERR;
8106 }
8107 while ((nread = getline(&line, &len, f)) != -1)
8108 {
8109 param = strtok(line,"=");
8110 value = strtok(NULL,"=");
8111
8112 if( strcmp("flags",param) == 0 )
8113 {
8114 value[strlen(value)-1]='\0';
8115 if(strstr (value,"AUTHORIZED") != NULL )
8116 {
8117 dev[auth_temp].cli_AuthenticationState = 1;
8118 dev[auth_temp].cli_Active = 1;
8119 auth_temp++;
8120 read_flag=1;
8121 }
8122 }
8123 if(read_flag==1)
8124 {
8125 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8126 {
8127 value[strlen(value)-1]='\0';
8128 sscanf(value, "%x:%x:%x:%x:%x:%x",
8129 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8130 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8131 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8132 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8133 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8134 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8135
8136 }
8137 else if( strcmp("rx_packets",param) == 0 )
8138 {
8139 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8140 }
8141
8142 else if( strcmp("tx_packets",param) == 0 )
8143 {
8144 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
8145 }
8146
8147 else if( strcmp("rx_bytes",param) == 0 )
8148 {
8149 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8150 }
8151
8152 else if( strcmp("tx_bytes",param) == 0 )
8153 {
8154 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
8155 mac_temp++;
8156 read_flag=0;
8157 }
8158 }
8159 }
8160
8161 *output_array_size = auth_temp;
8162 auth_temp=0;
8163 mac_temp=0;
8164 free(line);
8165 fclose(f);
8166#endif
8167 char interface_name[MAX_BUF_SIZE] = {0};
8168 char wifi_status[MAX_BUF_SIZE] = {0};
8169 char hostapdconf[MAX_BUF_SIZE] = {0};
8170
8171 wifi_associated_dev3_t *dev_array = NULL;
8172 ULONG wifi_count = 0;
8173
8174 *associated_dev_array = NULL;
8175 *output_array_size = 0;
8176
8177 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8178 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8179 {
8180 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8181
developerac6f1142022-12-20 19:26:35 +08008182 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08008183
8184 if(strlen(interface_name) > 1)
8185 {
8186 wifihal_interfacestatus(wifi_status,interface_name);
8187 if(strcmp(wifi_status,"RUNNING") == 0)
8188 {
8189 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8190
8191 *associated_dev_array = dev_array;
8192 *output_array_size = wifi_count;
8193 }
8194 else
8195 {
8196 *associated_dev_array = NULL;
8197 }
8198 }
8199 }
8200
8201 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8202 return RETURN_OK;
8203}
8204#endif
8205
8206/* getIPAddress function */
8207/**
8208* @description Returning IpAddress of the Matched String
8209*
8210* @param
8211* @str Having MacAddress
8212* @ipaddr Having ipaddr
8213* @return The status of the operation
8214* @retval RETURN_OK if successful
8215* @retval RETURN_ERR if any error is detected
8216*
8217*/
8218
8219INT getIPAddress(char *str,char *ipaddr)
8220{
8221 FILE *fp = NULL;
8222 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8223 int LeaseTime = 0,ret = 0;
8224 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8225 {
8226 return RETURN_ERR;
8227 }
8228
8229 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8230 {
8231 /*
8232 Sample:sss
8233 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8234 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8235 */
8236 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008237 &(LeaseTime),
8238 phyAddr,
8239 ipAddr,
8240 hostName
8241 );
developer06a01d92022-09-07 16:32:39 +08008242 if(ret != 4)
8243 continue;
8244 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008245 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008246 }
developerd946fd62022-12-08 18:03:28 +08008247 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008248 return RETURN_OK;
8249}
8250
8251/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8252/**
8253* @description Returning Inactive wireless connected clients informations
8254*
8255* @param
8256* @filename Holding private_wifi 2g/5g content files
8257* @associated_dev_array Having inactiv wireless clients informations
8258* @output_array_size Returning Inactive wireless counts
8259* @return The status of the operation
8260* @retval RETURN_OK if successful
8261* @retval RETURN_ERR if any error is detected
8262*
8263*/
8264
8265INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8266{
8267 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8268 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8269 FILE *fp = NULL;
8270 int arr[MACADDRESS_SIZE] = {0};
8271 unsigned char mac[MACADDRESS_SIZE] = {0};
8272 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8273 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8274 fp = popen(buf,"r");
8275 if(fp == NULL)
8276 return RETURN_ERR;
8277 else
8278 {
8279 fgets(path,sizeof(path),fp);
8280 maccount = atoi(path);
8281 }
8282 pclose(fp);
8283 *output_array_size = maccount;
8284 wifi_associated_dev3_t* temp = NULL;
8285 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8286 *associated_dev_array = temp;
8287 if(temp == NULL)
8288 {
8289 printf("Error Statement. Insufficient memory \n");
8290 return RETURN_ERR;
8291 }
8292 memset(buf,0,sizeof(buf));
8293 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8294 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008295 if (fp == NULL) {
8296 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8297 return RETURN_ERR;
8298 }
developer06a01d92022-09-07 16:32:39 +08008299 for(count = 0; count < maccount ; count++)
8300 {
8301 fgets(path,sizeof(path),fp);
8302 for(i = 0; path[i]!='\n';i++)
8303 str[i]=path[i];
8304 str[i]='\0';
8305 getIPAddress(str,ipaddr);
8306 memset(buf,0,sizeof(buf));
8307 if(strlen(ipaddr) > 0)
8308 {
8309 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8310 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8311 {
8312 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8313 {
8314 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8315 {
8316 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8317
8318 }
8319 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8320 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]);
8321 }
8322 temp[count].cli_AuthenticationState = 0; //TODO
8323 temp[count].cli_Active = 0; //TODO
8324 temp[count].cli_SignalStrength = 0;
8325 }
8326 else //Active wireless clients info
8327 {
8328 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8329 {
8330 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8331 {
8332 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8333
8334 }
8335 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8336 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]);
8337 }
8338 temp[count].cli_Active = 1;
8339 }
8340 }
8341 memset(ipaddr,0,sizeof(ipaddr));
8342 }
8343 pclose(fp);
8344 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8345 return RETURN_OK;
8346}
8347//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8348//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8349//To get Band Steering Capability
8350INT wifi_getBandSteeringCapability(BOOL *support)
8351{
8352 *support = FALSE;
8353 return RETURN_OK;
8354}
8355
8356
8357//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8358//To get Band Steering enable status
8359INT wifi_getBandSteeringEnable(BOOL *enable)
8360{
8361 *enable = FALSE;
8362 return RETURN_OK;
8363}
8364
8365//To turn on/off Band steering
8366INT wifi_setBandSteeringEnable(BOOL enable)
8367{
8368 return RETURN_OK;
8369}
8370
8371//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8372//To get Band Steering AP group
8373INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8374{
8375 if (NULL == output_ApGroup)
8376 return RETURN_ERR;
8377
8378 strcpy(output_ApGroup, "1,2");
8379 return RETURN_OK;
8380}
8381
8382//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8383//to set and read the band steering BandUtilizationThreshold parameters
8384INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8385{
8386 return RETURN_ERR;
8387}
8388
8389INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8390{
8391 return RETURN_ERR;
8392}
8393
8394//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8395//to set and read the band steering RSSIThreshold parameters
8396INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8397{
8398 return RETURN_ERR;
8399}
8400
8401INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8402{
8403 return RETURN_ERR;
8404}
8405
8406
8407//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8408//to set and read the band steering physical modulation rate threshold parameters
8409INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8410{
8411 //If chip is not support, return -1
8412 return RETURN_ERR;
8413}
8414
8415INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8416{
8417 //If chip is not support, return -1
8418 return RETURN_ERR;
8419}
8420
8421//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8422//to set and read the inactivity time (in seconds) for steering under overload condition
8423INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8424{
8425 return RETURN_ERR;
8426}
8427
8428INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8429{
8430 return RETURN_ERR;
8431}
8432
8433//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8434//to set and read the inactivity time (in seconds) for steering under Idle condition
8435INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8436{
8437 return RETURN_ERR;
8438}
8439
8440INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8441{
8442 return RETURN_ERR;
8443}
8444
8445//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8446//pClientMAC[64]
8447//pSourceSSIDIndex[64]
8448//pDestSSIDIndex[64]
8449//pSteeringReason[256]
8450INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8451{
8452 //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
8453 *pSteeringTime=time(NULL);
8454 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8455 return RETURN_OK;
8456}
8457
8458INT wifi_ifConfigDown(INT apIndex)
8459{
8460 INT status = RETURN_OK;
8461 char cmd[64];
8462
8463 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8464 printf("%s: %s\n", __func__, cmd);
8465 system(cmd);
8466
8467 return status;
8468}
8469
8470INT wifi_ifConfigUp(INT apIndex)
8471{
developerd946fd62022-12-08 18:03:28 +08008472 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008473 char cmd[128];
8474 char buf[1024];
8475
developerac6f1142022-12-20 19:26:35 +08008476 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008477 return RETURN_ERR;
8478 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008479 _syscmd(cmd, buf, sizeof(buf));
8480 return 0;
8481}
8482
8483//>> Deprecated. Replace with wifi_applyRadioSettings
8484INT wifi_pushBridgeInfo(INT apIndex)
8485{
developerd946fd62022-12-08 18:03:28 +08008486 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008487 char ip[32] = {0};
8488 char subnet[32] = {0};
8489 char bridge[32] = {0};
8490 int vlanId = 0;
8491 char cmd[128] = {0};
8492 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008493
8494 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8495 wifi_getApVlanID(apIndex,&vlanId);
8496
developerac6f1142022-12-20 19:26:35 +08008497 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008498 return RETURN_ERR;
8499 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008500 _syscmd(cmd,buf, sizeof(buf));
8501
8502 return 0;
8503}
8504
8505INT wifi_pushChannel(INT radioIndex, UINT channel)
8506{
developerd946fd62022-12-08 18:03:28 +08008507 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008508 char cmd[128];
8509 char buf[1024];
8510 int apIndex;
8511
8512 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008513 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008514 return RETURN_ERR;
8515 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008516 _syscmd(cmd,buf, sizeof(buf));
8517
8518 return 0;
8519}
8520
8521INT wifi_pushChannelMode(INT radioIndex)
8522{
8523 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8524 return RETURN_ERR;
8525}
8526
8527INT wifi_pushDefaultValues(INT radioIndex)
8528{
8529 //Apply Comcast specified default radio settings instantly
8530 //AMPDU=1
8531 //AMPDUFrames=32
8532 //AMPDULim=50000
8533 //txqueuelen=1000
8534
8535 return RETURN_ERR;
8536}
8537
8538INT wifi_pushTxChainMask(INT radioIndex)
8539{
8540 //Apply default TxChainMask instantly
8541 return RETURN_ERR;
8542}
8543
8544INT wifi_pushRxChainMask(INT radioIndex)
8545{
8546 //Apply default RxChainMask instantly
8547 return RETURN_ERR;
8548}
8549
8550INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8551{
8552 INT status;
8553
8554 status = wifi_setSSIDName(apIndex,ssid);
8555 wifi_setApEnable(apIndex,FALSE);
8556 wifi_setApEnable(apIndex,TRUE);
8557
8558 return status;
8559}
8560
8561INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8562{
8563 //Apply default Ssid Advertisement instantly
8564 return RETURN_ERR;
8565}
8566
8567INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8568{
8569 INT status = RETURN_ERR;
8570 *output = 0;
8571 return RETURN_ERR;
8572}
8573
8574INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8575{
8576 return RETURN_OK;
8577}
8578
8579INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8580{
8581 return RETURN_OK;
8582}
8583
8584//To-do
8585INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8586{
developereb199ae2022-09-13 14:04:27 +08008587 char output[16]={'\0'};
8588 char config_file[MAX_BUF_SIZE] = {0};
8589
8590 if (!output_string)
8591 return RETURN_ERR;
8592
8593 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8594 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8595
8596 if (strlen(output) == 0)
8597 snprintf(output_string, 64, "Disabled");
8598 else if (strncmp(output, "0", 1) == 0)
8599 snprintf(output_string, 64, "Disabled");
8600 else if (strncmp(output, "1", 1) == 0)
8601 snprintf(output_string, 64, "Optional");
8602 else if (strncmp(output, "2", 1) == 0)
8603 snprintf(output_string, 64, "Required");
8604 else {
8605 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8606 return RETURN_ERR;
8607 }
8608
8609 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008610 return RETURN_OK;
8611}
8612INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8613{
developereb199ae2022-09-13 14:04:27 +08008614 char str[MAX_BUF_SIZE]={'\0'};
8615 char cmd[MAX_CMD_SIZE]={'\0'};
8616 struct params params;
8617 char config_file[MAX_BUF_SIZE] = {0};
8618
8619 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8620 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8621 return RETURN_ERR;
8622
8623 params.name = "ieee80211w";
8624 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8625 params.value = "0";
8626 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8627 params.value = "1";
8628 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8629 params.value = "2";
8630 else{
8631 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8632 return RETURN_ERR;
8633 }
8634 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8635 wifi_hostapdWrite(config_file, &params, 1);
8636 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008637 return RETURN_OK;
8638}
8639INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8640{
8641 char output[16]={'\0'};
8642 char config_file[MAX_BUF_SIZE] = {0};
8643
8644 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8645 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8646 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8647
8648 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8649 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8650
8651 return RETURN_OK;
8652}
8653
8654INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8655{
8656 return RETURN_OK;
8657}
8658
8659INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8660{
8661 return RETURN_OK;
8662}
8663
8664INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8665{
8666 return RETURN_OK;
8667}
8668
8669INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8670{
8671 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8672 char config_file[MAX_BUF_SIZE] = {0};
8673
8674 if (NULL == output)
8675 return RETURN_ERR;
8676 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8677 wifi_hostapdRead(config_file,"hw_mode",output,64);
8678
8679 if(strcmp(output,"b")==0)
8680 sprintf(output, "%s", "1,2,5.5,11");
8681 else if (strcmp(output,"a")==0)
8682 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8683 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8684 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8685
8686 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8687 return RETURN_OK;
8688}
8689
8690INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8691{
8692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8693 char *temp;
8694 char temp_output[128];
8695 char temp_TransmitRates[128];
8696 char config_file[MAX_BUF_SIZE] = {0};
8697
8698 if (NULL == output)
8699 return RETURN_ERR;
8700
8701 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8702 wifi_hostapdRead(config_file,"supported_rates",output,64);
8703
developer5b398df2022-11-17 20:39:48 +08008704 if (strlen(output) == 0) {
8705 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8706 return RETURN_OK;
8707 }
developer06a01d92022-09-07 16:32:39 +08008708 strcpy(temp_TransmitRates,output);
8709 strcpy(temp_output,"");
8710 temp = strtok(temp_TransmitRates," ");
8711 while(temp!=NULL)
8712 {
8713 temp[strlen(temp)-1]=0;
8714 if((temp[0]=='5') && (temp[1]=='\0'))
8715 {
8716 temp="5.5";
8717 }
8718 strcat(temp_output,temp);
8719 temp = strtok(NULL," ");
8720 if(temp!=NULL)
8721 {
8722 strcat(temp_output,",");
8723 }
8724 }
8725 strcpy(output,temp_output);
8726 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8727
8728 return RETURN_OK;
8729}
8730
8731INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8732{
8733 return RETURN_OK;
8734}
8735
8736
8737INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8738{
8739 int i=0;
8740 char *temp;
developeref938762022-10-19 17:21:01 +08008741 char temp1[128] = {0};
8742 char temp_output[128] = {0};
8743 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008744 struct params params={'\0'};
8745 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008746 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008747
8748 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8749 if(NULL == output)
8750 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008751 strcpy(temp_TransmitRates,output);
8752
8753 for(i=0;i<strlen(temp_TransmitRates);i++)
8754 {
developeref938762022-10-19 17:21:01 +08008755 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008756 {
8757 continue;
8758 }
8759 else
8760 {
8761 return RETURN_ERR;
8762 }
8763 }
8764 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008765 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008766 while(temp!=NULL)
8767 {
8768 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008769 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008770 {
developeref938762022-10-19 17:21:01 +08008771 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008772 {
8773 return RETURN_ERR;
8774 }
8775 }
8776
8777 if(strcmp(temp,"5.5")==0)
8778 {
8779 strcpy(temp1,"55");
8780 }
8781 else
8782 {
8783 strcat(temp1,"0");
8784 }
8785 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008786 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008787 if(temp!=NULL)
8788 {
8789 strcat(temp_output," ");
8790 }
8791 }
8792 strcpy(output,temp_output);
8793
developer06a01d92022-09-07 16:32:39 +08008794 params.name = "supported_rates";
8795 params.value = output;
8796
8797 wifi_dbg_printf("\n%s:",__func__);
8798 wifi_dbg_printf("params.value=%s\n",params.value);
8799 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8800 wifi_hostapdWrite(config_file,&params,1);
8801 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8802
8803 return RETURN_OK;
8804}
8805
8806
8807static char *sncopy(char *dst, int dst_sz, const char *src)
8808{
8809 if (src && dst && dst_sz > 0) {
8810 strncpy(dst, src, dst_sz);
8811 dst[dst_sz - 1] = '\0';
8812 }
8813 return dst;
8814}
8815
8816static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8817{
8818 if (0 == strcmp(ht_mode, "HT40") ||
8819 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008820 0 == strcmp(ht_mode, "HT160") ||
8821 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008822 switch (channel) {
developer9a520b12023-09-21 16:01:43 +08008823 case 0 ... 7:
developer06a01d92022-09-07 16:32:39 +08008824 case 36:
8825 case 44:
8826 case 52:
8827 case 60:
8828 case 100:
8829 case 108:
8830 case 116:
8831 case 124:
8832 case 132:
8833 case 140:
8834 case 149:
8835 case 157:
8836 return 1;
8837 case 8 ... 13:
8838 case 40:
8839 case 48:
8840 case 56:
8841 case 64:
8842 case 104:
8843 case 112:
8844 case 120:
8845 case 128:
8846 case 136:
8847 case 144:
8848 case 153:
8849 case 161:
8850 return -1;
8851 default:
8852 return -EINVAL;
8853 }
8854 }
8855
8856 return -EINVAL;
8857}
8858
developerb7593de2022-10-18 09:51:57 +08008859static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8860{
8861 int idx = channel%8;
8862 if (0 == strcmp(ht_mode, "HT40") ||
8863 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008864 0 == strcmp(ht_mode, "HT160") ||
8865 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008866 switch (idx) {
8867 case 1:
8868 return 1;
8869 case 5:
8870 return -1;
8871 default:
8872 return -EINVAL;
8873 }
8874 }
8875
8876 return -EINVAL;
8877}
developer06a01d92022-09-07 16:32:39 +08008878static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8879{
8880 if (NULL == hw_mode) return;
8881
8882 if (0 == strcmp(hw_mode, "ac"))
8883 sncopy(bw_mode, bw_mode_len, "ht vht");
8884
8885 if (0 == strcmp(hw_mode, "n"))
8886 sncopy(bw_mode, bw_mode_len, "ht");
8887
8888 return;
8889}
8890
8891static int util_chan_to_freq(int chan)
8892{
8893 if (chan == 14)
8894 return 2484;
8895 else if (chan < 14)
8896 return 2407 + chan * 5;
8897 else if (chan >= 182 && chan <= 196)
8898 return 4000 + chan * 5;
8899 else
8900 return 5000 + chan * 5;
8901 return 0;
8902}
8903
developerb7593de2022-10-18 09:51:57 +08008904static int util_6G_chan_to_freq(int chan)
8905{
8906 if (chan)
8907 return 5950 + chan * 5;
8908 else
8909 return 0;
8910
8911}
developer06a01d92022-09-07 16:32:39 +08008912const int *util_unii_5g_chan2list(int chan, int width)
8913{
8914 static const int lists[] = {
8915 // <width>, <chan1>, <chan2>..., 0,
developer8b2f01f2024-03-01 14:50:27 +08008916 20, 36, 0,
8917 20, 40, 0,
8918 20, 44, 0,
8919 20, 48, 0,
8920 20, 52, 0,
8921 20, 56, 0,
8922 20, 60, 0,
8923 20, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008924 20, 100, 0,
8925 20, 104, 0,
8926 20, 108, 0,
8927 20, 112, 0,
8928 20, 116, 0,
8929 20, 120, 0,
8930 20, 124, 0,
8931 20, 128, 0,
8932 20, 132, 0,
8933 20, 136, 0,
8934 20, 140, 0,
8935 20, 144, 0,
8936 20, 149, 0,
8937 20, 153, 0,
8938 20, 157, 0,
8939 20, 161, 0,
8940 20, 165, 0,
developer8b2f01f2024-03-01 14:50:27 +08008941 20, 169, 0,
8942 20, 173, 0,
8943 20, 177, 0,
8944 40, 36, 40, 0,
8945 40, 44, 48, 0,
8946 40, 52, 56, 0,
8947 40, 60, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008948 40, 100, 104, 0,
8949 40, 108, 112, 0,
8950 40, 116, 120, 0,
8951 40, 124, 128, 0,
8952 40, 132, 136, 0,
8953 40, 140, 144, 0,
8954 40, 149, 153, 0,
8955 40, 157, 161, 0,
developer8b2f01f2024-03-01 14:50:27 +08008956 40, 165, 169, 0,
8957 40, 173, 177, 0,
8958 80, 36, 40, 44, 48, 0,
8959 80, 52, 56, 60, 64, 0,
developer06a01d92022-09-07 16:32:39 +08008960 80, 100, 104, 108, 112, 0,
8961 80, 116, 120, 124, 128, 0,
8962 80, 132, 136, 140, 144, 0,
8963 80, 149, 153, 157, 161, 0,
developer8b2f01f2024-03-01 14:50:27 +08008964 80, 165, 169, 173, 177, 0,
8965 160,36, 40, 44, 48, 52, 56, 60, 64, 0,
8966 160,100, 104, 108, 112, 116, 120, 124, 128, 0,
8967 160,149, 153, 157, 161, 165, 169, 173, 177, 0,
developer06a01d92022-09-07 16:32:39 +08008968 -1 // final delimiter
8969 };
8970 const int *start;
8971 const int *p;
8972
8973 for (p = lists; *p != -1; p++) {
8974 if (*p == width) {
8975 for (start = ++p; *p != 0; p++) {
8976 if (*p == chan)
8977 return start;
8978 }
8979 }
8980 // move to the end of channel list of given width
8981 while (*p != 0) {
8982 p++;
8983 }
8984 }
8985
8986 return NULL;
8987}
8988
8989static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8990{
8991 if (NULL == ht_mode)
8992 return 0;
8993
8994 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8995 const int *chans = util_unii_5g_chan2list(channel, width);
8996 int sum = 0;
8997 int cnt = 0;
8998
8999 if (NULL == chans)
9000 return 0;
9001
9002 while (*chans) {
9003 sum += *chans;
9004 cnt++;
9005 chans++;
9006 }
developer30423732022-12-01 16:17:49 +08009007 if (cnt == 0)
9008 return 0;
developer06a01d92022-09-07 16:32:39 +08009009 return sum / cnt;
9010}
9011
developerb7593de2022-10-18 09:51:57 +08009012static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
9013{
9014 if (NULL == ht_mode)
9015 return 0;
9016
9017 int width = strtol((ht_mode + 2), NULL, 10);
9018
9019 int idx = 0 ;
9020 int centerchan = 0;
9021 int chan_ofs = 1;
9022
9023 if (width == 40){
9024 idx = ((channel/4) + chan_ofs)%2;
9025 switch (idx) {
9026 case 0:
9027 centerchan = (channel - 2);
9028 break;
9029 case 1:
9030 centerchan = (channel + 2);
9031 break;
9032 default:
9033 return -EINVAL;
9034 }
9035 }else if (width == 80){
9036 idx = ((channel/4) + chan_ofs)%4;
9037 switch (idx) {
9038 case 0:
9039 centerchan = (channel - 6);
9040 break;
9041 case 1:
9042 centerchan = (channel + 6);
9043 break;
9044 case 2:
9045 centerchan = (channel + 2);
9046 break;
9047 case 3:
9048 centerchan = (channel - 2);
9049 break;
9050 default:
9051 return -EINVAL;
9052 }
9053 }else if (width == 160){
9054 switch (channel) {
9055 case 1 ... 29:
9056 centerchan = 15;
9057 break;
9058 case 33 ... 61:
9059 centerchan = 47;
9060 break;
9061 case 65 ... 93:
9062 centerchan = 79;
9063 break;
9064 case 97 ... 125:
9065 centerchan = 111;
9066 break;
9067 case 129 ... 157:
9068 centerchan = 143;
9069 break;
9070 case 161 ... 189:
9071 centerchan = 175;
9072 break;
9073 case 193 ... 221:
9074 centerchan = 207;
9075 break;
9076 default:
9077 return -EINVAL;
9078 }
developer7c4cd202023-03-01 10:56:29 +08009079 }else if (width == 320){
9080 switch (channel) {
9081 case 1 ... 29:
9082 centerchan = 31;
9083 break;
9084 case 33 ... 93:
9085 centerchan = 63;
9086 break;
9087 case 97 ... 157:
9088 centerchan = 127;
9089 break;
9090 case 161 ... 221:
9091 centerchan = 191;
9092 break;
9093 default:
9094 return -EINVAL;
9095 }
developerb7593de2022-10-18 09:51:57 +08009096 }
9097 return centerchan;
9098}
developer06a01d92022-09-07 16:32:39 +08009099static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9100{
9101 BOOL onlyG, onlyN, onlyA;
9102 CHAR tmp[64];
9103 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9104 if (ret == RETURN_OK) {
9105 sncopy(hw_mode, hw_mode_size, tmp);
9106 }
9107 return ret;
9108}
9109
9110INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9111{
9112 // Sample commands:
9113 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9114 // hostapd_cli -i wifi0 chan_switch 30 2437
9115 char cmd[MAX_CMD_SIZE] = {0};
9116 char buf[MAX_BUF_SIZE] = {0};
9117 int freq = 0, ret = 0;
9118 char center_freq1_str[32] = ""; // center_freq1=%d
9119 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9120 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9121 char hw_mode[16] = ""; // n|ac
9122 char bw_mode[16] = ""; // ht|ht vht
9123 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08009124 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009125 int sec_chan_offset;
9126 int width;
developer4fb0b922022-09-30 14:29:09 +08009127 char config_file[64] = {0};
9128 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08009129 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08009130 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08009131 wifi_band band = band_invalid;
9132 int center_chan = 0;
9133 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08009134
developer4fb0b922022-09-30 14:29:09 +08009135 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08009136
developerac6f1142022-12-20 19:26:35 +08009137 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009138 return RETURN_ERR;
9139
developer06a01d92022-09-07 16:32:39 +08009140 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9141
developerb7593de2022-10-18 09:51:57 +08009142 band = wifi_index_to_band(radioIndex);
9143
developer5884e982022-10-06 10:52:50 +08009144 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08009145
9146 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08009147 if (channel){
developerb7593de2022-10-18 09:51:57 +08009148 if (band == band_6){
9149 freq = util_6G_chan_to_freq(channel);
9150 }else{
9151 freq = util_chan_to_freq(channel);
9152 }
developer7c4cd202023-03-01 10:56:29 +08009153 if (width == 320) {
9154 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
9155 setEHT320 = TRUE;
9156 }
developer5884e982022-10-06 10:52:50 +08009157 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08009158
developer5884e982022-10-06 10:52:50 +08009159 // Provide bandwith if specified
9160 if (channel_width_MHz > 20) {
9161 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9162 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9163 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08009164
developer5884e982022-10-06 10:52:50 +08009165 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9166 }else if (channel_width_MHz == 20){
9167 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9168 }
developer06a01d92022-09-07 16:32:39 +08009169
developerb7593de2022-10-18 09:51:57 +08009170
developer5884e982022-10-06 10:52:50 +08009171 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08009172 if (band == band_6){
9173 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9174 if(center_chan){
9175 center_freq1 = util_6G_chan_to_freq(center_chan);
9176 }
9177 }else{
9178 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9179 if(center_chan){
9180 center_freq1 = util_chan_to_freq(center_chan);
9181 }
developer5884e982022-10-06 10:52:50 +08009182 }
developerb7593de2022-10-18 09:51:57 +08009183
9184 if (center_freq1)
9185 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9186
9187 }
9188
9189 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9190 if (band == band_6){
9191 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9192 }else{
9193 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08009194 }
developerb7593de2022-10-18 09:51:57 +08009195 if (sec_chan_offset != -EINVAL)
9196 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08009197
developer5884e982022-10-06 10:52:50 +08009198 // Only the first AP, other are hanging on the same radio
9199 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08009200 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9201 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08009202 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9203 wifi_dbg_printf("execute: '%s'\n", cmd);
9204 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08009205 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08009206
developer5884e982022-10-06 10:52:50 +08009207 ret = wifi_setRadioChannel(radioIndex, channel);
9208 if (ret != RETURN_OK) {
9209 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9210 return RETURN_ERR;
9211 }
9212
9213 if (sec_chan_offset == 1) ext_str = "Above";
9214 else if (sec_chan_offset == -1) ext_str = "Below";
9215
9216 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08009217
developer5884e982022-10-06 10:52:50 +08009218 } else {
9219 if (channel_width_MHz > 20)
9220 ext_str = "Above";
9221 }
developer4fb0b922022-09-30 14:29:09 +08009222
developer06a01d92022-09-07 16:32:39 +08009223 char mhz_str[16];
9224 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009225 if (setEHT320 == TRUE)
9226 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9227 else
9228 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009229
developer57fa24a2023-03-15 17:25:07 +08009230 writeBandWidth(radioIndex, mhz_str);
9231 if (band == band_2_4 || band == band_5) {
9232 if (width == 20)
9233 wifi_RemoveRadioExtChannel(radioIndex, ext_str);
9234 else
9235 wifi_setRadioExtChannel(radioIndex, ext_str);
9236 }
developer06a01d92022-09-07 16:32:39 +08009237 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9238
9239 return RETURN_OK;
9240}
9241
9242INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9243{
developer615510b2022-09-27 10:14:35 +08009244 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009245 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009246 char cmd[256]={0};
9247 char buf[128]={0};
9248 char file_name[32] = {0};
9249 char filter_SSID[32] = {0};
9250 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009251 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009252 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009253 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009254 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009255 size_t len=0;
9256 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009257 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009258 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009259 bool filter_enable = false;
9260 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009261 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009262
developer615510b2022-09-27 10:14:35 +08009263 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009264
developer615510b2022-09-27 10:14:35 +08009265 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9266 f = fopen(file_name, "r");
9267 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009268 fgets(buf, sizeof(file_name), f);
9269 if ((strncmp(buf, "0", 1)) != 0) {
9270 fgets(filter_SSID, sizeof(file_name), f);
9271 if (strlen(filter_SSID) != 0)
9272 filter_enable = true;
9273 }
developer615510b2022-09-27 10:14:35 +08009274 fclose(f);
9275 }
9276
developerac6f1142022-12-20 19:26:35 +08009277 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009278 return RETURN_ERR;
9279
developer033b37b2022-10-18 11:27:46 +08009280 phyId = radio_index_to_phy(radio_index);
9281
9282 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009283 _syscmd(cmd, buf, sizeof(buf));
9284 channels_num = strtol(buf, NULL, 10);
9285
developerd946fd62022-12-08 18:03:28 +08009286 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9287 // 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 +08009288 fprintf(stderr, "cmd: %s\n", cmd);
9289 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009290 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9291 return RETURN_ERR;
9292 }
developer5550e242022-09-30 09:59:32 +08009293
9294 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9295 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9296
developer615510b2022-09-27 10:14:35 +08009297 ret = fgets(line, sizeof(line), f);
9298 while (ret != NULL) {
9299 if(strstr(line, "BSS") != NULL) { // new neighbor info
9300 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9301 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9302 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9303
9304 if (!filter_BSS) {
9305 index++;
9306 wifi_neighbor_ap2_t *tmp;
9307 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9308 if (tmp == NULL) { // no more memory to use
9309 index--;
9310 wifi_dbg_printf("%s: realloc failed\n", __func__);
9311 break;
9312 }
9313 scan_array = tmp;
9314 }
9315 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009316
developer615510b2022-09-27 10:14:35 +08009317 filter_BSS = false;
9318 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9319 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9320 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9321 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9322 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009323 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009324 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009325
developer615510b2022-09-27 10:14:35 +08009326 if (freq >= 2412 && freq <= 2484) {
9327 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9328 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9329 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9330 }
9331 else if (freq >= 5160 && freq <= 5805) {
9332 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9333 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9334 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9335 }
developer06a01d92022-09-07 16:32:39 +08009336
developer615510b2022-09-27 10:14:35 +08009337 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009338 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009339 for (int i = 0; i < channels_num; i++) {
9340 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9341 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9342 break;
9343 }
9344 }
developer06a01d92022-09-07 16:32:39 +08009345 }
developer615510b2022-09-27 10:14:35 +08009346 } else if (strstr(line, "beacon interval") != NULL) {
9347 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9348 } else if (strstr(line, "signal") != NULL) {
9349 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9350 } else if (strstr(line,"SSID") != NULL) {
9351 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9352 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9353 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009354 }
developer615510b2022-09-27 10:14:35 +08009355 } else if (strstr(line, "Supported rates") != NULL) {
9356 char SRate[80] = {0}, *tmp = NULL;
9357 memset(buf, 0, sizeof(buf));
9358 strcpy(SRate, line);
9359 tmp = strtok(SRate, ":");
9360 tmp = strtok(NULL, ":");
9361 strcpy(buf, tmp);
9362 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009363
developer615510b2022-09-27 10:14:35 +08009364 tmp = strtok(buf, " \n");
9365 while (tmp != NULL) {
9366 strcat(SRate, tmp);
9367 if (SRate[strlen(SRate) - 1] == '*') {
9368 SRate[strlen(SRate) - 1] = '\0';
9369 }
9370 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009371
developer615510b2022-09-27 10:14:35 +08009372 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009373 }
developer615510b2022-09-27 10:14:35 +08009374 SRate[strlen(SRate) - 1] = '\0';
9375 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9376 } else if (strstr(line, "DTIM") != NULL) {
9377 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9378 } else if (strstr(line, "VHT capabilities") != NULL) {
9379 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9380 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9381 } else if (strstr(line, "HT capabilities") != NULL) {
9382 strcat(scan_array[index].ap_SupportedStandards, ",n");
9383 strcpy(scan_array[index].ap_OperatingStandards, "n");
9384 } else if (strstr(line, "VHT operation") != NULL) {
9385 ret = fgets(line, sizeof(line), f);
9386 sscanf(line," * channel width: %d", &vht_channel_width);
9387 if(vht_channel_width == 1) {
9388 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9389 } else {
9390 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9391 }
9392 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9393 continue;
9394 } else if (strstr(line, "HT operation") != NULL) {
9395 ret = fgets(line, sizeof(line), f);
9396 sscanf(line," * secondary channel offset: %s", &buf);
9397 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009398 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009399 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 +08009400 }
developer615510b2022-09-27 10:14:35 +08009401 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009402 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009403 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9404 } else {
9405 //20Mhz
9406 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 +08009407 }
developer615510b2022-09-27 10:14:35 +08009408 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009409 continue;
developer615510b2022-09-27 10:14:35 +08009410 } else if (strstr(line, "HE capabilities") != NULL) {
9411 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9412 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9413 ret = fgets(line, sizeof(line), f);
9414 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9415 if (strstr(line, "HE40/2.4GHz") != NULL)
9416 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9417 else
9418 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9419 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9420 if (strstr(line, "HE80/5GHz") != NULL) {
9421 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9422 ret = fgets(line, sizeof(line), f);
9423 } else
9424 continue;
9425 if (strstr(line, "HE160/5GHz") != NULL)
9426 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009427 }
developer615510b2022-09-27 10:14:35 +08009428 continue;
9429 } else if (strstr(line, "WPA") != NULL) {
9430 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9431 } else if (strstr(line, "RSN") != NULL) {
9432 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9433 } else if (strstr(line, "Group cipher") != NULL) {
9434 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9435 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9436 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009437 }
developer06a01d92022-09-07 16:32:39 +08009438 }
developer615510b2022-09-27 10:14:35 +08009439 ret = fgets(line, sizeof(line), f);
9440 }
9441
9442 if (!filter_BSS) {
9443 *output_array_size = index + 1;
9444 } else {
9445 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9446 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009447 }
developer06a01d92022-09-07 16:32:39 +08009448 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009449 pclose(f);
developer5550e242022-09-30 09:59:32 +08009450 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009451 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009452 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009453}
developer615510b2022-09-27 10:14:35 +08009454
developer06a01d92022-09-07 16:32:39 +08009455INT wifi_getApAssociatedDeviceStats(
9456 INT apIndex,
9457 mac_address_t *clientMacAddress,
9458 wifi_associated_dev_stats_t *associated_dev_stats,
9459 u64 *handle)
9460{
9461 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9462 char interface_name[50] = {0};
9463 char cmd[1024] = {0};
9464 char mac_str[18] = {0};
9465 char *key = NULL;
9466 char *val = NULL;
9467 FILE *f = NULL;
9468 char *line = NULL;
9469 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009470
9471 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9472 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9473 return RETURN_ERR;
9474 }
9475
9476 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9477 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9478 if((f = popen(cmd, "r")) == NULL) {
9479 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9480 return RETURN_ERR;
9481 }
9482
developer30423732022-12-01 16:17:49 +08009483 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009484 key = strtok(line,":");
9485 val = strtok(NULL,":");
9486
9487 if(!strncmp(key,"rx bytes",8))
9488 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9489 if(!strncmp(key,"tx bytes",8))
9490 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9491 if(!strncmp(key,"rx packets",10))
9492 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9493 if(!strncmp(key,"tx packets",10))
9494 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9495 if(!strncmp(key,"tx retries",10))
9496 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9497 if(!strncmp(key,"tx failed",9))
9498 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9499 if(!strncmp(key,"rx drop misc",13))
9500 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9501 if(!strncmp(key,"rx bitrate",10)) {
9502 val = strtok(val, " ");
9503 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9504 }
9505 if(!strncmp(key,"tx bitrate",10)) {
9506 val = strtok(val, " ");
9507 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9508 }
9509 }
9510 free(line);
9511 pclose(f);
9512 return RETURN_OK;
9513}
9514
9515INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9516{
developerd946fd62022-12-08 18:03:28 +08009517 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009518 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9519
9520 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9521 if (NULL == output_string)
9522 return RETURN_ERR;
9523
developerac6f1142022-12-20 19:26:35 +08009524 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009525 return RETURN_ERR;
9526 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 +08009527 _syscmd(cmd, buf, sizeof(buf));
9528
9529 //size of SSID name restricted to value less than 32 bytes
9530 snprintf(output_string, 32, "%s", buf);
9531 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9532
9533 return RETURN_OK;
9534}
9535
9536INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9537{
9538 //char cmd[MAX_CMD_SIZE] = {0};
9539 char config_file[MAX_BUF_SIZE] = {0};
9540 char buf[32] = {0};
9541
9542 if (!output_filterMode)
9543 return RETURN_ERR;
9544
9545 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9546 //_syscmd(cmd, buf, sizeof(buf));
9547 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +08009548 if (!syn_flag)
9549 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
9550 else
developer07ded1f2024-01-10 10:30:15 +08009551 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].macaddr_acl);
developer10adcc12022-09-13 14:39:17 +08009552 if(strlen(buf) == 0) {
9553 *output_filterMode = 0;
9554 }
9555 else {
9556 int macaddr_acl_mode = strtol(buf, NULL, 10);
9557 if (macaddr_acl_mode == 1) {
9558 *output_filterMode = 1;
9559 } else if (macaddr_acl_mode == 0) {
9560 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9561 if (strlen(buf) == 0) {
9562 *output_filterMode = 0;
9563 } else {
9564 *output_filterMode = 2;
9565 }
9566 } else {
9567 return RETURN_ERR;
9568 }
9569 }
developer06a01d92022-09-07 16:32:39 +08009570
9571 return RETURN_OK;
9572}
9573
9574INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9575{
9576 FILE *fp = NULL;
9577 char str[MAX_BUF_SIZE] = {0};
9578 int wificlientindex = 0 ;
9579 int count = 0;
9580 int signalstrength = 0;
9581 int arr[MACADDRESS_SIZE] = {0};
9582 unsigned char mac[MACADDRESS_SIZE] = {0};
9583 UINT wifi_count = 0;
9584 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9585 char pipeCmd[MAX_CMD_SIZE] = {0};
9586
9587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9588 *output_array_size = 0;
9589 *associated_dev_array = NULL;
9590 char interface_name[50] = {0};
9591
9592 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9593 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9594 return RETURN_ERR;
9595 }
9596
9597 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9598 fp = popen(pipeCmd, "r");
9599 if (fp == NULL)
9600 {
9601 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9602 return RETURN_ERR;
9603 }
9604
9605 /* Read the output a line at a time - output it. */
9606 fgets(str, sizeof(str)-1, fp);
9607 wifi_count = (unsigned int) atoi ( str );
9608 *output_array_size = wifi_count;
9609 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9610 pclose(fp);
9611
9612 if(wifi_count == 0)
9613 {
9614 return RETURN_OK;
9615 }
9616 else
9617 {
9618 wifi_associated_dev2_t* temp = NULL;
9619 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9620 *associated_dev_array = temp;
9621 if(temp == NULL)
9622 {
9623 printf("Error Statement. Insufficient memory \n");
9624 return RETURN_ERR;
9625 }
9626
9627 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9628 system(pipeCmd);
9629
9630 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9631 if(fp == NULL)
9632 {
9633 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9634 return RETURN_ERR;
9635 }
9636 fclose(fp);
9637
developer30423732022-12-01 16:17:49 +08009638 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009639 fp = popen(pipeCmd, "r");
9640 if(fp)
9641 {
9642 for(count =0 ; count < wifi_count; count++)
9643 {
9644 fgets(str, MAX_BUF_SIZE, fp);
9645 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9646 {
9647 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9648 {
9649 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9650
9651 }
9652 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9653 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]);
9654 }
9655 temp[count].cli_AuthenticationState = 1; //TODO
9656 temp[count].cli_Active = 1; //TODO
9657 }
9658 pclose(fp);
9659 }
9660
9661 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009662 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 +08009663 fp = popen(pipeCmd, "r");
9664 if(fp)
9665 {
9666 pclose(fp);
9667 }
9668 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9669 if(fp)
9670 {
9671 for(count =0 ; count < wifi_count ;count++)
9672 {
9673 fgets(str, MAX_BUF_SIZE, fp);
9674 signalstrength = atoi(str);
9675 temp[count].cli_RSSI = signalstrength;
9676 }
9677 pclose(fp);
9678 }
9679
9680
9681 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009682 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 +08009683 fp = popen(pipeCmd, "r");
9684 if (fp)
9685 {
9686 pclose(fp);
9687 }
9688 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9689 if (fp)
9690 {
9691 for (count = 0; count < wifi_count; count++)
9692 {
9693 fgets(str, MAX_BUF_SIZE, fp);
9694 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9695 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9696 }
9697 pclose(fp);
9698 }
9699
9700 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009701 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 +08009702 fp = popen(pipeCmd, "r");
9703 if (fp)
9704 {
9705 pclose(fp);
9706 }
9707 fp = popen("cat /tmp/Ass_Bitrate_Received.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_LastDataUplinkRate = strtoul(str, NULL, 10);
9714 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9715 }
9716 pclose(fp);
9717 }
9718 }
9719 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9720 return RETURN_OK;
9721
9722}
9723
9724INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9725{
9726#if 0
9727 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009728 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009729 _syscmd(cmd, buf, sizeof(buf));*/
9730
9731 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9732 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9733 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9734 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9735
9736 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.
9737 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].
9738 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].
9739 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].
9740 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9741 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9742
9743 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9744 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9745 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9746 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.
9747 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.
9748 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.
9749 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.
9750 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.
9751 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.
9752 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.
9753 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9754#endif
9755
9756 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009757 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009758 char pipeCmd[128] = {0};
9759 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009760 wifi_ssidTrafficStats2_t *out = output_struct;
9761
developerce736392022-09-13 15:24:34 +08009762 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009763 if (!output_struct)
9764 return RETURN_ERR;
9765
developerce736392022-09-13 15:24:34 +08009766 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009767 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009768 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009769 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009770
developer06a01d92022-09-07 16:32:39 +08009771 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009772 if (fp == NULL) {
9773 fprintf(stderr, "%s: popen failed\n", __func__);
9774 return RETURN_ERR;
9775 }
9776 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009777 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009778
developerce736392022-09-13 15:24:34 +08009779 if (strlen(str) == 0) // interface not exist
9780 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009781
developerce736392022-09-13 15:24:34 +08009782 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9783 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009784
developerce736392022-09-13 15:24:34 +08009785 memset(str, 0, sizeof(str));
9786 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009787 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009788 if (fp == NULL) {
9789 fprintf(stderr, "%s: popen failed\n", __func__);
9790 return RETURN_ERR;
9791 }
9792 fgets(str, sizeof(str), fp);
9793
9794 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9795 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009796 pclose(fp);
developerce736392022-09-13 15:24:34 +08009797
9798 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9799 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9800
9801 // Not supported
9802 output_struct->ssid_RetransCount = 0;
9803 output_struct->ssid_FailedRetransCount = 0;
9804 output_struct->ssid_RetryCount = 0;
9805 output_struct->ssid_MultipleRetryCount = 0;
9806 output_struct->ssid_ACKFailureCount = 0;
9807 output_struct->ssid_AggregatedPacketCount = 0;
9808
developer06a01d92022-09-07 16:32:39 +08009809 return RETURN_OK;
9810}
9811
9812//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).
9813INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9814{
9815 char output_val[16]={'\0'};
9816 char config_file[MAX_BUF_SIZE] = {0};
9817
9818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9819 if (!output)
9820 return RETURN_ERR;
9821 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developerefb790a2023-12-26 18:58:32 +08009822 if (!syn_flag)
9823 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9824 else
developer07ded1f2024-01-10 10:30:15 +08009825 snprintf(output_val, sizeof(output_val), "%s", vap_info[apIndex].ap_isolate);
developer06a01d92022-09-07 16:32:39 +08009826 if( strcmp(output_val,"1") == 0 )
9827 *output = TRUE;
9828 else
9829 *output = FALSE;
9830 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9831
9832 return RETURN_OK;
9833}
9834
9835INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9836{
9837 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9838 char str[MAX_BUF_SIZE]={'\0'};
9839 char string[MAX_BUF_SIZE]={'\0'};
9840 char cmd[MAX_CMD_SIZE]={'\0'};
9841 char *ch;
9842 char config_file[MAX_BUF_SIZE] = {0};
9843 struct params params;
9844
9845 if(enable == TRUE)
9846 strcpy(string,"1");
9847 else
9848 strcpy(string,"0");
9849
9850 params.name = "ap_isolate";
9851 params.value = string;
9852
9853 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9854 wifi_hostapdWrite(config_file,&params,1);
developerefb790a2023-12-26 18:58:32 +08009855 snprintf(vap_info[apIndex].ap_isolate, sizeof(vap_info[apIndex].ap_isolate), "%s", params.value);
developer06a01d92022-09-07 16:32:39 +08009856 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9857
9858 return RETURN_OK;
9859}
9860
9861INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9862{
9863 if (NULL == output_dBm)
9864 return RETURN_ERR;
9865
9866 *output_dBm = 0;
9867 return RETURN_OK;
9868}
9869
9870INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9871{
9872 return RETURN_OK;
9873}
9874INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9875{
9876 return RETURN_OK;
9877}
9878INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9879{
9880 return RETURN_OK;
9881}
9882INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9883{
9884 return RETURN_OK;
9885}
9886INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9887{
9888 return RETURN_OK;
9889}
9890INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9891{
9892 char config_file[MAX_BUF_SIZE] = {0};
9893 struct params list;
9894
9895 list.name = "bss_transition";
9896 list.value = activate?"1":"0";
9897 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9898 wifi_hostapdWrite(config_file, &list, 1);
developerefb790a2023-12-26 18:58:32 +08009899 snprintf(vap_info[apIndex].bss_transition, MAX_BUF_SIZE, "%s", list.value);
developer06a01d92022-09-07 16:32:39 +08009900
9901 return RETURN_OK;
9902}
9903wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9904
9905void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9906{
9907 return;
9908}
9909
9910INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9911{
9912 // TODO Implement me!
9913 return RETURN_OK;
9914}
9915
9916INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9917{
developera3c68b92022-09-13 15:27:29 +08009918 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009919 FILE *f = NULL;
9920
developer72ec5572023-01-05 16:27:13 +08009921 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009922
developer72ec5572023-01-05 16:27:13 +08009923 if (essid == NULL)
9924 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009925
developer72ec5572023-01-05 16:27:13 +08009926 if (strlen(essid) == 0 || apIndex == -1) {
9927 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9928 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009929 }
9930
developer72ec5572023-01-05 16:27:13 +08009931 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9932 f = fopen(file_name, "w");
9933 if (f == NULL)
9934 return RETURN_ERR;
9935
9936 // For mode == 0 is to disable filter, just don't write ssid to the file.
9937 fprintf(f, "%d\n%s", mode, mode?essid:"");
9938 fclose(f);
9939 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009940 return RETURN_OK;
9941}
9942
9943INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9944{
9945 // TODO Implement me!
9946 //Apply wifi_pushRadioChannel() instantly
9947 return RETURN_ERR;
9948}
9949
9950INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9951{
9952 // TODO Implement me!
9953 return RETURN_OK;
9954}
9955
9956#ifdef HAL_NETLINK_IMPL
9957static int tidStats_callback(struct nl_msg *msg, void *arg) {
9958 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9959 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9960 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9961 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9962 int rem , tid_index = 0;
9963
9964 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9965 wifi_associated_dev_tid_entry_t *stats_entry;
9966
9967 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9968 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9969 };
9970 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9971 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9972 };
9973
9974 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9975 genlmsg_attrlen(gnlh, 0), NULL);
9976
9977
9978 if (!tb[NL80211_ATTR_STA_INFO]) {
9979 fprintf(stderr, "station stats missing!\n");
9980 return NL_SKIP;
9981 }
9982
9983 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9984 tb[NL80211_ATTR_STA_INFO],
9985 stats_policy)) {
9986 fprintf(stderr, "failed to parse nested attributes!\n");
9987 return NL_SKIP;
9988 }
9989
9990 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9991 {
9992 stats_entry = &out->tid_array[tid_index];
9993
9994 stats_entry->tid = tid_index;
9995 stats_entry->ac = _tid_ac_index_get[tid_index];
9996
9997 if(sinfo[NL80211_STA_INFO_TID_STATS])
9998 {
9999 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
10000 printf("failed to parse nested stats attributes!");
10001 return NL_SKIP;
10002 }
10003 }
10004 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10005 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10006
10007 if(tid_index < (PS_MAX_TID - 1))
10008 tid_index++;
10009 }
10010 //ToDo: sum_time_ms, ewma_time_ms
10011 return NL_SKIP;
10012}
10013#endif
10014
10015INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
10016{
10017#ifdef HAL_NETLINK_IMPL
10018 Netlink nl;
10019 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010020 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010021
developerac6f1142022-12-20 19:26:35 +080010022 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010023 return RETURN_ERR;
10024
10025 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010026
10027 nl.id = initSock80211(&nl);
10028
10029 if (nl.id < 0) {
10030 fprintf(stderr, "Error initializing netlink \n");
10031 return -1;
10032 }
10033
10034 struct nl_msg* msg = nlmsg_alloc();
10035
10036 if (!msg) {
10037 fprintf(stderr, "Failed to allocate netlink message.\n");
10038 nlfree(&nl);
10039 return -2;
10040 }
10041
10042 genlmsg_put(msg,
10043 NL_AUTO_PORT,
10044 NL_AUTO_SEQ,
10045 nl.id,
10046 0,
10047 0,
10048 NL80211_CMD_GET_STATION,
10049 0);
10050
10051 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10052 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10053 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
10054 nl_send_auto(nl.socket, msg);
10055 nl_recvmsgs(nl.socket, nl.cb);
10056 nlmsg_free(msg);
10057 nlfree(&nl);
10058 return RETURN_OK;
10059#else
10060//iw implementation
10061#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
10062#define TOTAL_MAX_LINES 50
10063
10064 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +080010065 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +080010066 FILE *fp=NULL;
10067 char pipeCmd[1024]= {'\0'};
10068 int lines,tid_index=0;
10069 char mac_addr[20] = {'\0'};
10070
developerac6f1142022-12-20 19:26:35 +080010071 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010072 return RETURN_ERR;
10073
developer06a01d92022-09-07 16:32:39 +080010074 wifi_associated_dev_tid_entry_t *stats_entry;
10075
developer06a01d92022-09-07 16:32:39 +080010076 strcpy(mac_addr,clientMacAddress);
10077
10078 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
10079 fp= popen(pipeCmd,"r");
10080 if(fp == NULL)
10081 {
10082 perror("popen for station dump failed\n");
10083 return RETURN_ERR;
10084 }
10085 pclose(fp);
10086
10087 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
10088 fp=popen(pipeCmd,"r");
10089 if(fp == NULL)
10090 {
10091 perror("popen for grep station failed\n");
10092 return RETURN_ERR;
10093 }
10094 else if(fgets(buf,sizeof(buf),fp) != NULL)
10095 lines=atoi(buf);
10096 else
10097 {
10098 pclose(fp);
10099 fprintf(stderr,"No devices are connected \n");
10100 return RETURN_ERR;
10101 }
10102 pclose(fp);
10103
10104 if(lines == 1)
10105 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
10106
10107 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
10108 {
10109 stats_entry = &tid_stats->tid_array[tid_index];
10110 stats_entry->tid = tid_index;
10111
10112 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);
10113
10114 fp=popen(pipeCmd,"r");
10115 if(fp ==NULL)
10116 {
10117 perror("Failed to read from tid file \n");
10118 return RETURN_ERR;
10119 }
10120 else if(fgets(buf,sizeof(buf),fp) != NULL)
10121 stats_entry->num_msdus = atol(buf);
10122
10123 pclose(fp);
10124 stats_entry->ac = _tid_ac_index_get[tid_index];
10125// TODO:
10126// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
10127// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
10128 }
10129 return RETURN_OK;
10130#endif
10131}
10132
10133
10134INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
10135{
developerd946fd62022-12-08 18:03:28 +080010136 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +080010137 char cmd[128]={0};
10138 char buf[128]={0};
10139 int freq = 0;
developer63a1ef02024-05-03 16:59:38 +080010140 wifi_band band = band_invalid;
developer615510b2022-09-27 10:14:35 +080010141
10142 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10143
developer63a1ef02024-05-03 16:59:38 +080010144 band = wifi_index_to_band(apIndex);
developer615510b2022-09-27 10:14:35 +080010145 // full mode is used to scan all channels.
10146 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10147 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
developer63a1ef02024-05-03 16:59:38 +080010148 freq = ieee80211_channel_to_frequency(chan_list[0], band);
developer615510b2022-09-27 10:14:35 +080010149
developerac6f1142022-12-20 19:26:35 +080010150 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010151 return RETURN_ERR;
10152
developer615510b2022-09-27 10:14:35 +080010153 if (freq)
developerd946fd62022-12-08 18:03:28 +080010154 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +080010155 else
developerd946fd62022-12-08 18:03:28 +080010156 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +080010157
10158 _syscmd(cmd, buf, sizeof(buf));
10159 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10160
developer06a01d92022-09-07 16:32:39 +080010161 return RETURN_OK;
10162}
10163
10164
10165INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10166{
10167 // TODO Implement me!
10168 return RETURN_ERR;
10169}
10170
10171INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10172{
10173 // TODO Implement me!
10174 return RETURN_ERR;
10175}
10176
10177INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10178{
10179 // TODO Implement me!
10180 return RETURN_ERR;
10181}
10182
10183INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10184{
10185 // TODO Implement me!
10186 return RETURN_ERR;
10187}
10188
10189INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10190{
10191 // TODO Implement me!
10192 return RETURN_ERR;
10193}
10194
10195INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10196{
10197 // TODO Implement me!
10198 return RETURN_ERR;
10199}
10200
10201INT wifi_steering_eventUnregister(void)
10202{
10203 // TODO Implement me!
10204 return RETURN_ERR;
10205}
10206
10207INT wifi_delApAclDevices(INT apIndex)
10208{
10209#if 0
10210 char cmd[MAX_BUF_SIZE] = {0};
10211 char buf[MAX_BUF_SIZE] = {0};
10212
10213 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +080010214 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +080010215 if(_syscmd(cmd,buf,sizeof(buf)))
10216 return RETURN_ERR;
10217#endif
developer9988c232023-03-06 14:57:08 +080010218 char cmd[256]={0};
10219 char buf[64]={0};
developer06a01d92022-09-07 16:32:39 +080010220
developere6aafda2022-09-13 14:59:28 +080010221 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer9988c232023-03-06 14:57:08 +080010222 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 +080010223 if(_syscmd(cmd, buf, sizeof(buf)))
10224 return RETURN_ERR;
10225 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010226
10227 return RETURN_OK;
10228}
10229
10230#ifdef HAL_NETLINK_IMPL
10231static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10232 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10233 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10234 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10235 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10236 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10237 char mac_addr[20],dev[20];
10238
10239 nla_parse(tb,
10240 NL80211_ATTR_MAX,
10241 genlmsg_attrdata(gnlh, 0),
10242 genlmsg_attrlen(gnlh, 0),
10243 NULL);
10244
10245 if(!tb[NL80211_ATTR_STA_INFO]) {
10246 fprintf(stderr, "sta stats missing!\n");
10247 return NL_SKIP;
10248 }
10249
10250 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10251 fprintf(stderr, "failed to parse nested attributes!\n");
10252 return NL_SKIP;
10253 }
10254 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10255
10256 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10257
10258 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10259 fprintf(stderr, "failed to parse nested rate attributes!");
10260 return NL_SKIP;
10261 }
10262
10263 if(sinfo[NL80211_STA_INFO_TID_STATS])
10264 {
10265 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10266 printf("failed to parse nested stats attributes!");
10267 return NL_SKIP;
10268 }
10269 }
10270
10271 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10272 {
10273 printf("Type is VHT\n");
10274 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10275 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10276
10277 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10278 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10279 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10280 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10281 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10282 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10283 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10284 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10285 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10286 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10287 }
10288 else
10289 {
10290 printf(" OFDM or CCK \n");
10291 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10292 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10293 }
10294
10295 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10296 if(rinfo[NL80211_RATE_INFO_MCS])
10297 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10298 }
10299 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10300 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10301 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10302 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10303
10304 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10305 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10306
10307 if (sinfo[NL80211_STA_INFO_SIGNAL])
10308 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10309 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10310 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10311 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10312 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10313 //rssi_array need to be filled
10314 return NL_SKIP;
10315}
10316#endif
10317
10318INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10319{
10320#ifdef HAL_NETLINK_IMPL
10321 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010322 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010323 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010324 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010325
10326 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10327
10328 if (*output_array_size <= 0)
10329 return RETURN_OK;
10330
developer06a01d92022-09-07 16:32:39 +080010331 nl.id = initSock80211(&nl);
10332
10333 if (nl.id < 0) {
10334 fprintf(stderr, "Error initializing netlink \n");
10335 return 0;
10336 }
10337
10338 struct nl_msg* msg = nlmsg_alloc();
10339
10340 if (!msg) {
10341 fprintf(stderr, "Failed to allocate netlink message.\n");
10342 nlfree(&nl);
10343 return 0;
10344 }
10345
10346 genlmsg_put(msg,
10347 NL_AUTO_PORT,
10348 NL_AUTO_SEQ,
10349 nl.id,
10350 0,
10351 0,
10352 NL80211_CMD_GET_STATION,
10353 0);
10354
10355 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10356 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10357 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10358 nl_send_auto(nl.socket, msg);
10359 nl_recvmsgs(nl.socket, nl.cb);
10360 nlmsg_free(msg);
10361 nlfree(&nl);
10362 return RETURN_OK;
10363#else
10364 //TODO Implement me
10365 return RETURN_OK;
10366#endif
10367}
10368
10369#ifdef HAL_NETLINK_IMPL
10370static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10371 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10372 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10373 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10374 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10375 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10376 char mac_addr[20],dev[20];
10377
10378 nla_parse(tb,
10379 NL80211_ATTR_MAX,
10380 genlmsg_attrdata(gnlh, 0),
10381 genlmsg_attrlen(gnlh, 0),
10382 NULL);
10383
10384 if(!tb[NL80211_ATTR_STA_INFO]) {
10385 fprintf(stderr, "sta stats missing!\n");
10386 return NL_SKIP;
10387 }
10388
10389 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10390 fprintf(stderr, "failed to parse nested attributes!\n");
10391 return NL_SKIP;
10392 }
10393
10394 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10395
10396 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10397
10398 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10399 fprintf(stderr, "failed to parse nested rate attributes!");
10400 return NL_SKIP;
10401 }
10402
10403 if(sinfo[NL80211_STA_INFO_TID_STATS])
10404 {
10405 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10406 printf("failed to parse nested stats attributes!");
10407 return NL_SKIP;
10408 }
10409 }
10410 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10411 {
10412 printf("Type is VHT\n");
10413 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10414 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10415
10416 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10417 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10418 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10419 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10420 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10421 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10422 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10423 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10424 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10425 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10426 }
10427 else
10428 {
10429 printf(" OFDM or CCK \n");
10430 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10431 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10432 }
10433
10434 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10435 if(rinfo[NL80211_RATE_INFO_MCS])
10436 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10437 }
10438
10439 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10440 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10441 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10442 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10443
10444 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10445 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10446 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10447
10448 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10449 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10450
10451 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10452 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10453
10454 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10455 ((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]);
10456
10457 return NL_SKIP;
10458}
10459#endif
10460
10461INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10462{
10463#ifdef HAL_NETLINK_IMPL
10464 Netlink nl;
10465 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010466 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010467 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010468 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010469
10470 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10471
10472 if (*output_array_size <= 0)
10473 return RETURN_OK;
10474
developerd946fd62022-12-08 18:03:28 +080010475 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010476
10477 nl.id = initSock80211(&nl);
10478
10479 if(nl.id < 0) {
10480 fprintf(stderr, "Error initializing netlink \n");
10481 return 0;
10482 }
10483
10484 struct nl_msg* msg = nlmsg_alloc();
10485
10486 if(!msg) {
10487 fprintf(stderr, "Failed to allocate netlink message.\n");
10488 nlfree(&nl);
10489 return 0;
10490 }
10491
10492 genlmsg_put(msg,
10493 NL_AUTO_PORT,
10494 NL_AUTO_SEQ,
10495 nl.id,
10496 0,
10497 0,
10498 NL80211_CMD_GET_STATION,
10499 0);
10500
10501 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10502 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10503 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10504 nl_send_auto(nl.socket, msg);
10505 nl_recvmsgs(nl.socket, nl.cb);
10506 nlmsg_free(msg);
10507 nlfree(&nl);
10508 return RETURN_OK;
10509#else
10510 //TODO Implement me
10511 return RETURN_OK;
10512#endif
10513}
10514
10515INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10516{
10517 // TODO Implement me!
10518 char buf[MAX_BUF_SIZE] = {0};
10519 char config_file[MAX_BUF_SIZE] = {0};
10520
10521 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerefb790a2023-12-26 18:58:32 +080010522 if (!syn_flag)
10523 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10524 else
developer07ded1f2024-01-10 10:30:15 +080010525 snprintf(buf, sizeof(buf), "%s", vap_info[apIndex].bss_transition);
developer06a01d92022-09-07 16:32:39 +080010526 *activate = (strncmp("1",buf,1) == 0);
10527
10528 return RETURN_OK;
10529}
10530
10531INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10532{
10533 char config_file[MAX_BUF_SIZE] = {0};
10534 struct params list;
10535
10536 list.name = "rrm_neighbor_report";
10537 list.value = activate?"1":"0";
10538 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10539 wifi_hostapdWrite(config_file, &list, 1);
10540
10541 return RETURN_OK;
10542}
10543
10544INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10545{
10546 char buf[32] = {0};
10547 char config_file[MAX_BUF_SIZE] = {0};
10548
10549 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10550 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10551 *activate = (strncmp("1",buf,1) == 0);
10552
10553 return RETURN_OK;
10554}
10555#undef HAL_NETLINK_IMPL
10556#ifdef HAL_NETLINK_IMPL
10557static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10558 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10559 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10560 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10561 char dev[20];
10562 int freq =0 ;
10563 static int i=0;
10564
10565 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10566
10567 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10568 };
10569
10570 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10571
10572 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10573
10574 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10575 fprintf(stderr, "survey data missing!\n");
10576 return NL_SKIP;
10577 }
10578
10579 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10580 {
10581 fprintf(stderr, "failed to parse nested attributes!\n");
10582 return NL_SKIP;
10583 }
10584
10585
10586 if(out[0].array_size == 1 )
10587 {
10588 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10589 {
10590 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10591 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10592 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10593
10594 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10595 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10596 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10597 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10598 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10599 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10600 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10601 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10602 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10603 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10604 if (sinfo[NL80211_SURVEY_INFO_TIME])
10605 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10606 return NL_STOP;
10607 }
10608 }
10609 else
10610 {
10611 if ( i <= out[0].array_size )
10612 {
10613 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10614 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10615 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10616
10617 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10618 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10619 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10620 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10621 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10622 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10623 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10624 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10625 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10626 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10627 if (sinfo[NL80211_SURVEY_INFO_TIME])
10628 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10629 }
10630 }
10631
10632 i++;
10633 return NL_SKIP;
10634}
10635#endif
10636
developer63a1ef02024-05-03 16:59:38 +080010637static int ieee80211_channel_to_frequency(int chan, wifi_band band)
developer06a01d92022-09-07 16:32:39 +080010638{
developer63a1ef02024-05-03 16:59:38 +080010639 /* see 802.11 17.3.8.3.2 and Annex J
10640 * there are overlapping channel numbers in 5GHz and 2GHz bands */
10641 if (chan <= 0)
10642 return -1; /* not supported */
10643 switch (band) {
10644 case band_2_4:
10645 if (chan == 14)
10646 return 2484;
10647 else if (chan < 14)
10648 return (2407 + chan * 5);
10649 break;
10650 case band_5:
10651 if (chan >= 182 && chan <= 196)
10652 return (4000 + chan * 5);
10653 else
10654 return (5000 + chan * 5);
10655 break;
10656 case band_6:
10657 /* see 802.11ax D6.1 27.3.23.2 */
10658 if (chan == 2)
10659 return 5935;
10660 if (chan <= 233)
10661 return (5950 + chan * 5);
10662 break;
10663 default:
10664 return -1;
10665 break;
developer06a01d92022-09-07 16:32:39 +080010666 }
developer06a01d92022-09-07 16:32:39 +080010667}
10668
10669static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10670{
10671 int freqMHz = -1;
10672 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010673 char interface_name[16] = {0};
developer63a1ef02024-05-03 16:59:38 +080010674 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +080010675
developer63a1ef02024-05-03 16:59:38 +080010676 band = wifi_index_to_band(radioIndex);
10677 freqMHz = ieee80211_channel_to_frequency(channel, band);
developer06a01d92022-09-07 16:32:39 +080010678 if (freqMHz == -1) {
10679 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10680 return -1;
10681 }
10682
developer7930d352022-12-21 17:55:42 +080010683 wifi_GetInterfaceName(radioIndex, interface_name);
10684 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010685 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10686 radioIndex, freqMHz);
10687 return -1;
10688 }
10689
10690 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10691 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10692 return -1;
10693 }
10694
10695 return 0;
10696}
10697
10698static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10699{
10700 const char *ptr = buf;
10701 char *key = NULL;
10702 char *val = NULL;
10703 char line[256] = { '\0' };
10704
10705 while (ptr = get_line_from_str_buf(ptr, line)) {
10706 if (strstr(line, "Frequency")) continue;
10707
10708 key = strtok(line, ":");
10709 val = strtok(NULL, " ");
10710 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10711
10712 if (!strcmp(key, "noise")) {
10713 sscanf(val, "%d", &stats->ch_noise);
10714 if (stats->ch_noise == 0) {
10715 // Workaround for missing noise information.
10716 // Assume -95 for 2.4G and -103 for 5G
10717 if (radioIndex == 0) stats->ch_noise = -95;
10718 if (radioIndex == 1) stats->ch_noise = -103;
10719 }
10720 }
10721 else if (!strcmp(key, "channel active time")) {
10722 sscanf(val, "%llu", &stats->ch_utilization_total);
10723 }
10724 else if (!strcmp(key, "channel busy time")) {
10725 sscanf(val, "%llu", &stats->ch_utilization_busy);
10726 }
10727 else if (!strcmp(key, "channel receive time")) {
10728 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10729 }
10730 else if (!strcmp(key, "channel transmit time")) {
10731 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10732 }
10733 };
10734
10735 return 0;
10736}
10737
10738INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10739{
10740 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10741#ifdef HAL_NETLINK_IMPL
10742 Netlink nl;
10743 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010744 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010745
10746 local[0].array_size = array_size;
10747
developerac6f1142022-12-20 19:26:35 +080010748 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010749 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010750
10751 nl.id = initSock80211(&nl);
10752
10753 if (nl.id < 0) {
10754 fprintf(stderr, "Error initializing netlink \n");
10755 return -1;
10756 }
10757
10758 struct nl_msg* msg = nlmsg_alloc();
10759
10760 if (!msg) {
10761 fprintf(stderr, "Failed to allocate netlink message.\n");
10762 nlfree(&nl);
10763 return -2;
10764 }
10765
10766 genlmsg_put(msg,
10767 NL_AUTO_PORT,
10768 NL_AUTO_SEQ,
10769 nl.id,
10770 0,
10771 NLM_F_DUMP,
10772 NL80211_CMD_GET_SURVEY,
10773 0);
10774
10775 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10776 nl_send_auto(nl.socket, msg);
10777 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10778 nl_recvmsgs(nl.socket, nl.cb);
10779 nlmsg_free(msg);
10780 nlfree(&nl);
10781 //Copying the Values
10782 for(int i=0;i<array_size;i++)
10783 {
10784 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10785 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10786 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10787 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10788 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10789 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10790 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10791 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10792 }
10793#else
10794 ULONG channel = 0;
10795 int i;
10796 int number_of_channels = array_size;
10797 char buf[512];
10798 INT ret;
10799 wifi_channelStats_t tmp_stats;
10800
10801 if (number_of_channels == 0) {
10802 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10803 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10804 return RETURN_ERR;
10805 }
10806 number_of_channels = 1;
10807 input_output_channelStats_array[0].ch_number = channel;
10808 }
10809
10810 for (i = 0; i < number_of_channels; i++) {
10811
10812 input_output_channelStats_array[i].ch_noise = 0;
10813 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10814 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10815 input_output_channelStats_array[i].ch_utilization_busy = 0;
10816 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10817 input_output_channelStats_array[i].ch_utilization_total = 0;
10818
10819 memset(buf, 0, sizeof(buf));
10820 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10821 return RETURN_ERR;
10822 }
10823 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10824 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10825 return RETURN_ERR;
10826 }
10827
10828 // XXX: fake missing 'self' counter which is not available in iw survey output
10829 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10830 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10831
10832 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10833 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10834 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10835 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10836 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10837
10838 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",
10839 __func__,
10840 input_output_channelStats_array[i].ch_number,
10841 input_output_channelStats_array[i].ch_noise,
10842 input_output_channelStats_array[i].ch_utilization_total,
10843 input_output_channelStats_array[i].ch_utilization_busy,
10844 input_output_channelStats_array[i].ch_utilization_busy_rx,
10845 input_output_channelStats_array[i].ch_utilization_busy_tx,
10846 input_output_channelStats_array[i].ch_utilization_busy_self,
10847 input_output_channelStats_array[i].ch_utilization_busy_ext);
10848 }
10849#endif
10850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10851 return RETURN_OK;
10852}
10853#define HAL_NETLINK_IMPL
10854
10855/* Hostapd events */
10856
10857#ifndef container_of
10858#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10859#define container_of(ptr, type, member) \
10860 ((type *)((char *)ptr - offset_of(type, member)))
10861#endif /* container_of */
10862
10863struct ctrl {
10864 char sockpath[128];
10865 char sockdir[128];
10866 char bss[IFNAMSIZ];
10867 char reply[4096];
10868 int ssid_index;
10869 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10870 void (*overrun)(struct ctrl *ctrl);
10871 struct wpa_ctrl *wpa;
10872 unsigned int ovfl;
10873 size_t reply_len;
10874 int initialized;
10875 ev_timer retry;
10876 ev_timer watchdog;
10877 ev_stat stat;
10878 ev_io io;
10879};
10880static wifi_newApAssociatedDevice_callback clients_connect_cb;
10881static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10882static struct ctrl wpa_ctrl[MAX_APS];
10883static int initialized;
10884
10885static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10886{
10887 char cbuf[256] = {};
10888 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10889 struct cmsghdr *cmsg;
10890 unsigned int ovfl = ctrl->ovfl;
10891 unsigned int drop;
10892
10893 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10894 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10895 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10896 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10897
10898 drop = ovfl - ctrl->ovfl;
10899 ctrl->ovfl = ovfl;
10900
10901 return drop;
10902}
10903
10904static void ctrl_close(struct ctrl *ctrl)
10905{
10906 if (ctrl->io.cb)
10907 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10908 if (ctrl->retry.cb)
10909 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10910 if (!ctrl->wpa)
10911 return;
10912
10913 wpa_ctrl_detach(ctrl->wpa);
10914 wpa_ctrl_close(ctrl->wpa);
10915 ctrl->wpa = NULL;
10916 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10917}
10918
10919static void ctrl_process(struct ctrl *ctrl)
10920{
10921 const char *str;
10922 int drops;
10923 int level;
10924 int err;
10925
10926 /* Example events:
10927 *
10928 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10929 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10930 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10931 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10932 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10933 */
10934 if (!(str = index(ctrl->reply, '>')))
10935 return;
10936 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10937 return;
10938
10939 str++;
10940
10941 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10942 if (!(str = index(ctrl->reply, ' ')))
10943 return;
10944 wifi_associated_dev_t sta;
10945 memset(&sta, 0, sizeof(sta));
10946
10947 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10948 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10949 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10950
10951 sta.cli_Active=true;
10952
10953 (clients_connect_cb)(ctrl->ssid_index, &sta);
10954 goto handled;
10955 }
10956
10957 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10958 if (!(str = index(ctrl->reply, ' ')))
10959 return;
10960
10961 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10962 goto handled;
10963 }
10964
10965 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10966 printf("CTRL_WPA: handle TERMINATING event\n");
10967 goto retry;
10968 }
10969
10970 if (strncmp("AP-DISABLED", str, 11) == 0) {
10971 printf("CTRL_WPA: handle AP-DISABLED\n");
10972 goto retry;
10973 }
10974
10975 printf("Event not supported!!\n");
10976
10977handled:
10978
10979 if ((drops = ctrl_get_drops(ctrl))) {
10980 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10981 if (ctrl->overrun)
10982 ctrl->overrun(ctrl);
10983 }
10984
10985 return;
10986
10987retry:
10988 printf("WPA_CTRL: closing\n");
10989 ctrl_close(ctrl);
10990 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10991 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10992}
10993
10994static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10995{
10996 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10997 int err;
10998
10999 memset(ctrl->reply, 0, sizeof(ctrl->reply));
11000 ctrl->reply_len = sizeof(ctrl->reply) - 1;
11001 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
11002 ctrl->reply[ctrl->reply_len] = 0;
11003 if (err < 0) {
11004 if (errno == EAGAIN || errno == EWOULDBLOCK)
11005 return;
11006 ctrl_close(ctrl);
11007 ev_timer_again(EV_A_ &ctrl->retry);
11008 return;
11009 }
11010
11011 ctrl_process(ctrl);
11012}
11013
11014static int ctrl_open(struct ctrl *ctrl)
11015{
11016 int fd;
11017
11018 if (ctrl->wpa)
11019 return 0;
11020
11021 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
11022 if (!ctrl->wpa)
11023 goto err;
11024
11025 if (wpa_ctrl_attach(ctrl->wpa) < 0)
11026 goto err_close;
11027
11028 fd = wpa_ctrl_get_fd(ctrl->wpa);
11029 if (fd < 0)
11030 goto err_detach;
11031
11032 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
11033 goto err_detach;
11034
11035 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
11036 ev_io_start(EV_DEFAULT_ &ctrl->io);
11037
11038 return 0;
11039
11040err_detach:
11041 wpa_ctrl_detach(ctrl->wpa);
11042err_close:
11043 wpa_ctrl_close(ctrl->wpa);
11044err:
11045 ctrl->wpa = NULL;
11046 return -1;
11047}
11048
11049static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
11050{
11051 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
11052
11053 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
11054 ctrl_open(ctrl);
11055}
11056
11057static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
11058{
11059 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
11060
11061 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
11062 if (ctrl_open(ctrl) == 0) {
11063 printf("WPA_CTRL: retry successful\n");
11064 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11065 }
11066}
11067
11068int ctrl_enable(struct ctrl *ctrl)
11069{
11070 if (ctrl->wpa)
11071 return 0;
11072
11073 if (!ctrl->stat.cb) {
11074 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
11075 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
11076 }
11077
11078 if (!ctrl->retry.cb) {
11079 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
11080 }
11081
11082 return ctrl_open(ctrl);
11083}
11084
11085static void
11086ctrl_msg_cb(char *buf, size_t len)
11087{
11088 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
11089
11090 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
11091 ctrl_process(ctrl);
11092}
11093
11094static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
11095{
11096 int err;
11097
11098 if (!ctrl->wpa)
11099 return -1;
11100 if (*reply_len < 2)
11101 return -1;
11102
11103 (*reply_len)--;
11104 ctrl->reply_len = sizeof(ctrl->reply);
11105 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
11106 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
11107 if (err < 0)
11108 return err;
11109
11110 if (ctrl->reply_len > *reply_len)
11111 ctrl->reply_len = *reply_len;
11112
11113 *reply_len = ctrl->reply_len;
11114 memcpy(reply, ctrl->reply, *reply_len);
11115 reply[*reply_len - 1] = 0;
11116 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11117 return 0;
11118}
11119
11120static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11121{
11122 const char *pong = "PONG";
11123 const char *ping = "PING";
11124 char reply[1024];
11125 size_t len = sizeof(reply);
11126 int err;
11127 ULONG s, snum;
11128 INT ret;
11129 BOOL status;
11130
11131 printf("WPA_CTRL: watchdog cb\n");
11132
11133 ret = wifi_getSSIDNumberOfEntries(&snum);
11134 if (ret != RETURN_OK) {
11135 printf("%s: failed to get SSID count", __func__);
11136 return;
11137 }
11138
11139 if (snum > MAX_APS) {
11140 printf("more ssid than supported! %lu\n", snum);
11141 return;
11142 }
11143
11144 for (s = 0; s < snum; s++) {
11145 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080011146 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080011147 continue;
11148 }
11149 if (status == false) continue;
11150
11151 memset(reply, 0, sizeof(reply));
11152 len = sizeof(reply);
11153 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
11154 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
11155 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11156 continue;
11157
11158 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11159 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080011160 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080011161 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11162 }
11163}
11164
11165static int init_wpa()
11166{
11167 int ret = 0, i = 0;
11168 ULONG s, snum;
11169
11170 ret = wifi_getSSIDNumberOfEntries(&snum);
11171 if (ret != RETURN_OK) {
11172 printf("%s: failed to get SSID count", __func__);
11173 return RETURN_ERR;
11174 }
11175
11176 if (snum > MAX_APS) {
11177 printf("more ssid than supported! %lu\n", snum);
11178 return RETURN_ERR;
11179 }
11180
11181 for (s = 0; s < snum; s++) {
11182 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11183 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11184 wpa_ctrl[s].ssid_index = s;
11185 ctrl_enable(&wpa_ctrl[s]);
11186 }
11187
11188 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11189 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11190
11191 initialized = 1;
11192 printf("WPA_CTRL: initialized\n");
11193
11194 return RETURN_OK;
11195}
11196
11197void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11198{
11199 clients_connect_cb = callback_proc;
11200 if (!initialized)
11201 init_wpa();
11202}
11203
11204void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11205{
11206 clients_disconnect_cb = callback_proc;
11207 if (!initialized)
11208 init_wpa();
11209}
11210
11211INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11212{
11213 // TODO Implement me!
11214 return RETURN_ERR;
11215}
11216
11217INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11218{
11219 // TODO Implement me!
11220 return RETURN_ERR;
11221}
11222
11223INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11224{
11225 int i;
developer63a1ef02024-05-03 16:59:38 +080011226 int phyId = -1, band_remap = 0, range_remap = 0;
developer4b102122023-02-15 10:53:03 +080011227 char cmd[256] = {0};
11228 char channel_numbers_buf[256] = {0};
11229 char dfs_state_buf[256] = {0};
11230 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080011231 const char *ptr;
developer4b102122023-02-15 10:53:03 +080011232 BOOL dfs_enable = false;
developer63a1ef02024-05-03 16:59:38 +080011233 wifi_band band = band_invalid;
11234
11235 band = wifi_index_to_band(radioIndex);
11236 switch (band) {
11237 case band_2_4:
11238 band_remap = 1;
11239 range_remap = 2;
11240 break;
11241 case band_5:
11242 band_remap = 2;
11243 range_remap = 4;
11244 break;
11245 case band_6:
11246 band_remap = 4;
11247 range_remap = 4;
11248 break;
11249 default:
11250 break;
11251 }
developer06a01d92022-09-07 16:32:39 +080011252
developer4b102122023-02-15 10:53:03 +080011253 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080011254
developer4b102122023-02-15 10:53:03 +080011255 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11256 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011257
developer63a1ef02024-05-03 16:59:38 +080011258 snprintf(cmd, sizeof (cmd),
11259 "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 '[]'",
11260 phyId, band_remap, range_remap, band_remap, range_remap, dfs_enable?"":"radar\\|");
developer06a01d92022-09-07 16:32:39 +080011261
developer4b102122023-02-15 10:53:03 +080011262 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11263 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11264 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011265 }
11266
developer4b102122023-02-15 10:53:03 +080011267 ptr = channel_numbers_buf;
11268 i = 0;
11269 while (ptr = get_line_from_str_buf(ptr, line)) {
11270 if (i >= outputMapSize) {
11271 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11272 return RETURN_ERR;
11273 }
11274 sscanf(line, "%d", &outputMap[i].ch_number);
11275
11276 memset(cmd, 0, sizeof(cmd));
11277 // Below command should fetch string for DFS state (usable, available or unavailable)
11278 // Example line: "DFS state: usable (for 78930 sec)"
11279 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) {
11280 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011281 return RETURN_ERR;
11282 }
11283
developer4b102122023-02-15 10:53:03 +080011284 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11285 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011286 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11287 return RETURN_ERR;
11288 }
11289
developer4b102122023-02-15 10:53:03 +080011290 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011291
developer4b102122023-02-15 10:53:03 +080011292 if (!strcmp(dfs_state_buf, "usable")) {
11293 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11294 } else if (!strcmp(dfs_state_buf, "available")) {
11295 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11296 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11297 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11298 } else {
11299 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011300 }
developer4b102122023-02-15 10:53:03 +080011301 i++;
developer06a01d92022-09-07 16:32:39 +080011302 }
11303
developer4b102122023-02-15 10:53:03 +080011304 return RETURN_OK;
11305
developer06a01d92022-09-07 16:32:39 +080011306 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11307 return RETURN_ERR;
11308}
11309
11310INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11311{
11312 // TODO Implement me!
11313 return RETURN_ERR;
11314}
11315
11316INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11317{
11318 return RETURN_OK;
11319}
11320
11321INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11322{
11323 // TODO Implement me!
11324 return RETURN_ERR;
11325}
11326
11327INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11328{
11329 // TODO API refrence Implementaion is present on RPI hal
11330 return RETURN_ERR;
11331}
11332
developerfeab1d12023-09-27 11:29:38 +080011333
developer06a01d92022-09-07 16:32:39 +080011334INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11335{
developera5005b62022-09-13 15:43:35 +080011336 char cmd[128]={'\0'};
11337 char buf[128]={'\0'};
developerfeab1d12023-09-27 11:29:38 +080011338 int radioIndex = -1;
11339 int phyIndex = -1;
11340 bool enabled = false;
11341 int cur_tx_dbm = 0;
developera5005b62022-09-13 15:43:35 +080011342
11343 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfeab1d12023-09-27 11:29:38 +080011344
developera5005b62022-09-13 15:43:35 +080011345 if(txpwr_pcntg == NULL)
11346 return RETURN_ERR;
11347
developerfeab1d12023-09-27 11:29:38 +080011348 // The API name as getRadioXXX, I think the input index should be radioIndex,
11349 // but current we not change the name, but use it as radioIndex
11350 radioIndex = apIndex;
11351 phyIndex = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +080011352
developera5005b62022-09-13 15:43:35 +080011353 // Get the maximum tx power of the device
developerfeab1d12023-09-27 11:29:38 +080011354 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
developer439baa32024-05-02 15:54:58 +080011355 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", single_wiphy ? radioIndex : phyIndex);
developera5005b62022-09-13 15:43:35 +080011356 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011357 if (strcmp(buf, "enable") == 0)
11358 enabled = true;
developera5005b62022-09-13 15:43:35 +080011359
developerfeab1d12023-09-27 11:29:38 +080011360 if (!enabled) {
11361 *txpwr_pcntg = 100;
11362 return RETURN_OK;
11363 }
11364
developera5005b62022-09-13 15:43:35 +080011365 memset(cmd, 0, sizeof(cmd));
11366 memset(buf, 0, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011367 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
developer439baa32024-05-02 15:54:58 +080011368 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", single_wiphy ? radioIndex : phyIndex);
developera5005b62022-09-13 15:43:35 +080011369 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011370 cur_tx_dbm = strtol(buf, NULL, 10);
developera5005b62022-09-13 15:43:35 +080011371
developerfeab1d12023-09-27 11:29:38 +080011372 switch (cur_tx_dbm) {
11373 case 0:
11374 *txpwr_pcntg = 100; // range 91-100
developera5005b62022-09-13 15:43:35 +080011375 break;
developerfeab1d12023-09-27 11:29:38 +080011376 case 1:
11377 *txpwr_pcntg = 75; // range 61-90
11378 break;
11379 case 3:
11380 *txpwr_pcntg = 50; // range 31-60
11381 break;
11382 case 6:
11383 *txpwr_pcntg = 25; // range 16-30
11384 break;
11385 case 9:
11386 *txpwr_pcntg = 12; // range 10-15
11387 break;
11388 case 12:
11389 *txpwr_pcntg = 6; // range 1-9
11390 break;
11391 default:
11392 *txpwr_pcntg = 100; // 0
developera5005b62022-09-13 15:43:35 +080011393 }
developerfeab1d12023-09-27 11:29:38 +080011394
developer06a01d92022-09-07 16:32:39 +080011395 return RETURN_OK;
11396}
11397
11398INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11399{
developer58599c22022-09-13 16:40:34 +080011400 // TODO precac feature.
11401 struct params params = {0};
11402 char config_file[128] = {0};
11403
11404 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11405
11406 params.name = "enable_background_radar";
11407 params.value = enable?"1":"0";
11408 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11409 wifi_hostapdWrite(config_file, &params, 1);
11410 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11411
11412 /* TODO precac feature */
11413
11414 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11415 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011416}
11417
11418INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11419{
developer58599c22022-09-13 16:40:34 +080011420 char config_file[128] = {0};
11421 char buf[64] = {0};
11422
11423 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11424 if (NULL == enable || NULL == precac)
11425 return RETURN_ERR;
11426
11427 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11428 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
developerf7e92b62023-05-04 17:06:52 +080011429 if (strncmp(buf, "1", 1) == 0) {
developer58599c22022-09-13 16:40:34 +080011430 *enable = true;
developerf7e92b62023-05-04 17:06:52 +080011431 *precac = true;
11432 } else {
developer58599c22022-09-13 16:40:34 +080011433 *enable = false;
developerf7e92b62023-05-04 17:06:52 +080011434 *precac = false;
11435 }
developer58599c22022-09-13 16:40:34 +080011436
11437 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11438 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011439}
11440
11441INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11442{
developer58599c22022-09-13 16:40:34 +080011443 *supported = TRUE;
11444 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011445}
11446
developera7149722023-01-11 11:36:21 +080011447bool check_is_hemu_vendor_new_patch() {
11448 char cmd[128] = {0};
11449 char buf[128] = {0};
11450
11451 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11452 _syscmd(cmd, buf, sizeof(buf));
11453
11454 if (strlen(buf) > 0)
11455 return FALSE;
11456 else
11457 return TRUE;
11458}
11459
developer3e6b1692022-09-30 18:04:05 +080011460INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11461{
11462 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11463 struct params params = {0};
11464 char config_file[64] = {0};
11465 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011466 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011467 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011468 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011469 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11470
developera7149722023-01-11 11:36:21 +080011471 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011472
11473 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11474 set_mu_type &= ~0x05; // unset bit 0, 2
11475 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11476 set_mu_type |= 0x01;
11477 set_mu_type &= ~0x04;
11478 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11479 set_mu_type &= ~0x01;
11480 set_mu_type |= 0x04;
11481 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11482 set_mu_type |= 0x05; // set bit 0, 2
11483 }
11484
developera7149722023-01-11 11:36:21 +080011485 new_vendor_patch = check_is_hemu_vendor_new_patch();
11486 if (new_vendor_patch)
11487 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11488 else
11489 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11490
11491 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011492 sprintf(buf, "%u", set_mu_type);
11493 params.value = buf;
11494 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11495 wifi_hostapdWrite(config_file, &params, 1);
11496 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011497 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011498
11499 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11500 return RETURN_OK;
11501}
11502
11503INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11504{
11505 struct params params={0};
11506 char config_file[64] = {0};
11507 char buf[64] = {0};
11508 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011509 bool new_vendor_patch = FALSE;
11510 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011511
11512 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11513
11514 if (mu_type == NULL)
11515 return RETURN_ERR;
11516
developera7149722023-01-11 11:36:21 +080011517 new_vendor_patch = check_is_hemu_vendor_new_patch();
11518
11519 if (new_vendor_patch)
11520 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11521 else
11522 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11523
developer3e6b1692022-09-30 18:04:05 +080011524 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011525 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011526 get_mu_type = strtol(buf, NULL, 10);
11527
11528 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11529 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11530 else if (get_mu_type & 0x04)
11531 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11532 else if (get_mu_type & 0x01)
11533 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11534 else
11535 *mu_type = WIFI_DL_MU_TYPE_NONE;
11536
11537 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11538 return RETURN_OK;
11539}
11540
11541INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11542{
11543 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11544 struct params params={0};
11545 char config_file[64] = {0};
11546 char buf[64] = {0};
11547 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011548 bool new_vendor_patch = FALSE;
11549 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11551
developera7149722023-01-11 11:36:21 +080011552 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011553
11554 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11555 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11556 set_mu_type &= ~0x0a;
11557 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11558 set_mu_type |= 0x02;
11559 set_mu_type &= ~0x08;
11560 }
11561
developera7149722023-01-11 11:36:21 +080011562 new_vendor_patch = check_is_hemu_vendor_new_patch();
11563
11564 if (new_vendor_patch)
11565 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11566 else
11567 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11568
11569 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011570 sprintf(buf, "%u", set_mu_type);
11571 params.value = buf;
11572 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11573 wifi_hostapdWrite(config_file, &params, 1);
11574 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011575 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011576
11577 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11578 return RETURN_OK;
11579}
11580
11581INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11582{
11583 struct params params={0};
11584 char config_file[64] = {0};
11585 char buf[64] = {0};
11586 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011587 bool new_vendor_patch = FALSE;
11588 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011589
11590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11591
developera7149722023-01-11 11:36:21 +080011592 new_vendor_patch = check_is_hemu_vendor_new_patch();
11593
11594 if (new_vendor_patch)
11595 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11596 else
11597 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11598
developer3e6b1692022-09-30 18:04:05 +080011599 if (mu_type == NULL)
11600 return RETURN_ERR;
11601
11602 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011603 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011604
11605 get_mu_type = strtol(buf, NULL, 10);
11606 if (get_mu_type & 0x02)
11607 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11608 else
11609 *mu_type = WIFI_DL_MU_TYPE_NONE;
11610
11611 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11612 return RETURN_OK;
11613}
11614
11615
developer454b9462022-09-13 15:29:16 +080011616INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11617{
11618 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011619 char buf[256] = {0};
11620 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011621 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011622 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011623 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011624 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011625
11626 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11627
developer254882b2022-09-30 17:12:31 +080011628 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011629 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11630 return RETURN_ERR;
11631 }
developer454b9462022-09-13 15:29:16 +080011632
developer254882b2022-09-30 17:12:31 +080011633 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011634 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011635
developer254882b2022-09-30 17:12:31 +080011636 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11637 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011638 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011639 _syscmd(cmd, buf, sizeof(buf));
11640 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11641 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11642 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011643 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 +080011644 _syscmd(cmd, buf, sizeof(buf));
11645 }
11646 if (band == band_5) {
11647 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11648 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011649 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 +080011650 _syscmd(cmd, buf, sizeof(buf));
11651 }
11652 }
11653 }
11654 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011655
developer254882b2022-09-30 17:12:31 +080011656 if (guard_interval == wifi_guard_interval_400)
11657 strcpy(GI, "0.4");
11658 else if (guard_interval == wifi_guard_interval_800)
11659 strcpy(GI, "0.8");
11660 else if (guard_interval == wifi_guard_interval_1600)
11661 strcpy(GI, "1.6");
11662 else if (guard_interval == wifi_guard_interval_3200)
11663 strcpy(GI, "3.2");
11664 else if (guard_interval == wifi_guard_interval_auto)
11665 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011666 // Record GI for get GI function
11667 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11668 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011669 if (f == NULL)
11670 return RETURN_ERR;
11671 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011672 fclose(f);
11673 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11674 return RETURN_OK;
11675}
11676
11677INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11678{
11679 char buf[32] = {0};
11680 char cmd[64] = {0};
11681
11682 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11683
11684 if (guard_interval == NULL)
11685 return RETURN_ERR;
11686
developer7c4cd202023-03-01 10:56:29 +080011687 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011688 _syscmd(cmd, buf, sizeof(buf));
11689
11690 if (strncmp(buf, "0.4", 3) == 0)
11691 *guard_interval = wifi_guard_interval_400;
11692 else if (strncmp(buf, "0.8", 3) == 0)
11693 *guard_interval = wifi_guard_interval_800;
11694 else if (strncmp(buf, "1.6", 3) == 0)
11695 *guard_interval = wifi_guard_interval_1600;
11696 else if (strncmp(buf, "3.2", 3) == 0)
11697 *guard_interval = wifi_guard_interval_3200;
11698 else
11699 *guard_interval = wifi_guard_interval_auto;
11700
11701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11702 return RETURN_OK;
11703}
11704
developer3cc61d12022-09-13 16:36:05 +080011705INT wifi_setBSSColor(INT radio_index, UCHAR color)
11706{
11707 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11708 struct params params = {0};
11709 char config_file[128] = {0};
11710 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011711 UCHAR *color_list;
11712 int color_num = 0;
11713 int maxNumberColors = 64;
11714 BOOL color_is_aval = FALSE;
11715
developerbf0b9dc2023-07-06 14:30:54 +080011716 if (color > 63 || color == 0)
developer2acb9632023-03-14 14:58:31 +080011717 return RETURN_ERR;
11718
developer517f3be2023-05-08 10:02:39 +080011719 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11720 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK) {
11721 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011722 return RETURN_ERR;
developer517f3be2023-05-08 10:02:39 +080011723 }
developer2acb9632023-03-14 14:58:31 +080011724
11725 for (int i = 0; i < color_num; i++) {
11726 if (color_list[i] == color) {
11727 color_is_aval = TRUE;
11728 break;
11729 }
11730 }
11731 if (color_is_aval == FALSE) {
developer517f3be2023-05-08 10:02:39 +080011732 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011733 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11734 return RETURN_ERR;
11735 }
developer3cc61d12022-09-13 16:36:05 +080011736
11737 params.name = "he_bss_color";
11738 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11739 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011740 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011741 wifi_hostapdWrite(config_file, &params, 1);
11742 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011743 wifi_reloadAp(radio_index);
11744
developer517f3be2023-05-08 10:02:39 +080011745 free(color_list);
developer3cc61d12022-09-13 16:36:05 +080011746 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11747 return RETURN_OK;
11748}
11749
11750INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11751{
developer3cc61d12022-09-13 16:36:05 +080011752 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011753 char cmd[128] = {0};
11754 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011755
developer3cc61d12022-09-13 16:36:05 +080011756 if (NULL == color)
11757 return RETURN_ERR;
11758
developer2acb9632023-03-14 14:58:31 +080011759 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11760 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011761
developer2acb9632023-03-14 14:58:31 +080011762 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11763 _syscmd(cmd, buf, sizeof(buf));
11764 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011765
developer2acb9632023-03-14 14:58:31 +080011766 return RETURN_OK;
11767}
11768
11769INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11770{
11771 char buf[64] = {0};
11772 char cmd[128] = {0};
11773 char interface_name[16] = {0};
11774 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011775
developer2acb9632023-03-14 14:58:31 +080011776 if (NULL == colorList || NULL == numColorReturned)
11777 return RETURN_ERR;
11778
11779 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11780 return RETURN_ERR;
11781
11782 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11783 _syscmd(cmd, buf, sizeof(buf));
11784 color_bitmap = strtoull(buf, NULL, 16);
11785
11786 *numColorReturned = 0;
11787 for (int i = 0; i < maxNumberColors; i++) {
11788 if (color_bitmap & 1) {
11789 colorList[*numColorReturned] = i;
11790 (*numColorReturned) += 1;
11791 }
11792 color_bitmap >>= 1;
11793 }
developer3cc61d12022-09-13 16:36:05 +080011794 return RETURN_OK;
11795}
11796
developer06a01d92022-09-07 16:32:39 +080011797/* multi-psk support */
11798INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11799{
11800 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011801 char interface_name[16] = {0};
11802
developerac6f1142022-12-20 19:26:35 +080011803 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011804 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011805
developerd946fd62022-12-08 18:03:28 +080011806 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11807 interface_name,
developer06a01d92022-09-07 16:32:39 +080011808 mac[0],
11809 mac[1],
11810 mac[2],
11811 mac[3],
11812 mac[4],
11813 mac[5]
11814 );
11815 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11816 _syscmd(cmd, key->wifi_keyId, 64);
11817
11818
11819 return RETURN_OK;
11820}
11821
11822INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11823{
developerd946fd62022-12-08 18:03:28 +080011824 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011825 FILE *fd = NULL;
11826 char fname[100];
11827 char cmd[128] = {0};
11828 char out[64] = {0};
11829 wifi_key_multi_psk_t * key = NULL;
11830 if(keysNumber < 0)
11831 return RETURN_ERR;
11832
developer431128d2022-12-16 15:30:41 +080011833 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011834 fd = fopen(fname, "w");
11835 if (!fd) {
11836 return RETURN_ERR;
11837 }
11838 key= (wifi_key_multi_psk_t *) keys;
11839 for(int i=0; i<keysNumber; ++i, key++) {
11840 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11841 }
11842 fclose(fd);
11843
11844 //reload file
developerac6f1142022-12-20 19:26:35 +080011845 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011846 return RETURN_ERR;
11847 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011848 _syscmd(cmd, out, 64);
11849 return RETURN_OK;
11850}
11851
11852INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11853{
11854 FILE *fd = NULL;
11855 char fname[100];
11856 char * line = NULL;
11857 char * pos = NULL;
11858 size_t len = 0;
11859 ssize_t read = 0;
11860 INT ret = RETURN_OK;
11861 wifi_key_multi_psk_t *keys_it = NULL;
11862
11863 if (keysNumber < 1) {
11864 return RETURN_ERR;
11865 }
11866
developer431128d2022-12-16 15:30:41 +080011867 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011868 fd = fopen(fname, "r");
11869 if (!fd) {
11870 return RETURN_ERR;
11871 }
11872
11873 if (keys == NULL) {
11874 ret = RETURN_ERR;
11875 goto close;
11876 }
11877
11878 keys_it = keys;
11879 while ((read = getline(&line, &len, fd)) != -1) {
11880 //Strip trailing new line if present
11881 if (read > 0 && line[read-1] == '\n') {
11882 line[read-1] = '\0';
11883 }
11884
11885 if(strcmp(line,"keyid=")) {
11886 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11887 if (!(pos = index(line, ' '))) {
11888 ret = RETURN_ERR;
11889 goto close;
11890 }
11891 pos++;
11892 //Here should be 00:00:00:00:00:00
11893 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11894 printf("Not supported MAC: %s\n", pos);
11895 }
11896 if (!(pos = index(pos, ' '))) {
11897 ret = RETURN_ERR;
11898 goto close;
11899 }
11900 pos++;
11901
11902 //The rest is PSK
11903 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11904 keys_it++;
11905
11906 if(--keysNumber <= 0)
11907 break;
11908 }
11909 }
11910
11911close:
11912 free(line);
11913 fclose(fd);
11914 return ret;
11915}
11916/* end of multi-psk support */
11917
11918INT wifi_setNeighborReports(UINT apIndex,
11919 UINT numNeighborReports,
11920 wifi_NeighborReport_t *neighborReports)
11921{
11922 char cmd[256] = { 0 };
11923 char hex_bssid[13] = { 0 };
11924 char bssid[18] = { 0 };
11925 char nr[256] = { 0 };
11926 char ssid[256];
11927 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011928 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011929 INT ret;
11930
11931 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011932 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011933 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011934 return RETURN_ERR;
11935 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 +080011936 system(cmd);
11937
11938 for(unsigned int i = 0; i < numNeighborReports; i++)
11939 {
11940 memset(ssid, 0, sizeof(ssid));
11941 ret = wifi_getSSIDName(apIndex, ssid);
11942 if (ret != RETURN_OK)
11943 return RETURN_ERR;
11944
11945 memset(hex_ssid, 0, sizeof(hex_ssid));
11946 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11947 sprintf(hex_ssid + k,"%02x", ssid[j]);
11948
11949 snprintf(hex_bssid, sizeof(hex_bssid),
11950 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11951 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11952 snprintf(bssid, sizeof(bssid),
11953 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11954 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11955
11956 snprintf(nr, sizeof(nr),
11957 "%s" // bssid
11958 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11959 "%02hhx" // operclass
11960 "%02hhx" // channel
11961 "%02hhx", // phy_mode
11962 hex_bssid,
11963 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11964 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11965 neighborReports[i].opClass,
11966 neighborReports[i].channel,
11967 neighborReports[i].phyTable);
11968
11969 snprintf(cmd, sizeof(cmd),
11970 "hostapd_cli set_neighbor "
11971 "%s " // bssid
11972 "ssid=%s " // ssid
11973 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011974 "-i %s",
11975 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011976
11977 if (WEXITSTATUS(system(cmd)) != 0)
11978 {
11979 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11980 }
11981 }
11982
11983 return RETURN_OK;
11984}
11985
11986INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11987{
11988 return RETURN_OK;
11989}
11990
11991#ifdef _WIFI_HAL_TEST_
11992int main(int argc,char **argv)
11993{
11994 int index;
11995 INT ret=0;
11996 char buf[1024]="";
11997
11998 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11999 if(argc<3)
12000 {
12001 if(argc==2)
12002 {
12003 if(!strcmp(argv[1], "init"))
12004 return wifi_init();
12005 if(!strcmp(argv[1], "reset"))
12006 return wifi_reset();
12007 if(!strcmp(argv[1], "wifi_getHalVersion"))
12008 {
12009 char buffer[64];
12010 if(wifi_getHalVersion(buffer)==RETURN_OK)
12011 printf("Version: %s\n", buffer);
12012 else
12013 printf("Error in wifi_getHalVersion\n");
12014 return RETURN_OK;
12015 }
12016 }
12017 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
12018 exit(-1);
12019 }
12020
12021 index = atoi(argv[2]);
12022 if(strstr(argv[1], "wifi_getApName")!=NULL)
12023 {
12024 wifi_getApName(index,buf);
12025 printf("Ap name is %s \n",buf);
12026 return 0;
12027 }
12028 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
12029 {
12030 BOOL b = FALSE;
12031 BOOL *output_bool = &b;
12032 wifi_getRadioAutoChannelEnable(index,output_bool);
12033 printf("Channel enabled = %d \n",b);
12034 return 0;
12035 }
12036 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
12037 {
12038 wifi_getApWpaEncryptionMode(index,buf);
12039 printf("encryption enabled = %s\n",buf);
12040 return 0;
12041 }
12042 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
12043 {
12044 BOOL b = FALSE;
12045 BOOL *output_bool = &b;
12046 wifi_getApSsidAdvertisementEnable(index,output_bool);
12047 printf("advertisment enabled = %d\n",b);
12048 return 0;
12049 }
12050 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
12051 {
12052 if(argc <= 3 )
12053 {
12054 printf("Insufficient arguments \n");
12055 exit(-1);
12056 }
12057
12058 char sta[20] = {'\0'};
12059 ULLONG handle= 0;
12060 strcpy(sta,argv[3]);
12061 mac_address_t st;
12062 mac_addr_aton(st,sta);
12063
12064 wifi_associated_dev_tid_stats_t tid_stats;
12065 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
12066 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
12067 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);
12068 }
12069
12070 if(strstr(argv[1], "getApEnable")!=NULL) {
12071 BOOL enable;
12072 ret=wifi_getApEnable(index, &enable);
12073 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12074 }
12075 else if(strstr(argv[1], "setApEnable")!=NULL) {
12076 BOOL enable = atoi(argv[3]);
12077 ret=wifi_setApEnable(index, enable);
12078 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12079 }
12080 else if(strstr(argv[1], "getApStatus")!=NULL) {
12081 char status[64];
12082 ret=wifi_getApStatus(index, status);
12083 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
12084 }
12085 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
12086 {
12087 wifi_getSSIDNameStatus(index,buf);
12088 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
12089 return 0;
12090 }
12091 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
12092 wifi_ssidTrafficStats2_t stats={0};
12093 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
12094 printf("%s %d: returns %d\n", argv[1], index, ret);
12095 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
12096 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
12097 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
12098 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
12099 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
12100 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
12101 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
12102 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
12103 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
12104 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
12105 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
12106 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
12107 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
12108 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
12109 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
12110 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
12111 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
12112 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
12113 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
12114 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
12115 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
12116 }
12117 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
12118 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
12119 UINT array_size=0;
12120 UINT i=0;
12121 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
12122 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12123 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
12124 printf(" neighbor %d:\n", i);
12125 printf(" ap_SSID =%s\n", pt->ap_SSID);
12126 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
12127 printf(" ap_Mode =%s\n", pt->ap_Mode);
12128 printf(" ap_Channel =%d\n", pt->ap_Channel);
12129 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
12130 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12131 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
12132 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
12133 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
12134 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
12135 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12136 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
12137 printf(" ap_Noise =%d\n", pt->ap_Noise);
12138 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
12139 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
12140 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
12141 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
12142 }
12143 if(neighbor_ap_array)
12144 free(neighbor_ap_array); //make sure to free the list
12145 }
12146 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
12147 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
12148 UINT array_size=0;
12149 UINT i=0;
12150 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
12151 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
12152 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
12153 printf(" associated_dev %d:\n", i);
12154 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
12155 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
12156 printf(" cli_SNR =%d\n", pt->cli_SNR);
12157 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
12158 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
12159 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
12160 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
12161 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
12162 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
12163 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
12164 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
12165 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
12166 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
12167 }
12168 if(associated_dev_array)
12169 free(associated_dev_array); //make sure to free the list
12170 }
12171
12172 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
12173 {
12174#define MAX_ARRAY_SIZE 64
12175 int i, array_size;
12176 char *p, *ch_str;
12177 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
12178
12179 if(argc != 5)
12180 {
12181 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
12182 exit(-1);
12183 }
12184 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
12185
12186 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
12187 {
12188 strtok_r(ch_str, ",", &p);
12189 input_output_channelStats_array[i].ch_number = atoi(ch_str);
12190 }
12191 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
12192 if(!array_size)
12193 array_size=1;//Need to print current channel statistics
12194 for(i=0; i<array_size; i++)
12195 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12196 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12197 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12198 input_output_channelStats_array[i].ch_number,\
12199 input_output_channelStats_array[i].ch_noise,\
12200 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12201 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12202 input_output_channelStats_array[i].ch_utilization_busy,\
12203 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12204 input_output_channelStats_array[i].ch_utilization_total);
12205 }
12206
12207 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12208 {
12209 if(argc <= 3 )
12210 {
12211 printf("Insufficient arguments \n");
12212 exit(-1);
12213 }
12214 char mac_addr[20] = {'\0'};
12215 wifi_device_t output_struct;
12216 int dev_index = atoi(argv[3]);
12217
12218 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12219 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12220 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);
12221 }
12222
12223 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12224 {
12225 if (argc <= 3)
12226 {
12227 printf("Insufficient arguments\n");
12228 exit(-1);
12229 }
12230 char args[256];
12231 wifi_NeighborReport_t *neighborReports;
12232
12233 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12234 if (!neighborReports)
12235 {
12236 printf("Failed to allocate memory");
12237 exit(-1);
12238 }
12239
12240 for (int i = 3; i < argc; ++i)
12241 {
12242 char *val;
12243 int j = 0;
12244 memset(args, 0, sizeof(args));
12245 strncpy(args, argv[i], sizeof(args));
12246 val = strtok(args, ";");
12247 while (val != NULL)
12248 {
12249 if (j == 0)
12250 {
12251 mac_addr_aton(neighborReports[i - 3].bssid, val);
12252 } else if (j == 1)
12253 {
12254 neighborReports[i - 3].info = strtol(val, NULL, 16);
12255 } else if (j == 2)
12256 {
12257 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12258 } else if (j == 3)
12259 {
12260 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12261 } else if (j == 4)
12262 {
12263 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12264 } else {
12265 printf("Insufficient arguments]n\n");
12266 exit(-1);
12267 }
12268 val = strtok(NULL, ";");
12269 j++;
12270 }
12271 }
12272
12273 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12274 if (ret != RETURN_OK)
12275 {
12276 printf("wifi_setNeighborReports ret = %d", ret);
12277 exit(-1);
12278 }
12279 }
12280 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12281 {
12282 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12283 printf("%s.\n", buf);
12284 else
12285 printf("Error returned\n");
12286 }
12287 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12288 {
12289 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12290 printf("%s.\n", buf);
12291 else
12292 printf("Error returned\n");
12293 }
12294 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12295 {
12296 if (argc <= 2)
12297 {
12298 printf("Insufficient arguments\n");
12299 exit(-1);
12300 }
12301 char buf[64]= {'\0'};
12302 wifi_getRadioOperatingChannelBandwidth(index,buf);
12303 printf("Current bandwidth is %s \n",buf);
12304 return 0;
12305 }
12306 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12307 {
12308 if (argc <= 5)
12309 {
12310 printf("Insufficient arguments\n");
12311 exit(-1);
12312 }
12313 UINT channel = atoi(argv[3]);
12314 UINT width = atoi(argv[4]);
12315 UINT beacon = atoi(argv[5]);
12316 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12317 printf("Result = %d", ret);
12318 }
12319
12320 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12321 return 0;
12322}
12323
12324#endif
12325
12326#ifdef WIFI_HAL_VERSION_3
12327
developer1e5aa162022-09-13 16:06:24 +080012328INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12329{
12330 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12331 if (bitMap & WIFI_BITRATE_1MBPS)
12332 strcat(BasicRate, "1,");
12333 if (bitMap & WIFI_BITRATE_2MBPS)
12334 strcat(BasicRate, "2,");
12335 if (bitMap & WIFI_BITRATE_5_5MBPS)
12336 strcat(BasicRate, "5.5,");
12337 if (bitMap & WIFI_BITRATE_6MBPS)
12338 strcat(BasicRate, "6,");
12339 if (bitMap & WIFI_BITRATE_9MBPS)
12340 strcat(BasicRate, "9,");
12341 if (bitMap & WIFI_BITRATE_11MBPS)
12342 strcat(BasicRate, "11,");
12343 if (bitMap & WIFI_BITRATE_12MBPS)
12344 strcat(BasicRate, "12,");
12345 if (bitMap & WIFI_BITRATE_18MBPS)
12346 strcat(BasicRate, "18,");
12347 if (bitMap & WIFI_BITRATE_24MBPS)
12348 strcat(BasicRate, "24,");
12349 if (bitMap & WIFI_BITRATE_36MBPS)
12350 strcat(BasicRate, "36,");
12351 if (bitMap & WIFI_BITRATE_48MBPS)
12352 strcat(BasicRate, "48,");
12353 if (bitMap & WIFI_BITRATE_54MBPS)
12354 strcat(BasicRate, "54,");
12355 if (strlen(BasicRate) != 0) // remove last comma
12356 BasicRate[strlen(BasicRate) - 1] = '\0';
12357 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12358 return RETURN_OK;
12359}
12360
12361INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12362{
12363 UINT BitMap = 0;
12364 char *rate;
12365
12366 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12367 rate = strtok(BasicRatesList, ",");
12368 while(rate != NULL)
12369 {
12370 if (strcmp(rate, "1") == 0)
12371 BitMap |= WIFI_BITRATE_1MBPS;
12372 else if (strcmp(rate, "2") == 0)
12373 BitMap |= WIFI_BITRATE_2MBPS;
12374 else if (strcmp(rate, "5.5") == 0)
12375 BitMap |= WIFI_BITRATE_5_5MBPS;
12376 else if (strcmp(rate, "6") == 0)
12377 BitMap |= WIFI_BITRATE_6MBPS;
12378 else if (strcmp(rate, "9") == 0)
12379 BitMap |= WIFI_BITRATE_9MBPS;
12380 else if (strcmp(rate, "11") == 0)
12381 BitMap |= WIFI_BITRATE_11MBPS;
12382 else if (strcmp(rate, "12") == 0)
12383 BitMap |= WIFI_BITRATE_12MBPS;
12384 else if (strcmp(rate, "18") == 0)
12385 BitMap |= WIFI_BITRATE_18MBPS;
12386 else if (strcmp(rate, "24") == 0)
12387 BitMap |= WIFI_BITRATE_24MBPS;
12388 else if (strcmp(rate, "36") == 0)
12389 BitMap |= WIFI_BITRATE_36MBPS;
12390 else if (strcmp(rate, "48") == 0)
12391 BitMap |= WIFI_BITRATE_48MBPS;
12392 else if (strcmp(rate, "54") == 0)
12393 BitMap |= WIFI_BITRATE_54MBPS;
12394 rate = strtok(NULL, ",");
12395 }
12396 *basicRateBitMap = BitMap;
12397 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12398 return RETURN_OK;
12399}
12400
developer7c4cd202023-03-01 10:56:29 +080012401INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12402{
12403 int center_channel = 0;
12404 char central_channel_str[16] = {0};
12405 char config_file[32] = {0};
12406 struct params param = {0};
12407
12408 center_channel = util_unii_6g_centerfreq("HT320", channel);
12409 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12410 if (channel >= 193)
12411 return RETURN_ERR;
12412 if (channel >= 33) {
12413 if (channel > center_channel)
12414 center_channel += 32;
12415 else
12416 center_channel -= 32;
12417 }
12418 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12419 if (channel <= 29)
12420 return RETURN_ERR;
12421 }
12422 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12423 param.name = "eht_oper_centr_freq_seg0_idx";
12424 param.value = central_channel_str;
12425 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12426 wifi_hostapdWrite(config_file, &param, 1);
12427
12428 return RETURN_OK;
12429}
12430
12431INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12432{
12433 int op_class = 0;
12434 char config_file[32] = {0};
12435 char op_class_str[8] = {0};
12436 struct params param = {0};
12437
12438 if (bandwidth == 20)
12439 op_class = 131;
12440 else if (bandwidth == 40)
12441 op_class = 132;
12442 else if (bandwidth == 80)
12443 op_class = 133;
12444 else if (bandwidth == 160)
12445 op_class = 134;
12446 else if (bandwidth == 320)
12447 op_class = 137;
12448 else
12449 return RETURN_ERR;
12450 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12451 param.name = "op_class";
12452 param.value = op_class_str;
12453 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12454 wifi_hostapdWrite(config_file, &param, 1);
12455 return RETURN_OK;
12456}
12457
12458INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12459{
12460 char config_file[32] = {0};
12461 char buf [16] = {0};
12462
12463 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12464 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12465 return RETURN_ERR; // 6g band should set op_class
12466 *class = (UINT)strtoul(buf, NULL, 10);
12467
12468 return RETURN_OK;
12469}
12470
developer1e5aa162022-09-13 16:06:24 +080012471// 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 +080012472INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12473{
developer1e5aa162022-09-13 16:06:24 +080012474 char buf[128] = {0};
12475 char cmd[128] = {0};
12476 char config_file[64] = {0};
12477 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012478 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012479 wifi_radio_operationParam_t current_param;
12480
12481 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12482
12483 multiple_set = TRUE;
12484 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12485 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12486 return RETURN_ERR;
12487 }
12488 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12489 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12490 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12491 return RETURN_ERR;
12492 }
12493 }
developer5884e982022-10-06 10:52:50 +080012494
12495 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12496 bandwidth = 20;
12497 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12498 bandwidth = 40;
12499 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12500 bandwidth = 80;
12501 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12502 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012503 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12504 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012505 if (operationParam->autoChannelEnabled){
12506 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12507 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12508 return RETURN_ERR;
12509 }
12510 }else{
developer1e5aa162022-09-13 16:06:24 +080012511 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12512 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12513 return RETURN_ERR;
12514 }
12515 }
developer5884e982022-10-06 10:52:50 +080012516
developer7c4cd202023-03-01 10:56:29 +080012517 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12518 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12519 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12520 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12521 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12522 return RETURN_ERR;
12523 }
12524 }
12525
12526 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12527 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12528 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12529 return RETURN_ERR;
12530 }
12531 }
12532
developer1e5aa162022-09-13 16:06:24 +080012533 if (current_param.variant != operationParam->variant) {
12534 // Two different definition bit map, so need to check every bit.
12535 if (operationParam->variant & WIFI_80211_VARIANT_A)
12536 set_mode |= WIFI_MODE_A;
12537 if (operationParam->variant & WIFI_80211_VARIANT_B)
12538 set_mode |= WIFI_MODE_B;
12539 if (operationParam->variant & WIFI_80211_VARIANT_G)
12540 set_mode |= WIFI_MODE_G;
12541 if (operationParam->variant & WIFI_80211_VARIANT_N)
12542 set_mode |= WIFI_MODE_N;
12543 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12544 set_mode |= WIFI_MODE_AC;
12545 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12546 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012547 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12548 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012549 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12550 memset(buf, 0, sizeof(buf));
12551 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12552 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12553 return RETURN_ERR;
12554 }
12555 }
12556 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12557 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12558 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12559 return RETURN_ERR;
12560 }
12561 }
12562 if (current_param.beaconInterval != operationParam->beaconInterval) {
12563 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12564 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12565 return RETURN_ERR;
12566 }
12567 }
12568 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12569 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12570 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12571 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12572 return RETURN_ERR;
12573 }
12574 }
12575 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12576 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12577 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12578 return RETURN_ERR;
12579 }
12580 }
12581 if (current_param.guardInterval != operationParam->guardInterval) {
12582 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12583 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12584 return RETURN_ERR;
12585 }
12586 }
12587 if (current_param.transmitPower != operationParam->transmitPower) {
12588 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12589 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12590 return RETURN_ERR;
12591 }
12592 }
12593 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12594 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12595 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12596 return RETURN_ERR;
12597 }
12598 }
12599 if (current_param.obssCoex != operationParam->obssCoex) {
12600 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12601 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12602 return RETURN_ERR;
12603 }
12604 }
12605 if (current_param.stbcEnable != operationParam->stbcEnable) {
12606 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12607 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12608 return RETURN_ERR;
12609 }
12610 }
developer5735d092023-09-19 20:12:26 +080012611 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12612 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12613 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12614 return RETURN_ERR;
12615 }
12616 }
developer1e5aa162022-09-13 16:06:24 +080012617
12618 // if enable is true, then restart the radio
12619 wifi_setRadioEnable(index, FALSE);
12620 if (operationParam->enable == TRUE)
12621 wifi_setRadioEnable(index, TRUE);
12622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12623
developer06a01d92022-09-07 16:32:39 +080012624 return RETURN_OK;
12625}
12626
12627INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12628{
developer1e5aa162022-09-13 16:06:24 +080012629 char band[64] = {0};
12630 char buf[256] = {0};
12631 char config_file[64] = {0};
12632 char cmd[128] = {0};
12633 int ret = RETURN_ERR;
12634 int mode = 0;
12635 ULONG channel = 0;
12636 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012637
12638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12639 printf("Entering %s index = %d\n", __func__, (int)index);
12640
developer1e5aa162022-09-13 16:06:24 +080012641 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12642 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12643 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012644 {
developer1e5aa162022-09-13 16:06:24 +080012645 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012646 return RETURN_ERR;
12647 }
12648 operationParam->enable = enabled;
12649
12650 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012651 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012652 {
developer1e5aa162022-09-13 16:06:24 +080012653 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012654 return RETURN_ERR;
12655 }
12656
12657 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012658 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012659 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012660 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012661 else if (!strcmp(band, "6GHz"))
12662 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012663 else
12664 {
developer1e5aa162022-09-13 16:06:24 +080012665 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012666 band);
12667 }
12668
developer1e5aa162022-09-13 16:06:24 +080012669 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12670 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12671 operationParam->channel = 0;
12672 operationParam->autoChannelEnabled = TRUE;
12673 } else {
12674 operationParam->channel = strtol(buf, NULL, 10);
12675 operationParam->autoChannelEnabled = FALSE;
12676 }
12677
developer06a01d92022-09-07 16:32:39 +080012678 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012679 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12680 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12681 return RETURN_ERR;
12682 }
developer06a01d92022-09-07 16:32:39 +080012683 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12684 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12685 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012686 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012687 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12688 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012689 else
12690 {
developer1e5aa162022-09-13 16:06:24 +080012691 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12692 return false;
developer06a01d92022-09-07 16:32:39 +080012693 }
12694
developer7c4cd202023-03-01 10:56:29 +080012695 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12696 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12697 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12698 return RETURN_ERR;
12699 }
12700 }
12701
developer1e5aa162022-09-13 16:06:24 +080012702 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12703 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12704 return RETURN_ERR;
12705 }
12706 // Two different definition bit map, so need to check every bit.
12707 if (mode & WIFI_MODE_A)
12708 operationParam->variant |= WIFI_80211_VARIANT_A;
12709 if (mode & WIFI_MODE_B)
12710 operationParam->variant |= WIFI_80211_VARIANT_B;
12711 if (mode & WIFI_MODE_G)
12712 operationParam->variant |= WIFI_80211_VARIANT_G;
12713 if (mode & WIFI_MODE_N)
12714 operationParam->variant |= WIFI_80211_VARIANT_N;
12715 if (mode & WIFI_MODE_AC)
12716 operationParam->variant |= WIFI_80211_VARIANT_AC;
12717 if (mode & WIFI_MODE_AX)
12718 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012719 if (mode & WIFI_MODE_BE)
12720 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012721 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12722 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12723 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012724 }
developer1e5aa162022-09-13 16:06:24 +080012725 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12726 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12727 return RETURN_ERR;
12728 }
12729 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12730 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12731 return RETURN_ERR;
12732 }
developer06a01d92022-09-07 16:32:39 +080012733
developer1e5aa162022-09-13 16:06:24 +080012734 memset(buf, 0, sizeof(buf));
12735 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12736 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12737 return RETURN_ERR;
12738 }
12739 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12740
12741 memset(buf, 0, sizeof(buf));
12742 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12743 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12744 return RETURN_ERR;
12745 }
12746 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12747
12748 memset(buf, 0, sizeof(buf));
12749 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12750 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12751
12752 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12753 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12754 return RETURN_ERR;
12755 }
12756 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12757 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12758 return RETURN_ERR;
12759 }
12760
12761 memset(buf, 0, sizeof(buf));
12762 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12763 if (strcmp(buf, "-1") == 0) {
12764 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12765 operationParam->ctsProtection = FALSE;
12766 } else {
12767 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12768 operationParam->ctsProtection = TRUE;
12769 }
12770
12771 memset(buf, 0, sizeof(buf));
12772 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12773 if (strcmp(buf, "0") == 0)
12774 operationParam->obssCoex = FALSE;
12775 else
12776 operationParam->obssCoex = TRUE;
12777
12778 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12779 _syscmd(cmd, buf, sizeof(buf));
12780 if (strlen(buf) != 0)
12781 operationParam->stbcEnable = TRUE;
12782 else
12783 operationParam->stbcEnable = FALSE;
12784
developer5735d092023-09-19 20:12:26 +080012785 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12786 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12787 return RETURN_ERR;
12788 }
developer1e5aa162022-09-13 16:06:24 +080012789
12790 // Below value is hardcoded
12791
12792 operationParam->numSecondaryChannels = 0;
12793 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12794 operationParam->channelSecondary[i] = 0;
12795 }
12796 operationParam->csa_beacon_count = 15;
12797 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012798
12799 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12800 return RETURN_OK;
12801}
12802
12803static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12804{
developerc086fb72022-10-04 10:18:22 +080012805 int max_radio_num = 0;
12806
12807 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012808 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012809 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12810 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012811 }
12812
developerc086fb72022-10-04 10:18:22 +080012813 return (arrayIndex * max_radio_num) + radioIndex;
12814}
developer06a01d92022-09-07 16:32:39 +080012815
developerc086fb72022-10-04 10:18:22 +080012816wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12817 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12818 return WIFI_BITRATE_1MBPS;
12819 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12820 return WIFI_BITRATE_2MBPS;
12821 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12822 return WIFI_BITRATE_5_5MBPS;
12823 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12824 return WIFI_BITRATE_6MBPS;
12825 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12826 return WIFI_BITRATE_9MBPS;
12827 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12828 return WIFI_BITRATE_11MBPS;
12829 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12830 return WIFI_BITRATE_12MBPS;
12831 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12832 return WIFI_BITRATE_18MBPS;
12833 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12834 return WIFI_BITRATE_24MBPS;
12835 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12836 return WIFI_BITRATE_36MBPS;
12837 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12838 return WIFI_BITRATE_48MBPS;
12839 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12840 return WIFI_BITRATE_54MBPS;
12841 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012842}
12843
developer1d57d002022-10-12 18:03:15 +080012844INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12845{
12846 if (beacon == WIFI_BITRATE_1MBPS)
12847 strcpy(beacon_str, "1Mbps");
12848 else if (beacon == WIFI_BITRATE_2MBPS)
12849 strcpy(beacon_str, "2Mbps");
12850 else if (beacon == WIFI_BITRATE_5_5MBPS)
12851 strcpy(beacon_str, "5.5Mbps");
12852 else if (beacon == WIFI_BITRATE_6MBPS)
12853 strcpy(beacon_str, "6Mbps");
12854 else if (beacon == WIFI_BITRATE_9MBPS)
12855 strcpy(beacon_str, "9Mbps");
12856 else if (beacon == WIFI_BITRATE_11MBPS)
12857 strcpy(beacon_str, "11Mbps");
12858 else if (beacon == WIFI_BITRATE_12MBPS)
12859 strcpy(beacon_str, "12Mbps");
12860 else if (beacon == WIFI_BITRATE_18MBPS)
12861 strcpy(beacon_str, "18Mbps");
12862 else if (beacon == WIFI_BITRATE_24MBPS)
12863 strcpy(beacon_str, "24Mbps");
12864 else if (beacon == WIFI_BITRATE_36MBPS)
12865 strcpy(beacon_str, "36Mbps");
12866 else if (beacon == WIFI_BITRATE_48MBPS)
12867 strcpy(beacon_str, "48Mbps");
12868 else if (beacon == WIFI_BITRATE_54MBPS)
12869 strcpy(beacon_str, "54Mbps");
12870 return RETURN_OK;
12871}
12872
developer74ed4192023-09-21 17:15:17 +080012873void checkVapStatus(int apIndex, bool *enable)
12874{
12875 char if_name[16] = {0};
12876 char cmd[128] = {0};
12877 char buf[128] = {0};
12878
12879 *enable = FALSE;
12880 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12881 return;
12882
12883 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12884 _syscmd(cmd, buf, sizeof(buf));
12885 if (strlen(buf) > 0)
12886 *enable = TRUE;
12887 return;
12888}
12889
developerefb790a2023-12-26 18:58:32 +080012890INT wifi_getVapInfoMisc(int vap_index)
12891{
12892 char config_file[MAX_BUF_SIZE] = {0};
12893
12894 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX,vap_index);
12895 wifi_hostapdRead(config_file,"ssid",vap_info[vap_index].ssid, MAX_BUF_SIZE);
12896 wifi_hostapdRead(config_file,"wpa", vap_info[vap_index].wpa, MAX_BUF_SIZE);
12897 wifi_hostapdRead(config_file,"wpa_key_mgmt", vap_info[vap_index].wpa_key_mgmt, MAX_BUF_SIZE);
12898 wifi_hostapdRead(config_file,"wpa_passphrase", vap_info[vap_index].wpa_passphrase, MAX_BUF_SIZE);
12899 wifi_hostapdRead(config_file,"ap_isolate", vap_info[vap_index].ap_isolate, MAX_BUF_SIZE);
12900 wifi_hostapdRead(config_file,"macaddr_acl", vap_info[vap_index].macaddr_acl, MAX_BUF_SIZE);
12901 wifi_hostapdRead(config_file,"bss_transition", vap_info[vap_index].bss_transition, MAX_BUF_SIZE);
12902 wifi_hostapdRead(config_file,"ignore_broadcast_ssid", vap_info[vap_index].ignore_broadcast_ssid, MAX_BUF_SIZE);
12903 wifi_hostapdRead(config_file, "max_num_sta", vap_info[vap_index].max_sta, MAX_BUF_SIZE);
12904 return RETURN_OK;
12905}
12906
12907int wifi_Syncthread(void *arg)
12908{
12909 int radio_idx = 0, i = 0;
12910 int vap_index = 0;
developera2af46a2024-01-04 19:11:23 +080012911 int max_radio = 0;
developerefb790a2023-12-26 18:58:32 +080012912
developera2af46a2024-01-04 19:11:23 +080012913 wifi_getMaxRadioNumber(&max_radio);
developerefb790a2023-12-26 18:58:32 +080012914 while (1)
12915 {
12916 sleep(5);
developera2af46a2024-01-04 19:11:23 +080012917 for (radio_idx = 0; radio_idx < max_radio; radio_idx++)
developerefb790a2023-12-26 18:58:32 +080012918 {
12919 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
12920 {
12921 vap_index = array_index_to_vap_index(radio_idx, i);
12922 if (vap_index >= 0)
12923 wifi_getVapInfoMisc(vap_index);
12924 }
12925 }
12926 syn_flag = 1;
12927 }
12928 return 0;
12929}
12930
developer06a01d92022-09-07 16:32:39 +080012931INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12932{
developerc086fb72022-10-04 10:18:22 +080012933 INT mode = 0;
12934 INT ret = -1;
12935 INT output = 0;
12936 int i = 0;
12937 int vap_index = 0;
12938 BOOL enabled = FALSE;
12939 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012940 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012941
developer06a01d92022-09-07 16:32:39 +080012942
12943 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12944 printf("Entering %s index = %d\n", __func__, (int)index);
12945
developera77d84b2023-02-22 16:10:50 +080012946 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012947 {
developerc086fb72022-10-04 10:18:22 +080012948 map->vap_array[i].radio_index = index;
12949
developer06a01d92022-09-07 16:32:39 +080012950 vap_index = array_index_to_vap_index(index, i);
12951 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012952 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012953
developerc086fb72022-10-04 10:18:22 +080012954 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012955
12956 map->vap_array[i].vap_index = vap_index;
12957
12958 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012959 ret = wifi_getApName(vap_index, buf);
12960 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012961 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12962
developerc086fb72022-10-04 10:18:22 +080012963 return RETURN_ERR;
12964 }
12965 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12966
12967 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012968 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012969 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012970 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012971 return RETURN_ERR;
12972 }
12973 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 +080012974
developer74ed4192023-09-21 17:15:17 +080012975 checkVapStatus(vap_index, &enabled);
developer06a01d92022-09-07 16:32:39 +080012976 map->vap_array[i].u.bss_info.enabled = enabled;
12977
developerc086fb72022-10-04 10:18:22 +080012978 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12979 if (ret != RETURN_OK) {
12980 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12981 return RETURN_ERR;
12982 }
developer06a01d92022-09-07 16:32:39 +080012983 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012984
12985 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12986 if (ret != RETURN_OK) {
12987 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12988 return RETURN_ERR;
12989 }
12990 map->vap_array[i].u.bss_info.isolation = enabled;
12991
12992 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12993 if (ret != RETURN_OK) {
12994 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12995 return RETURN_ERR;
12996 }
12997 map->vap_array[i].u.bss_info.bssMaxSta = output;
12998
12999 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
13000 if (ret != RETURN_OK) {
13001 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
13002 return RETURN_ERR;
13003 }
13004 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080013005
developerc086fb72022-10-04 10:18:22 +080013006 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
13007 if (ret != RETURN_OK) {
13008 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
13009 return RETURN_ERR;
13010 }
13011 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080013012
developerc086fb72022-10-04 10:18:22 +080013013 ret = wifi_getApSecurity(vap_index, &security);
13014 if (ret != RETURN_OK) {
13015 printf("%s: wifi_getApSecurity return error\n", __func__);
13016 return RETURN_ERR;
13017 }
13018 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080013019
developerc086fb72022-10-04 10:18:22 +080013020 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
13021 if (ret != RETURN_OK) {
13022 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
13023 return RETURN_ERR;
13024 }
13025 if (mode == 0)
13026 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
13027 else
13028 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
13029 if (mode == 1)
13030 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
13031 else if (mode == 2)
13032 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080013033
developerc086fb72022-10-04 10:18:22 +080013034 ret = wifi_getApWmmEnable(vap_index, &enabled);
13035 if (ret != RETURN_OK) {
13036 printf("%s: wifi_getApWmmEnable return error\n", __func__);
13037 return RETURN_ERR;
13038 }
13039 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080013040
developerc086fb72022-10-04 10:18:22 +080013041 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
13042 if (ret != RETURN_OK) {
13043 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080013044 return RETURN_ERR;
13045 }
developerc086fb72022-10-04 10:18:22 +080013046 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080013047
13048 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080013049 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080013050 if (ret != RETURN_OK) {
13051 printf("%s: wifi_getApBeaconRate return error\n", __func__);
13052 return RETURN_ERR;
13053 }
13054 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080013055
developerc086fb72022-10-04 10:18:22 +080013056 memset(buf, 0, sizeof(buf));
13057 ret = wifi_getBaseBSSID(vap_index, buf);
13058 if (ret != RETURN_OK) {
13059 printf("%s: wifi_getBaseBSSID return error\n", __func__);
13060 return RETURN_ERR;
13061 }
13062 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
13063 &map->vap_array[i].u.bss_info.bssid[0],
13064 &map->vap_array[i].u.bss_info.bssid[1],
13065 &map->vap_array[i].u.bss_info.bssid[2],
13066 &map->vap_array[i].u.bss_info.bssid[3],
13067 &map->vap_array[i].u.bss_info.bssid[4],
13068 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080013069 // 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]);
13070
13071 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
13072 if (ret != RETURN_OK) {
13073 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
13074 return RETURN_ERR;
13075 }
13076 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer613892e2023-09-21 16:33:35 +080013077
13078 ret = wifi_getApWpsEnable(vap_index, &enabled);
13079 if (ret != RETURN_OK) {
13080 fprintf(stderr, "%s: wifi_getApWpsEnable\n", __func__);
13081 return RETURN_ERR;
13082 }
13083
13084 map->vap_array[i].u.bss_info.wps.enable = enabled;
13085
developera77d84b2023-02-22 16:10:50 +080013086 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080013087 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080013088 }
developerefb790a2023-12-26 18:58:32 +080013089
13090 if (!tflag) {
13091 result = pthread_create(&pthread_id, NULL, wifi_Syncthread,NULL);
13092 if (result != 0)
13093 printf("%s %d fail create sync thread\n", __func__, __LINE__);
13094 else
13095 tflag = 1;
13096 }
13097
developer06a01d92022-09-07 16:32:39 +080013098 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13099 return RETURN_OK;
13100}
13101
developer431128d2022-12-16 15:30:41 +080013102
developerd946fd62022-12-08 18:03:28 +080013103static int prepareInterface(UINT apIndex, char *new_interface)
13104{
13105 char cur_interface[16] = {0};
13106 char config_file[128] = {0};
13107 char cmd[128] = {0};
13108 char buf[16] = {0};
13109 int max_radio_num = 0;
13110 int radioIndex = -1;
13111 int phyIndex = -1;
13112
13113 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
13114 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
13115
13116 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
13117 wifi_getMaxRadioNumber(&max_radio_num);
13118 radioIndex = apIndex % max_radio_num;
13119 phyIndex = radio_index_to_phy(radioIndex);
13120 // disable and del old interface, then add new interface
13121 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080013122 if (!(apIndex/max_radio_num)) {
13123 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
13124 _syscmd(cmd, buf, sizeof(buf));
13125 }
developerd946fd62022-12-08 18:03:28 +080013126 }
developer431128d2022-12-16 15:30:41 +080013127 // update the vap status file
13128 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
13129 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080013130 return RETURN_OK;
13131}
13132
developer06a01d92022-09-07 16:32:39 +080013133INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13134{
developerd946fd62022-12-08 18:03:28 +080013135 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013136 unsigned int i;
13137 wifi_vap_info_t *vap_info = NULL;
13138 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080013139 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080013140 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080013141 char buf[256] = {0};
13142 char cmd[128] = {0};
13143 char config_file[64] = {0};
13144 char bssid[32] = {0};
13145 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080013146 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080013147
13148 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13149 printf("Entering %s index = %d\n", __func__, (int)index);
13150 for (i = 0; i < map->num_vaps; i++)
13151 {
developer1d57d002022-10-12 18:03:15 +080013152 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080013153 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080013154
13155 // Check vap status file to enable multiple ap if the system boot.
13156 checkVapStatus(vap_info->vap_index, &enable);
13157 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080013158 continue;
developer06a01d92022-09-07 16:32:39 +080013159
developer1d57d002022-10-12 18:03:15 +080013160 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
13161
developer431128d2022-12-16 15:30:41 +080013162 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
13163 enable = FALSE;
13164
13165 // multi-ap first up need to copy current radio config
13166 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080013167 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
13168 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080013169 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
13170 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
13171 } else {
13172 // Check whether the interface name is valid or this ap change it.
13173 int apIndex = -1;
13174 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
13175 if (apIndex != -1 && apIndex != vap_info->vap_index)
13176 continue;
13177 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080013178 }
developer06a01d92022-09-07 16:32:39 +080013179
developer1d57d002022-10-12 18:03:15 +080013180 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080013181 params[0].name = "interface";
13182 params[0].value = vap_info->vap_name;
13183 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
13184 params[1].name = "bssid";
13185 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080013186 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080013187 params[2].name = "wpa_psk_file";
13188 params[2].value = psk_file;
13189
13190 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
13191 wifi_hostapdWrite(config_file, params, 3);
13192
13193 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
13194 _syscmd(cmd, buf, sizeof(buf));
13195
13196 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
13197 if (ret != RETURN_OK) {
13198 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
13199 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013200 }
developer1d57d002022-10-12 18:03:15 +080013201
13202 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
13203 if (ret != RETURN_OK) {
13204 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
13205 return RETURN_ERR;
13206 }
13207
13208 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
13209 if (ret != RETURN_OK) {
13210 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
13211 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080013212 }
13213
developer1d57d002022-10-12 18:03:15 +080013214 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
13215 if (ret != RETURN_OK) {
13216 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
13217 return RETURN_ERR;
13218 }
developer06a01d92022-09-07 16:32:39 +080013219
developer1d57d002022-10-12 18:03:15 +080013220 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
13221 if (ret != RETURN_OK) {
13222 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
13223 return RETURN_ERR;
13224 }
developer06a01d92022-09-07 16:32:39 +080013225
developer1d57d002022-10-12 18:03:15 +080013226 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
13227 if (ret != RETURN_OK) {
13228 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
13229 return RETURN_ERR;
13230 }
13231
developer804c64f2022-10-19 13:54:40 +080013232 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080013233 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080013234 }else {
13235 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080013236 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080013237 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13238 _syscmd(cmd, buf, sizeof(buf));
13239 }else{
developer1d57d002022-10-12 18:03:15 +080013240 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080013241 }
developer1d57d002022-10-12 18:03:15 +080013242 }
13243
13244 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13245 if (ret != RETURN_OK) {
13246 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13247 return RETURN_ERR;
13248 }
13249
13250 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13251 if (ret != RETURN_OK) {
13252 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13253 return RETURN_ERR;
13254 }
13255
13256 memset(buf, 0, sizeof(buf));
13257 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
13258 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
13259 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13260 if (ret != RETURN_OK) {
13261 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13262 return RETURN_ERR;
13263 }
13264
developer1d57d002022-10-12 18:03:15 +080013265 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13266 if (ret != RETURN_OK) {
13267 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13268 return RETURN_ERR;
13269 }
13270
13271 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13272 if (ret != RETURN_OK) {
13273 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13274 return RETURN_ERR;
13275 }
developer06a01d92022-09-07 16:32:39 +080013276
developer894affa2023-05-10 18:13:19 +080013277 ret = wifi_setApWpsEnable(vap_info->vap_index, vap_info->u.bss_info.wps.enable);
13278 if (ret != RETURN_OK) {
13279 fprintf(stderr, "%s: wifi_setApWpsEnable return error\n", __func__);
13280 return RETURN_ERR;
13281 }
13282
developer2f995fb2023-02-24 10:40:44 +080013283 wifi_setApEnable(vap_info->vap_index, FALSE);
developer74ed4192023-09-21 17:15:17 +080013284 if (vap_info->u.bss_info.enabled == TRUE)
13285 wifi_setApEnable(vap_info->vap_index, TRUE);
13286
developer2f995fb2023-02-24 10:40:44 +080013287 multiple_set = FALSE;
13288
13289 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer900e2b72023-05-23 10:23:48 +080013290 if (vap_info->u.bss_info.wps.enable && vap_info->u.bss_info.wps.methods && WIFI_ONBOARDINGMETHODS_PUSHBUTTON) {
developer894affa2023-05-10 18:13:19 +080013291 // The set wps methods function should check whether wps is configured.
13292 ret = wifi_setApWpsButtonPush(vap_info->vap_index);
13293 if (ret != RETURN_OK) {
13294 fprintf(stderr, "%s: wifi_setApWpsButtonPush return error\n", __func__);
13295 return RETURN_ERR;
13296 }
13297 // wifi_setApWpsConfigMethodsEnabled only write to config.
13298 ret = wifi_setApWpsConfigMethodsEnabled(vap_info->vap_index, "PushButton");
13299 if (ret != RETURN_OK) {
13300 fprintf(stderr, "%s: wifi_setApWpsConfigMethodsEnabled return error\n", __func__);
13301 return RETURN_ERR;
13302 }
13303 }
developer2f995fb2023-02-24 10:40:44 +080013304
developer894affa2023-05-10 18:13:19 +080013305 // TODO mgmtPowerControl, interworking
developer06a01d92022-09-07 16:32:39 +080013306 }
developerfb09ba62023-06-09 17:03:21 +080013307
13308 // IGMP Snooping enable should be placed after all hostapd_reload.
13309 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13310 if (ret != RETURN_OK) {
13311 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable return error\n", __func__);
13312 return RETURN_ERR;
13313 }
13314
developer06a01d92022-09-07 16:32:39 +080013315 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13316 return RETURN_OK;
13317}
13318
13319int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13320{
13321 char *token, *next;
13322 const char s[2] = ",";
13323 int count =0;
13324
13325 /* get the first token */
13326 token = strtok_r(pchannels, s, &next);
13327
13328 /* walk through other tokens */
13329 while( token != NULL && count < MAX_CHANNELS) {
13330 chlistptr->channels_list[count++] = atoi(token);
13331 token = strtok_r(NULL, s, &next);
13332 }
13333
13334 return count;
13335}
13336
13337static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13338{
13339 INT status;
13340 wifi_channels_list_t *chlistp;
13341 CHAR output_string[64];
13342 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013343 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013344 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013345
13346 if(rcap == NULL)
13347 {
13348 return RETURN_ERR;
13349 }
13350
13351 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013352 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013353
developer1e5aa162022-09-13 16:06:24 +080013354 if (band == band_2_4)
13355 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13356 else if (band == band_5)
13357 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13358 else if (band == band_6)
13359 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013360
13361 chlistp = &(rcap->channel_list[0]);
13362 memset(pchannels, 0, sizeof(pchannels));
13363
13364 /* possible number of radio channels */
13365 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13366 {
13367 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13368 }
13369 /* Number of channels and list*/
13370 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13371
13372 /* autoChannelSupported */
13373 /* always ON with wifi_getRadioAutoChannelSupported */
13374 rcap->autoChannelSupported = TRUE;
13375
13376 /* DCSSupported */
13377 /* always ON with wifi_getRadioDCSSupported */
13378 rcap->DCSSupported = TRUE;
13379
13380 /* zeroDFSSupported - TBD */
13381 rcap->zeroDFSSupported = FALSE;
13382
13383 /* Supported Country List*/
13384 memset(output_string, 0, sizeof(output_string));
13385 status = wifi_getRadioCountryCode(radioIndex, output_string);
13386 if( status != 0 ) {
13387 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13388 return RETURN_ERR;
13389 } else {
13390 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13391 }
13392 if(!strcmp(output_string,"US")){
13393 rcap->countrySupported[0] = wifi_countrycode_US;
13394 rcap->countrySupported[1] = wifi_countrycode_CA;
13395 } else if (!strcmp(output_string,"CA")) {
13396 rcap->countrySupported[0] = wifi_countrycode_CA;
13397 rcap->countrySupported[1] = wifi_countrycode_US;
13398 } else {
13399 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13400 }
13401
13402 rcap->numcountrySupported = 2;
13403
13404 /* csi */
13405 rcap->csi.maxDevices = 8;
13406 rcap->csi.soudingFrameSupported = TRUE;
13407
developer7930d352022-12-21 17:55:42 +080013408 wifi_GetInterfaceName(radioIndex, interface_name);
13409 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013410
13411 /* channelWidth - all supported bandwidths */
13412 int i=0;
13413 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013414
13415 /* mode - all supported variants */
13416 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13417 wifi_getRadioSupportedStandards(radioIndex, output_string);
13418
developer06a01d92022-09-07 16:32:39 +080013419 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13420 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13421 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013422 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013423
developer7c4cd202023-03-01 10:56:29 +080013424 if (strstr(output_string, "n") != NULL)
13425 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13426 if (strstr(output_string, "ax") != NULL)
13427 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13428 if (strstr(output_string, "be") != NULL)
13429 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13430 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013431 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13432 WIFI_CHANNELBANDWIDTH_40MHZ |
13433 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013434 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013435
developer7c4cd202023-03-01 10:56:29 +080013436 if (strstr(output_string, "n") != NULL)
13437 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13438 if (strstr(output_string, "ac") != NULL)
13439 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13440 if (strstr(output_string, "ax") != NULL)
13441 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13442 if (strstr(output_string, "be") != NULL)
13443 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13444 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13445 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13446 WIFI_CHANNELBANDWIDTH_40MHZ |
13447 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013448 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013449
13450 if (strstr(output_string, "be") != NULL) {
13451 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13452 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13453 }
developer06a01d92022-09-07 16:32:39 +080013454 }
developer7c4cd202023-03-01 10:56:29 +080013455
developer06a01d92022-09-07 16:32:39 +080013456 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13457 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13458
13459 /* supportedBitRate - all supported bitrates */
13460 rcap->supportedBitRate[i] = 0;
13461 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13462 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13463 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13464 }
developer1e5aa162022-09-13 16:06:24 +080013465 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013466 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13467 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13468 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13469 }
13470
13471
13472 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13473 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13474 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13475 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13476 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13477 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13478 rcap->cipherSupported = 0;
13479 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13480 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13481
13482 return RETURN_OK;
13483}
13484
13485INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13486{
developer30423732022-12-01 16:17:49 +080013487 INT status = 0, radioIndex = 0;
13488 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013489 int iter = 0;
developer30423732022-12-01 16:17:49 +080013490 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013491 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013492 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013493
13494 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13495
13496 memset(cap, 0, sizeof(wifi_hal_capability_t));
13497
13498 /* version */
13499 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13500 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13501
13502 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013503 wifi_getMaxRadioNumber(&max_num_radios);
13504 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013505
13506 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13507 {
13508 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13509 if (status != 0) {
13510 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13511 return RETURN_ERR;
13512 }
13513
13514 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13515 {
developer804c64f2022-10-19 13:54:40 +080013516 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013517 {
13518 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13519 return RETURN_ERR;
13520 }
13521 iface_info = &cap->wifi_prop.interface_map[iter];
13522 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13523 iface_info->rdk_radio_index = radioIndex;
13524 memset(output, 0, sizeof(output));
13525 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13526 {
13527 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13528 }
13529 // TODO: bridge name
13530 // TODO: vlan id
13531 // TODO: primary
13532 iface_info->index = array_index_to_vap_index(radioIndex, j);
13533 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013534 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013535 {
13536 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13537 }
13538 iter++;
13539 }
13540 }
13541
13542 cap->BandSteeringSupported = FALSE;
13543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13544 return RETURN_OK;
13545}
13546
developer9df4e652022-10-11 11:27:38 +080013547INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13548{
13549 struct params h_config={0};
13550 char config_file[64] = {0};
13551
13552 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13553
13554 h_config.name = "okc";
13555 h_config.value = okc_enable?"1":"0";
13556
13557 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13558 wifi_hostapdWrite(config_file, &h_config, 1);
13559 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13560
13561 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13562 return RETURN_OK;
13563}
13564
13565INT wifi_setSAEMFP(int ap_index, BOOL enable)
13566{
13567 struct params h_config={0};
13568 char config_file[64] = {0};
13569 char buf[128] = {0};
13570
13571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13572
13573 h_config.name = "sae_require_mfp";
13574 h_config.value = 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_setSAEpwe(int ap_index, int sae_pwe)
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_pwe";
13593 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13594 h_config.value = buf;
13595
13596 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13597 wifi_hostapdWrite(config_file, &h_config, 1);
13598 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13599
13600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13601 return RETURN_OK;
13602}
13603
13604INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13605{
13606 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13607 struct params h_config={0};
13608 char config_file[64] = {0};
13609
13610 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13611
13612 h_config.name = "wpa_disable_eapol_key_retries";
13613 h_config.value = disable_EAPOL_retries?"1":"0";
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
developer06a01d92022-09-07 16:32:39 +080013623INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13624{
developer587c1b62022-09-27 15:58:59 +080013625 char buf[128] = {0};
13626 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013627 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013628 char password[64] = {0};
13629 char mfp[32] = {0};
13630 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013631 BOOL okc_enable = FALSE;
13632 BOOL sae_MFP = FALSE;
13633 BOOL disable_EAPOL_retries = TRUE;
13634 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013635 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013636 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013637
13638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13639
13640 multiple_set = TRUE;
13641 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13642 if (security->mode == wifi_security_mode_none) {
13643 strcpy(wpa_mode, "None");
13644 } else if (security->mode == wifi_security_mode_wpa_personal)
13645 strcpy(wpa_mode, "WPA-Personal");
13646 else if (security->mode == wifi_security_mode_wpa2_personal)
13647 strcpy(wpa_mode, "WPA2-Personal");
13648 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13649 strcpy(wpa_mode, "WPA-WPA2-Personal");
13650 else if (security->mode == wifi_security_mode_wpa_enterprise)
13651 strcpy(wpa_mode, "WPA-Enterprise");
13652 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13653 strcpy(wpa_mode, "WPA2-Enterprise");
13654 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13655 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013656 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013657 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013658 okc_enable = TRUE;
13659 sae_MFP = TRUE;
13660 sae_pwe = 2;
13661 disable_EAPOL_retries = FALSE;
13662 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013663 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013664 okc_enable = TRUE;
13665 sae_MFP = TRUE;
13666 sae_pwe = 2;
13667 disable_EAPOL_retries = FALSE;
13668 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013669 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013670 sae_MFP = TRUE;
13671 sae_pwe = 2;
13672 disable_EAPOL_retries = FALSE;
developerae432c62023-04-24 11:07:20 +080013673 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer5c9fee82023-01-13 14:44:16 +080013674 strcpy(wpa_mode, "OWE");
13675 sae_MFP = TRUE;
13676 sae_pwe = 2;
13677 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013678 }
13679
13680 band = wifi_index_to_band(ap_index);
13681 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13682 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13683 return RETURN_ERR;
13684 }
developer587c1b62022-09-27 15:58:59 +080013685
13686 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013687 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013688 wifi_setSAEMFP(ap_index, sae_MFP);
13689 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013690 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013691
developerae432c62023-04-24 11:07:20 +080013692 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer4b102122023-02-15 10:53:03 +080013693 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) {
13694 int key_len = strlen(security->u.key.key);
13695 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13696 if (key_len == 64) { // set wpa_psk
13697 strncpy(password, security->u.key.key, 64); // 64 characters
13698 password[64] = '\0';
13699 wifi_setApSecurityPreSharedKey(ap_index, password);
13700 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13701 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13702 strncpy(password, security->u.key.key, 63);
13703 password[63] = '\0';
13704 wifi_setApSecurityKeyPassphrase(ap_index, password);
13705 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13706 } else
13707 return RETURN_ERR;
13708 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013709 }
13710 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13711 params.name = "sae_password";
13712 params.value = security->u.key.key;
13713 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013714 } else { // remove sae_password
13715 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13716 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013717 }
13718 }
developer587c1b62022-09-27 15:58:59 +080013719
13720 if (security->mode != wifi_security_mode_none) {
13721 memset(&params, 0, sizeof(params));
13722 params.name = "wpa_pairwise";
13723 if (security->encr == wifi_encryption_tkip)
13724 params.value = "TKIP";
13725 else if (security->encr == wifi_encryption_aes)
13726 params.value = "CCMP";
13727 else if (security->encr == wifi_encryption_aes_tkip)
13728 params.value = "TKIP CCMP";
13729 wifi_hostapdWrite(config_file, &params, 1);
13730 }
13731
13732 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013733 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013734 else if (security->mfp == wifi_mfp_cfg_optional)
13735 strcpy(mfp, "Optional");
13736 else if (security->mfp == wifi_mfp_cfg_required)
13737 strcpy(mfp, "Required");
13738 wifi_setApSecurityMFPConfig(ap_index, mfp);
13739
13740 memset(&params, 0, sizeof(params));
13741 params.name = "transition_disable";
13742 if (security->wpa3_transition_disable == TRUE)
13743 params.value = "0x01";
13744 else
13745 params.value = "0x00";
13746 wifi_hostapdWrite(config_file, &params, 1);
13747
13748 memset(&params, 0, sizeof(params));
13749 params.name = "wpa_group_rekey";
13750 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13751 params.value = buf;
13752 wifi_hostapdWrite(config_file, &params, 1);
13753
13754 memset(&params, 0, sizeof(params));
13755 params.name = "wpa_strict_rekey";
13756 params.value = security->strict_rekey?"1":"0";
13757 wifi_hostapdWrite(config_file, &params, 1);
13758
13759 memset(&params, 0, sizeof(params));
13760 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013761 if (security->eapol_key_retries == 0)
13762 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013763 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13764 params.value = buf;
13765 wifi_hostapdWrite(config_file, &params, 1);
13766
13767 memset(&params, 0, sizeof(params));
13768 params.name = "disable_pmksa_caching";
13769 params.value = security->disable_pmksa_caching?"1":"0";
13770 wifi_hostapdWrite(config_file, &params, 1);
13771
developer23e71282023-01-18 10:25:19 +080013772 if (multiple_set == FALSE) {
13773 wifi_setApEnable(ap_index, FALSE);
13774 wifi_setApEnable(ap_index, TRUE);
13775 }
developer587c1b62022-09-27 15:58:59 +080013776
13777 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13778
developer06a01d92022-09-07 16:32:39 +080013779 return RETURN_OK;
13780}
13781
13782INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13783{
developer9df4e652022-10-11 11:27:38 +080013784 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013785 char config_file[128] = {0};
13786 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013787 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013788
13789 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13790 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13791 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13792 security->mode = wifi_security_mode_none;
13793 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013794 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013795 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013796 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013797 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013798 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013799 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013800 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013801 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013802 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013803 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013804 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013805 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013806 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013807 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013808 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013809 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013810 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013811 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013812 else if (!strcmp(buf, "OWE"))
developerae432c62023-04-24 11:07:20 +080013813 security->mode = wifi_security_mode_enhanced_open;
developer587c1b62022-09-27 15:58:59 +080013814 }
13815
13816 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13817 if (security->mode == wifi_security_mode_none)
13818 security->encr = wifi_encryption_none;
13819 else {
13820 if (strcmp(buf, "TKIP") == 0)
13821 security->encr = wifi_encryption_tkip;
13822 else if (strcmp(buf, "CCMP") == 0)
13823 security->encr = wifi_encryption_aes;
13824 else
13825 security->encr = wifi_encryption_aes_tkip;
13826 }
13827
developer9df4e652022-10-11 11:27:38 +080013828 if (security->mode != wifi_encryption_none) {
13829 memset(buf, 0, sizeof(buf));
13830 // wpa3 can use one or both configs as password, so we check sae_password first.
13831 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013832 if (strlen(buf) != 0) {
13833 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13834 security->u.key.type = wifi_security_key_type_sae;
13835 set_sae = TRUE;
13836 strncpy(security->u.key.key, buf, sizeof(buf));
13837 }
13838 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13839 if (strlen(buf) != 0){
13840 if (set_sae == TRUE)
13841 security->u.key.type = wifi_security_key_type_psk_sae;
13842 else if (strlen(buf) == 64)
13843 security->u.key.type = wifi_security_key_type_psk;
13844 else
13845 security->u.key.type = wifi_security_key_type_pass;
13846 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013847 }
developer9df4e652022-10-11 11:27:38 +080013848 security->u.key.key[255] = '\0';
13849 }
13850
developer587c1b62022-09-27 15:58:59 +080013851 memset(buf, 0, sizeof(buf));
13852 wifi_getApSecurityMFPConfig(ap_index, buf);
13853 if (strcmp(buf, "Disabled") == 0)
13854 security->mfp = wifi_mfp_cfg_disabled;
13855 else if (strcmp(buf, "Optional") == 0)
13856 security->mfp = wifi_mfp_cfg_optional;
13857 else if (strcmp(buf, "Required") == 0)
13858 security->mfp = wifi_mfp_cfg_required;
13859
13860 memset(buf, 0, sizeof(buf));
13861 security->wpa3_transition_disable = FALSE;
13862 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13863 disable = strtol(buf, NULL, 16);
13864 if (disable != 0)
13865 security->wpa3_transition_disable = TRUE;
13866
13867 memset(buf, 0, sizeof(buf));
13868 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13869 if (strlen(buf) == 0)
13870 security->rekey_interval = 86400;
13871 else
13872 security->rekey_interval = strtol(buf, NULL, 10);
13873
13874 memset(buf, 0, sizeof(buf));
13875 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13876 if (strlen(buf) == 0)
developer894d8222023-06-15 13:40:44 +080013877 security->strict_rekey = 0;
developer587c1b62022-09-27 15:58:59 +080013878 else
13879 security->strict_rekey = strtol(buf, NULL, 10);
13880
13881 memset(buf, 0, sizeof(buf));
13882 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13883 if (strlen(buf) == 0)
13884 security->eapol_key_retries = 4;
13885 else
13886 security->eapol_key_retries = strtol(buf, NULL, 10);
13887
13888 memset(buf, 0, sizeof(buf));
13889 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13890 if (strlen(buf) == 0)
13891 security->disable_pmksa_caching = FALSE;
13892 else
13893 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13894
13895 /* TODO
13896 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13897 */
13898 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13899 security->eap_identity_req_timeout = 0;
13900 security->eap_identity_req_retries = 0;
13901 security->eap_req_timeout = 0;
13902 security->eap_req_retries = 0;
13903 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013904 return RETURN_OK;
13905}
13906
13907#endif /* WIFI_HAL_VERSION_3 */
13908
13909#ifdef WIFI_HAL_VERSION_3_PHASE2
13910INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13911{
developerd946fd62022-12-08 18:03:28 +080013912 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013913 char cmd[128] = {0};
13914 char buf[128] = {0};
13915 char *mac_addr = NULL;
13916 BOOL status = FALSE;
13917 size_t len = 0;
13918
13919 if(ap_index > MAX_APS)
13920 return RETURN_ERR;
13921
13922 *output_numDevices = 0;
13923 wifi_getApEnable(ap_index, &status);
13924 if (status == FALSE)
13925 return RETURN_OK;
13926
developerac6f1142022-12-20 19:26:35 +080013927 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013928 return RETURN_ERR;
13929 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013930 _syscmd(cmd, buf, sizeof(buf));
13931
13932 mac_addr = strtok(buf, "\n");
13933 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13934 *output_numDevices = i + 1;
13935 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13936 addr_ptr = output_deviceMacAddressArray[i];
13937 mac_addr_aton(addr_ptr, mac_addr);
13938 mac_addr = strtok(NULL, "\n");
13939 }
13940
13941 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013942}
13943#else
13944INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13945{
developerd946fd62022-12-08 18:03:28 +080013946 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013947 char cmd[128];
13948 BOOL status = false;
13949
13950 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13951 return RETURN_ERR;
13952
13953 output_buf[0] = '\0';
13954
13955 wifi_getApEnable(ap_index,&status);
13956 if (!status)
13957 return RETURN_OK;
13958
developerac6f1142022-12-20 19:26:35 +080013959 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013960 return RETURN_ERR;
13961 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013962 _syscmd(cmd, output_buf, output_buf_size);
13963
13964 return RETURN_OK;
13965}
13966#endif
developer2f513ab2022-09-13 14:26:06 +080013967
13968INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13969{
13970 char output[16]={'\0'};
13971 char config_file[MAX_BUF_SIZE] = {0};
13972
13973 if (!enable)
13974 return RETURN_ERR;
13975
13976 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13977 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13978
13979 if (strlen(output) == 0)
13980 *enable = FALSE;
13981 else if (strncmp(output, "1", 1) == 0)
13982 *enable = TRUE;
13983 else
13984 *enable = FALSE;
13985
13986 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13987 return RETURN_OK;
13988}
developer2d9c30f2022-09-13 15:06:14 +080013989
13990INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13991{
developer804c64f2022-10-19 13:54:40 +080013992 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013993 return RETURN_ERR;
13994 *output_enable=TRUE;
13995 return RETURN_OK;
13996}
developerfd7d2892022-09-13 16:44:53 +080013997
13998INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13999{
14000 char cmd[128] = {0};
14001 char buf[128] = {0};
14002 char line[128] = {0};
14003 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080014004 FILE *f = NULL;
14005 int index = 0;
14006 int exp = 0;
14007 int mantissa = 0;
14008 int duration = 0;
14009 int radio_index = 0;
14010 int max_radio_num = 0;
14011 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080014012 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080014013 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14014
14015 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080014016
developerfd7d2892022-09-13 16:44:53 +080014017 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080014018
14019 phyId = radio_index_to_phy(radio_index);
developer439baa32024-05-02 15:54:58 +080014020 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 +080014021 _syscmd(cmd, buf, sizeof(buf));
14022 *numSessionReturned = strtol(buf, NULL, 10) - 1;
14023 if (*numSessionReturned > maxNumberSessions)
14024 *numSessionReturned = maxNumberSessions;
14025 else if (*numSessionReturned < 1) {
14026 *numSessionReturned = 0;
14027 return RETURN_OK;
14028 }
14029
developer439baa32024-05-02 15:54:58 +080014030 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 +080014031 if ((f = popen(cmd, "r")) == NULL) {
14032 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
14033 return RETURN_ERR;
14034 }
14035
14036 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080014037 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080014038 char *tmp = NULL;
14039 strcpy(buf, line);
14040 tmp = strtok(buf, " ");
14041 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
14042 tmp = strtok(NULL, " ");
14043 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
14044 tmp = strtok(NULL, " ");
14045 if (strstr(tmp, "t")) {
14046 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
14047 }
14048 if (strstr(tmp, "a")) {
14049 twtSessions[index].twtParameters.operation.announced = TRUE;
14050 }
14051 tmp = strtok(NULL, " ");
14052 exp = strtol(tmp, NULL, 10);
14053 tmp = strtok(NULL, " ");
14054 mantissa = strtol(tmp, NULL, 10);
14055 tmp = strtok(NULL, " ");
14056 duration = strtol(tmp, NULL, 10);
14057
14058 // only implicit supported
14059 twtSessions[index].twtParameters.operation.implicit = TRUE;
14060 // only individual agreement supported
14061 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
14062
14063 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
14064 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080014065 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080014066 // Overflow handling
14067 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
14068 } else {
14069 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
14070 }
14071 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
14072 index++;
14073 }
14074
14075 pclose(f);
14076 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14077 return RETURN_OK;
14078}