blob: 6103c34a33bea25ecfc92dbc7c0f8eb6a54176e4 [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>
64#define MAC_ALEN 6
65
developer7930d352022-12-21 17:55:42 +080066#define MAX_BUF_SIZE 256
67#define MAX_CMD_SIZE 256
68#define IF_NAME_SIZE 16
developer06a01d92022-09-07 16:32:39 +080069#define CONFIG_PREFIX "/nvram/hostapd"
developer431128d2022-12-16 15:30:41 +080070#define ACL_PREFIX "/nvram/hostapd-acl"
71#define DENY_PREFIX "/nvram/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080072//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
73#define SOCK_PREFIX "/var/run/hostapd/wifi"
developer431128d2022-12-16 15:30:41 +080074#define VAP_STATUS_FILE "/nvram/vap-status"
developera3c68b92022-09-13 15:27:29 +080075#define ESSID_FILE "/tmp/essid"
developer247302b2022-10-06 15:03:00 +080076#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080077#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080078#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080079#define VLAN_FILE "/nvram/hostapd.vlan"
developer431128d2022-12-16 15:30:41 +080080#define PSK_FILE "/nvram/hostapd"
developerf49437e2022-09-29 19:58:21 +080081#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080082#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080083
developer81bf2ed2022-09-13 15:31:14 +080084#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080085
86/*
87 MAX_APS - Number of all AP available in system
88 2x Home AP
89 2x Backhaul AP
90 2x Guest AP
91 2x Secure Onboard AP
92 2x Service AP
93
94*/
developer06a01d92022-09-07 16:32:39 +080095
developer033b37b2022-10-18 11:27:46 +080096
developera77d84b2023-02-22 16:10:50 +080097#define MAX_APS ((MAX_NUM_RADIOS)*(MAX_NUM_VAP_PER_RADIO))
developer06a01d92022-09-07 16:32:39 +080098#ifndef AP_PREFIX
99#define AP_PREFIX "wifi"
100#endif
101
102#ifndef RADIO_PREFIX
103#define RADIO_PREFIX "wlan"
104#endif
105
developer89df4502023-02-16 20:45:02 +0800106#define MAX_ASSOCIATED_STA_NUM 2007 // hostapd default
developer06a01d92022-09-07 16:32:39 +0800107
108//Uncomment to enable debug logs
109//#define WIFI_DEBUG
110
111#ifdef WIFI_DEBUG
112#define wifi_dbg_printf printf
113#define WIFI_ENTRY_EXIT_DEBUG printf
114#else
115#define wifi_dbg_printf(format, args...) printf("")
116#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
117#endif
118
119#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
120#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
121#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
122#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
123#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
124#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
125#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
126#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
127#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
128#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
129
developer4fb0b922022-09-30 14:29:09 +0800130#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800131
132#define BW_FNAME "/nvram/bw_file.txt"
133
134#define PS_MAX_TID 16
135
136static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
137 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
138 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
139 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
140 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
141 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
142 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
143 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
144 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
145 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
147 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
148 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
150 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
152 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
153};
154
155typedef unsigned long long u64;
156
157/* Enum to define WiFi Bands */
158typedef enum
159{
160 band_invalid = -1,
161 band_2_4 = 0,
162 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800163 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800164} wifi_band;
165
developerdb744382022-09-13 15:34:54 +0800166typedef enum {
167 WIFI_MODE_A = 0x01,
168 WIFI_MODE_B = 0x02,
169 WIFI_MODE_G = 0x04,
170 WIFI_MODE_N = 0x08,
171 WIFI_MODE_AC = 0x10,
172 WIFI_MODE_AX = 0x20,
developer7c4cd202023-03-01 10:56:29 +0800173 WIFI_MODE_BE = 0x40,
developerdb744382022-09-13 15:34:54 +0800174} wifi_ieee80211_Mode;
175
developer06a01d92022-09-07 16:32:39 +0800176#ifdef WIFI_HAL_VERSION_3
177
178// Return number of elements in array
179#ifndef ARRAY_SIZE
180#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
181#endif /* ARRAY_SIZE */
182
183#ifndef ARRAY_AND_SIZE
184#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
185#endif /* ARRAY_AND_SIZE */
186
187#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
188
189typedef struct {
190 int32_t value;
191 int32_t param;
192 intptr_t key;
193 intptr_t data;
194} wifi_secur_list;
195
developerfa41b1f2023-01-06 10:25:51 +0800196static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
197static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
developer72ec5572023-01-05 16:27:13 +0800198static int util_get_sec_chan_offset(int channel, const char* ht_mode);
developer06a01d92022-09-07 16:32:39 +0800199wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
200wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
201char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800202static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800203
204static wifi_secur_list map_security[] =
205{
206 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
207 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
208 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
209 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
210 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800214 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800216 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800217 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800218};
219
220wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
221{
222 wifi_secur_list *item;
223 int i;
224
225 for (item = list,i = 0;i < list_sz; item++, i++) {
226 if ((int)(item->key) == key) {
227 return item;
228 }
229 }
230
231 return NULL;
232}
233
234char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
235{
236 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
237
238 if (!item) {
239 return "";
240 }
241
242 return (char *)(item->data);
243}
244
245wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
246{
247 wifi_secur_list *item;
248 int i;
249
250 for (item = list,i = 0;i < list_sz; item++, i++) {
251 if (strcmp((char *)(item->data), str) == 0) {
252 return item;
253 }
254 }
255
256 return NULL;
257}
258#endif /* WIFI_HAL_VERSION_3 */
259
260#ifdef HAL_NETLINK_IMPL
261typedef struct {
262 int id;
263 struct nl_sock* socket;
264 struct nl_cb* cb;
265} Netlink;
266
267static int mac_addr_aton(unsigned char *mac_addr, char *arg)
268{
269 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800270 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 +0800271 mac_addr[0] = mac_addr_int[0];
272 mac_addr[1] = mac_addr_int[1];
273 mac_addr[2] = mac_addr_int[2];
274 mac_addr[3] = mac_addr_int[3];
275 mac_addr[4] = mac_addr_int[4];
276 mac_addr[5] = mac_addr_int[5];
277 return 0;
278}
279
280static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
281{
282 unsigned int mac_addr_int[6]={};
283 mac_addr_int[0] = arg[0];
284 mac_addr_int[1] = arg[1];
285 mac_addr_int[2] = arg[2];
286 mac_addr_int[3] = arg[3];
287 mac_addr_int[4] = arg[4];
288 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800289 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 +0800290 return;
291}
292
293static int ieee80211_frequency_to_channel(int freq)
294{
developerf5745ee2022-10-05 16:09:53 +0800295 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800296 if (freq == 2484)
297 return 14;
developerf5745ee2022-10-05 16:09:53 +0800298 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
299 else if (freq == 5935)
300 return 2;
developer06a01d92022-09-07 16:32:39 +0800301 else if (freq < 2484)
302 return (freq - 2407) / 5;
303 else if (freq >= 4910 && freq <= 4980)
304 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800305 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800306 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800307 else if (freq <= 45000) /* DMG band lower limit */
308 /* see 802.11ax D6.1 27.3.23.2 */
309 return (freq - 5950) / 5;
310 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800311 return (freq - 56160) / 2160;
312 else
313 return 0;
314}
315
316static int initSock80211(Netlink* nl) {
317 nl->socket = nl_socket_alloc();
318 if (!nl->socket) {
319 fprintf(stderr, "Failing to allocate the sock\n");
320 return -ENOMEM;
321 }
322
323 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
324
325 if (genl_connect(nl->socket)) {
326 fprintf(stderr, "Failed to connect\n");
327 nl_close(nl->socket);
328 nl_socket_free(nl->socket);
329 return -ENOLINK;
330 }
331
332 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
333 if (nl->id< 0) {
334 fprintf(stderr, "interface not found.\n");
335 nl_close(nl->socket);
336 nl_socket_free(nl->socket);
337 return -ENOENT;
338 }
339
340 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
341 if ((!nl->cb)) {
342 fprintf(stderr, "Failed to allocate netlink callback.\n");
343 nl_close(nl->socket);
344 nl_socket_free(nl->socket);
345 return ENOMEM;
346 }
347
348 return nl->id;
349}
350
351static int nlfree(Netlink *nl)
352{
353 nl_cb_put(nl->cb);
354 nl_close(nl->socket);
355 nl_socket_free(nl->socket);
356 return 0;
357}
358
359static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
360 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
361 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
362 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
363};
364
365static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
366};
367
368static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
369};
370
371typedef struct _wifi_channelStats_loc {
372 INT array_size;
373 INT ch_number;
374 BOOL ch_in_pool;
375 INT ch_noise;
376 BOOL ch_radar_noise;
377 INT ch_max_80211_rssi;
378 INT ch_non_80211_noise;
379 INT ch_utilization;
380 ULLONG ch_utilization_total;
381 ULLONG ch_utilization_busy;
382 ULLONG ch_utilization_busy_tx;
383 ULLONG ch_utilization_busy_rx;
384 ULLONG ch_utilization_busy_self;
385 ULLONG ch_utilization_busy_ext;
386} wifi_channelStats_t_loc;
387
388typedef struct wifi_device_info {
389 INT wifi_devIndex;
390 UCHAR wifi_devMacAddress[6];
391 CHAR wifi_devIPAddress[64];
392 BOOL wifi_devAssociatedDeviceAuthentiationState;
393 INT wifi_devSignalStrength;
394 INT wifi_devTxRate;
395 INT wifi_devRxRate;
396} wifi_device_info_t;
397
398#endif
399
400//For 5g Alias Interfaces
401static BOOL priv_flag = TRUE;
402static BOOL pub_flag = TRUE;
403static BOOL Radio_flag = TRUE;
404//wifi_setApBeaconRate(1, beaconRate);
405
developer1e5aa162022-09-13 16:06:24 +0800406BOOL multiple_set = FALSE;
407
developer06a01d92022-09-07 16:32:39 +0800408struct params
409{
410 char * name;
411 char * value;
412};
413
414static int _syscmd(char *cmd, char *retBuf, int retBufSize)
415{
416 FILE *f;
417 char *ptr = retBuf;
418 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
419
420 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
421 if((f = popen(cmd, "r")) == NULL) {
422 fprintf(stderr,"\npopen %s error\n", cmd);
423 return RETURN_ERR;
424 }
425
426 while(!feof(f))
427 {
428 *ptr = 0;
429 if(bufSize>=128) {
430 bufbytes=128;
431 } else {
432 bufbytes=bufSize-1;
433 }
434
435 fgets(ptr,bufbytes,f);
436 readbytes=strlen(ptr);
437
438 if(!readbytes)
439 break;
440
441 bufSize-=readbytes;
442 ptr += readbytes;
443 }
444 cmd_ret = pclose(f);
445 retBuf[retBufSize-1]=0;
446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
447
448 return cmd_ret >> 8;
449}
450
developer033b37b2022-10-18 11:27:46 +0800451INT radio_index_to_phy(int radioIndex)
452{
453 char cmd[128] = {0};
454 char buf[64] = {0};
455 int phyIndex = 0;
456 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
457 _syscmd(cmd, buf, sizeof(buf));
458
459 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
developer431128d2022-12-16 15:30:41 +0800460 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800461 return RETURN_ERR;
462 }
463 sscanf(buf, "phy%d", &phyIndex);
464
465 return phyIndex;
466}
developer026ac9e2022-11-07 13:46:24 +0800467
developer431128d2022-12-16 15:30:41 +0800468INT wifi_getMaxRadioNumber(INT *max_radio_num)
469{
470 char cmd[64] = {0};
471 char buf[4] = {0};
472
473 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
474
475 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
476 _syscmd(cmd, buf, sizeof(buf));
477 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
478
479 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
480
481 return RETURN_OK;
482}
483
developer59ff6de2023-02-08 17:58:14 +0800484static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
485{
486 char cmd[MAX_CMD_SIZE]={'\0'};
487 char buf[MAX_BUF_SIZE]={'\0'};
488 int ret = 0;
489
490 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
491 ret = _syscmd(cmd, buf, sizeof(buf));
492 if ((ret != 0) && (strlen(buf) == 0))
493 return -1;
494 snprintf(output, output_size, "%s", buf);
495
496 return 0;
497}
498
499static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
500{
501 char cmd[MAX_CMD_SIZE]={'\0'};
502 char buf[MAX_BUF_SIZE]={'\0'};
503
504 for(int i=0;i<item_count;i++)
505 {
506 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
507 if (strlen(buf) == 0) //Insert
508 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
509 else //Update
510 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
511
512 if(_syscmd(cmd, buf, sizeof(buf)))
513 return -1;
514 }
515
516 return 0;
517}
518
developer431128d2022-12-16 15:30:41 +0800519wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800520{
521 char cmd[128] = {0};
522 char buf[64] = {0};
developer59ff6de2023-02-08 17:58:14 +0800523 char config_file[128] = {0};
developer026ac9e2022-11-07 13:46:24 +0800524 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800525 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800526 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800527 int radioIndex = 0;
528 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800529 wifi_band band = band_invalid;
530
531 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800532
developer431128d2022-12-16 15:30:41 +0800533 wifi_getMaxRadioNumber(&max_radio_num);
534 radioIndex = apIndex % max_radio_num;
developer026ac9e2022-11-07 13:46:24 +0800535 phyIndex = radio_index_to_phy(radioIndex);
developer59ff6de2023-02-08 17:58:14 +0800536 snprintf(cmd, sizeof(cmd), "cat /sys/class/ieee80211/phy%d/device/device 2> /dev/null", phyIndex);
537 _syscmd(cmd, buf, sizeof(buf));
538 if (strncmp(buf, "0x7915", 6) == 0) { // harrier have two bands, consider as a special case.
539 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
540 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
541 if (strncmp(buf, "a", 1) == 0)
542 return band_5;
543 else
544 return band_2_4;
545 }
developer5884e982022-10-06 10:52:50 +0800546 while(i < 10){
developer59ff6de2023-02-08 17:58:14 +0800547 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tr -d ':\\n' | awk '{print $2}'", phyIndex);
developer5884e982022-10-06 10:52:50 +0800548 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800549 nl80211_band = strtol(buf, NULL, 10);
550 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800551 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800552 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800553 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800554 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800555 band = band_6;
556
557 if(band != band_invalid)
558 break;
559
560 i++;
561 sleep(1);
562 }
developerc707e972022-09-13 15:38:02 +0800563
564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
565 return band;
566}
567
developerd946fd62022-12-08 18:03:28 +0800568//For Getting Current Interface Name from corresponding hostapd configuration
developerac6f1142022-12-20 19:26:35 +0800569static int wifi_GetInterfaceName(int apIndex, char *interface_name)
developerd946fd62022-12-08 18:03:28 +0800570{
571 char config_file[128] = {0};
572
573 if (interface_name == NULL)
574 return RETURN_ERR;
575
576 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
577
578 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
579 wifi_hostapdRead(config_file, "interface", interface_name, 16);
580 if (strlen(interface_name) == 0)
581 return RETURN_ERR;
582
583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
584 return RETURN_OK;
585}
586
developerac6f1142022-12-20 19:26:35 +0800587// wifi agent will call this function, do not change the parameter
588void GetInterfaceName(char *interface_name, char *conf_file)
589{
590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
591 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
593}
594
developer06a01d92022-09-07 16:32:39 +0800595static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
596{
developerd946fd62022-12-08 18:03:28 +0800597 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800598 if (multiple_set == TRUE)
599 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800600 char cmd[MAX_CMD_SIZE]="", output[32]="";
601 FILE *fp;
602 int i;
603 //NOTE RELOAD should be done in ApplySSIDSettings
developerac6f1142022-12-20 19:26:35 +0800604 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800605 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800606 for(i=0; i<item_count; i++, list++)
607 {
developerd946fd62022-12-08 18:03:28 +0800608 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800609 if((fp = popen(cmd, "r"))==NULL)
610 {
611 perror("popen failed");
612 return -1;
613 }
614 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
615 {
616 pclose(fp);
617 perror("fgets failed");
618 return -1;
619 }
620 pclose(fp);
621 }
622 return 0;
623}
624
625static int wifi_reloadAp(int apIndex)
626{
developerd946fd62022-12-08 18:03:28 +0800627 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800628 if (multiple_set == TRUE)
629 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800630 char cmd[MAX_CMD_SIZE]="";
631 char buf[MAX_BUF_SIZE]="";
632
developerac6f1142022-12-20 19:26:35 +0800633 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800634 return RETURN_ERR;
635 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800636 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
637 return RETURN_ERR;
638
developerd946fd62022-12-08 18:03:28 +0800639 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800640 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
641 return RETURN_ERR;
642
developerd946fd62022-12-08 18:03:28 +0800643 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800644 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
645 return RETURN_ERR;
646
647 return RETURN_OK;
648}
649
developer06a01d92022-09-07 16:32:39 +0800650INT File_Reading(CHAR *file, char *Value)
651{
652 FILE *fp = NULL;
653 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
654 int count = 0;
655
656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
657 fp = popen(file,"r");
658 if(fp == NULL)
659 return RETURN_ERR;
660
661 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
662 {
663 for(count=0;buf[count]!='\n';count++)
664 copy_buf[count]=buf[count];
665 copy_buf[count]='\0';
666 }
667 strcpy(Value,copy_buf);
668 pclose(fp);
669 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
670
671 return RETURN_OK;
672}
673
674void wifi_RestartHostapd_2G()
675{
676 int Public2GApIndex = 4;
677
678 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
679 wifi_setApEnable(Public2GApIndex, FALSE);
680 wifi_setApEnable(Public2GApIndex, TRUE);
681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
682}
683
684void wifi_RestartHostapd_5G()
685{
686 int Public5GApIndex = 5;
687
688 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
689 wifi_setApEnable(Public5GApIndex, FALSE);
690 wifi_setApEnable(Public5GApIndex, TRUE);
691 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
692}
693
694void wifi_RestartPrivateWifi_2G()
695{
696 int PrivateApIndex = 0;
697
698 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
699 wifi_setApEnable(PrivateApIndex, FALSE);
700 wifi_setApEnable(PrivateApIndex, TRUE);
701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
702}
703
704void wifi_RestartPrivateWifi_5G()
705{
706 int Private5GApIndex = 1;
707
708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
709 wifi_setApEnable(Private5GApIndex, FALSE);
710 wifi_setApEnable(Private5GApIndex, TRUE);
711 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
712}
713
714static int writeBandWidth(int radioIndex,char *bw_value)
715{
716 char buf[MAX_BUF_SIZE];
717 char cmd[MAX_CMD_SIZE];
718
719 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
720 if(_syscmd(cmd, buf, sizeof(buf)))
721 {
722 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
723 _syscmd(cmd, buf, sizeof(buf));
724 return RETURN_OK;
725 }
726
727 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
728 _syscmd(cmd,buf,sizeof(buf));
729 return RETURN_OK;
730}
731
732static int readBandWidth(int radioIndex,char *bw_value)
733{
developer30423732022-12-01 16:17:49 +0800734 char buf[MAX_BUF_SIZE] = {0};
735 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800736 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
737 _syscmd(cmd,buf,sizeof(buf));
738 if(NULL!=strstr(buf,"20MHz"))
developer06a01d92022-09-07 16:32:39 +0800739 strcpy(bw_value,"20MHz");
developer06a01d92022-09-07 16:32:39 +0800740 else if(NULL!=strstr(buf,"40MHz"))
developer06a01d92022-09-07 16:32:39 +0800741 strcpy(bw_value,"40MHz");
developer06a01d92022-09-07 16:32:39 +0800742 else if(NULL!=strstr(buf,"80MHz"))
developer06a01d92022-09-07 16:32:39 +0800743 strcpy(bw_value,"80MHz");
developer57fa24a2023-03-15 17:25:07 +0800744 else if(NULL!=strstr(buf,"160MHz"))
745 strcpy(bw_value,"160MHz");
746 else if(NULL!=strstr(buf,"320MHz"))
747 strcpy(bw_value,"320MHz");
developer06a01d92022-09-07 16:32:39 +0800748 else
developer06a01d92022-09-07 16:32:39 +0800749 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800750 return RETURN_OK;
751}
752
developer264159b2022-11-02 09:41:35 +0800753// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800754INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
755{
developer5f222492022-09-13 15:21:52 +0800756 struct params params={'\0'};
757 char config_file[MAX_BUF_SIZE] = {0};
758 char buf[MAX_BUF_SIZE] = {'\0'};
759
760 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800761 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800762 if (strlen (beaconRate) >= 5) {
763 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
764 buf[strlen(beaconRate) - 4] = '\0';
765 } else if (strlen(beaconRate) > 0)
766 strcpy(buf, beaconRate);
767 else
768 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800769
770 params.name = "beacon_rate";
771 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
772 if (strncmp(buf, "5.5", 3) == 0) {
773 snprintf(buf, sizeof(buf), "55");
774 params.value = buf;
775 } else {
776 strcat(buf, "0");
777 params.value = buf;
778 }
779
780 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
781 wifi_hostapdWrite(config_file, &params, 1);
782 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
784
785 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800786}
787
788INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
789{
developer1d57d002022-10-12 18:03:15 +0800790 char config_file[128] = {'\0'};
791 char temp_output[128] = {'\0'};
792 char buf[128] = {'\0'};
793 char cmd[128] = {'\0'};
794 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800795 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800796
797 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
798 if (NULL == beaconRate)
799 return RETURN_ERR;
800
801 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
802 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800803 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800804 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
805 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800806 if (strncmp(buf, "55", 2) == 0)
807 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
808 else {
809 rate = strtol(buf, NULL, 10)/10;
810 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
811 }
developer5f222492022-09-13 15:21:52 +0800812 } else {
developer1d57d002022-10-12 18:03:15 +0800813 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800814 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
developer1d57d002022-10-12 18:03:15 +0800815 _syscmd(cmd, buf, sizeof(buf));
816 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800817 }
818 strncpy(beaconRate, temp_output, sizeof(temp_output));
819 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
820
821 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800822}
823
824INT wifi_setLED(INT radioIndex, BOOL enable)
825{
826 return 0;
827}
828INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
829{
830 return RETURN_OK;
831}
832/**********************************************************************************
833 *
834 * Wifi Subsystem level function prototypes
835 *
836**********************************************************************************/
837//---------------------------------------------------------------------------------------------------
838//Wifi system api
839//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
840INT wifi_getHalVersion(CHAR *output_string) //RDKB
841{
842 if(!output_string)
843 return RETURN_ERR;
844 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
845
846 return RETURN_OK;
847}
848
849
850/* wifi_factoryReset() function */
851/**
852* @description Clears internal variables to implement a factory reset of the Wi-Fi
853* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
854*
855* @param None
856*
857* @return The status of the operation.
858* @retval RETURN_OK if successful.
859* @retval RETURN_ERR if any error is detected
860*
861* @execution Synchronous
862* @sideeffect None
863*
864* @note This function must not suspend and must not invoke any blocking system
865* calls. It should probably just send a message to a driver event handler task.
866*
867*/
868INT wifi_factoryReset()
869{
870 char cmd[128];
871
872 /*delete running hostapd conf files*/
developer72ec5572023-01-05 16:27:13 +0800873 wifi_dbg_printf("\n[%s]: deleting hostapd conf file",__func__);
874 sprintf(cmd, "rm -rf /nvram/hostapd*");
developer06a01d92022-09-07 16:32:39 +0800875 system(cmd);
876 system("systemctl restart hostapd.service");
877
878 return RETURN_OK;
879}
880
881/* wifi_factoryResetRadios() function */
882/**
883* @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.
884*
885* @param None
886* @return The status of the operation
887* @retval RETURN_OK if successful
888* @retval RETURN_ERR if any error is detected
889*
890* @execution Synchronous
891*
892* @sideeffect None
893*
894* @note This function must not suspend and must not invoke any blocking system
895* calls. It should probably just send a message to a driver event handler task.
896*
897*/
898INT wifi_factoryResetRadios()
899{
developer72ec5572023-01-05 16:27:13 +0800900 int max_radio_num = 0;
901 wifi_getMaxRadioNumber(&max_radio_num);
902 for (int radioIndex = 0; radioIndex < max_radio_num; radioIndex++)
903 wifi_factoryResetRadio(radioIndex);
developer06a01d92022-09-07 16:32:39 +0800904
developer72ec5572023-01-05 16:27:13 +0800905 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800906}
907
908
909/* wifi_factoryResetRadio() function */
910/**
911* @description Restore selected radio parameters without touching access point parameters
912*
913* @param radioIndex - Index of Wi-Fi Radio channel
914*
915* @return The status of the operation.
916* @retval RETURN_OK if successful.
917* @retval RETURN_ERR if any error is detected
918*
919* @execution Synchronous.
920* @sideeffect None.
921*
922* @note This function must not suspend and must not invoke any blocking system
923* calls. It should probably just send a message to a driver event handler task.
924*
925*/
926INT wifi_factoryResetRadio(int radioIndex) //RDKB
927{
developer72ec5572023-01-05 16:27:13 +0800928 char cmd[128] = {0};
929 char buf[128] = {0};
930 int max_radio_num = 0;
931
932 wifi_getMaxRadioNumber(&max_radio_num);
933 if (radioIndex < 0 || radioIndex > max_radio_num)
934 return RETURN_ERR;
935
936 snprintf(cmd, sizeof(cmd), "systemctl stop hostapd.service");
937 _syscmd(cmd, buf, sizeof(buf));
developer5ff7f5f2022-09-13 15:12:16 +0800938
developer06a01d92022-09-07 16:32:39 +0800939 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72ec5572023-01-05 16:27:13 +0800940 snprintf(cmd, sizeof(cmd), "rm /nvram/hostapd%d* %s%d.txt", radioIndex, GUARD_INTERVAL_FILE, radioIndex);
941 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800942
developer72ec5572023-01-05 16:27:13 +0800943 snprintf(cmd, sizeof(cmd), "systemctl start hostapd.service");
944 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800945 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
946 return RETURN_OK;
947}
948
949/* wifi_initRadio() function */
950/**
951* Description: This function call initializes the specified radio.
952* Implementation specifics may dictate the functionality since
953* different hardware implementations may have different initilization requirements.
954* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
955*
956* @return The status of the operation.
957* @retval RETURN_OK if successful.
958* @retval RETURN_ERR if any error is detected
959*
960* @execution Synchronous.
961* @sideeffect None.
962*
963* @note This function must not suspend and must not invoke any blocking system
964* calls. It should probably just send a message to a driver event handler task.
965*
966*/
967INT wifi_initRadio(INT radioIndex)
968{
969 //TODO: Initializes the wifi subsystem (for specified radio)
970 return RETURN_OK;
971}
972void macfilter_init()
973{
974 char count[4]={'\0'};
975 char buf[253]={'\0'};
976 char tmp[19]={'\0'};
977 int dev_count,block,mac_entry=0;
978 char res[4]={'\0'};
979 char acl_file_path[64] = {'\0'};
980 FILE *fp = NULL;
981 int index=0;
982 char iface[10]={'\0'};
983 char config_file[MAX_BUF_SIZE] = {0};
984
985
986 sprintf(acl_file_path,"/tmp/mac_filter.sh");
987
988 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800989 if (fp == NULL) {
990 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
991 return RETURN_ERR;
992 }
developer06a01d92022-09-07 16:32:39 +0800993 sprintf(buf,"#!/bin/sh \n");
994 fprintf(fp,"%s\n",buf);
995
996 system("chmod 0777 /tmp/mac_filter.sh");
997
998 for(index=0;index<=1;index++)
999 {
1000 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1001 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1002 sprintf(buf,"syscfg get %dcountfilter",index);
1003 _syscmd(buf,count,sizeof(count));
1004 mac_entry=atoi(count);
1005
1006 sprintf(buf,"syscfg get %dblockall",index);
1007 _syscmd(buf,res,sizeof(res));
1008 block = atoi(res);
1009
1010 //Allow only those macs mentioned in ACL
1011 if(block==1)
1012 {
1013 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1014 fprintf(fp,"%s\n",buf);
1015 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1016 {
1017 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1018 _syscmd(buf,tmp,sizeof(tmp));
1019 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1020 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1021 fprintf(fp,"%s\n",buf);
1022 }
1023 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1024 fprintf(fp,"%s\n",buf);
1025 }
1026
1027 //Block all the macs mentioned in ACL
1028 else if(block==2)
1029 {
1030 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1031 fprintf(fp,"%s\n",buf);
1032
1033 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1034 {
1035 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1036 _syscmd(buf,tmp,sizeof(tmp));
1037 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1038 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1039 fprintf(fp,"%s\n",buf);
1040 }
1041 }
1042 }
1043 fclose(fp);
1044}
1045
1046// Initializes the wifi subsystem (all radios)
1047INT wifi_init() //RDKB
1048{
1049 char interface[MAX_BUF_SIZE]={'\0'};
1050 char bridge_name[MAX_BUF_SIZE]={'\0'};
1051 INT len=0;
1052
1053 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1054 //Not intitializing macfilter for Turris-Omnia Platform for now
1055 //macfilter_init();
1056
1057 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001058 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001059 sleep(2);//sleep to wait for hostapd to start
1060
1061 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1062
1063 return RETURN_OK;
1064}
1065
1066/* wifi_reset() function */
1067/**
1068* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1069* Implementation specifics may dictate what is actualy reset since
1070* different hardware implementations may have different requirements.
1071* Parameters : None
1072*
1073* @return The status of the operation.
1074* @retval RETURN_OK if successful.
1075* @retval RETURN_ERR if any error is detected
1076*
1077* @execution Synchronous.
1078* @sideeffect None.
1079*
1080* @note This function must not suspend and must not invoke any blocking system
1081* calls. It should probably just send a message to a driver event handler task.
1082*
1083*/
1084INT wifi_reset()
1085{
1086 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001087 system("systemctl stop hostapd.service");
1088 sleep(2);
1089 system("systemctl start hostapd.service");
1090 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001091 return RETURN_OK;
1092}
1093
1094/* wifi_down() function */
1095/**
1096* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1097* Implementation specifics may dictate some functionality since
1098* different hardware implementations may have different requirements.
1099*
1100* @param None
1101*
1102* @return The status of the operation
1103* @retval RETURN_OK if successful
1104* @retval RETURN_ERR if any error is detected
1105*
1106* @execution Synchronous
1107* @sideeffect None
1108*
1109* @note This function must not suspend and must not invoke any blocking system
1110* calls. It should probably just send a message to a driver event handler task.
1111*
1112*/
1113INT wifi_down()
1114{
1115 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer72ec5572023-01-05 16:27:13 +08001116 int max_num_radios = 0;
1117 wifi_getMaxRadioNumber(&max_num_radios);
1118 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
1119 wifi_setRadioEnable(radioIndex, FALSE);
1120
developer06a01d92022-09-07 16:32:39 +08001121 return RETURN_OK;
1122}
1123
1124
1125/* wifi_createInitialConfigFiles() function */
1126/**
1127* @description This function creates wifi configuration files. The format
1128* and content of these files are implementation dependent. This function call is
1129* used to trigger this task if necessary. Some implementations may not need this
1130* function. If an implementation does not need to create config files the function call can
1131* do nothing and return RETURN_OK.
1132*
1133* @param None
1134*
1135* @return The status of the operation
1136* @retval RETURN_OK if successful
1137* @retval RETURN_ERR if any error is detected
1138*
1139* @execution Synchronous
1140* @sideeffect None
1141*
1142* @note This function must not suspend and must not invoke any blocking system
1143* calls. It should probably just send a message to a driver event handler task.
1144*
1145*/
1146INT wifi_createInitialConfigFiles()
1147{
1148 //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)
1149 return RETURN_OK;
1150}
1151
1152// outputs the country code to a max 64 character string
1153INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1154{
developerd946fd62022-12-08 18:03:28 +08001155 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001156 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001157 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001158 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001159
developerac6f1142022-12-20 19:26:35 +08001160 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001161 return RETURN_ERR;
1162 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001163 _syscmd(cmd, buf, sizeof(buf));
1164 if(strlen(buf) > 0)
1165 snprintf(output_string, 64, "%s", buf);
1166 else
1167 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001168
1169 return RETURN_OK;
1170}
1171
1172INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1173{
1174 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001175 char str[MAX_BUF_SIZE]={'\0'};
1176 char cmd[MAX_CMD_SIZE]={'\0'};
1177 struct params params;
1178 char config_file[MAX_BUF_SIZE] = {0};
1179
1180 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1181 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1182 return RETURN_ERR;
1183
developerb86c6f32022-10-07 14:34:58 +08001184 if (strlen(CountryCode) == 0)
1185 strcpy(CountryCode, "US");
1186
developer7543b3b2022-09-13 13:47:17 +08001187 params.name = "country_code";
1188 params.value = CountryCode;
1189 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1190 int ret = wifi_hostapdWrite(config_file, &params, 1);
1191 if (ret) {
1192 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1193 ,__func__, ret);
1194 }
1195
1196 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1197 if (ret) {
1198 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1199 ,__func__, ret);
1200 }
developer7543b3b2022-09-13 13:47:17 +08001201 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1202
developer06a01d92022-09-07 16:32:39 +08001203 return RETURN_OK;
1204}
1205
developera748dcf2022-09-13 15:56:48 +08001206INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1207{
developerd946fd62022-12-08 18:03:28 +08001208 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001209 char channel_util_file[64] = {0};
1210 char cmd[128] = {0};
1211 char buf[128] = {0};
1212 char line[128] = {0};
1213 char *param = NULL, *value = NULL;
1214 int read = 0;
1215 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1216 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1217 size_t len = 0;
1218 FILE *f = NULL;
1219
1220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1221
developerac6f1142022-12-20 19:26:35 +08001222 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001223 return RETURN_ERR;
1224 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001225 _syscmd(cmd, buf, sizeof(buf));
1226 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1227
1228 memset(cmd, 0, sizeof(cmd));
1229 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001230 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001231 if ((f = popen(cmd, "r")) == NULL) {
1232 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1233 return RETURN_ERR;
1234 }
1235
1236 read = getline(&line, &len, f);
1237 while (read != -1) {
1238 param = strtok(line, ":\t");
1239 value = strtok(NULL, " ");
1240 if(strstr(param, "frequency") != NULL) {
1241 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1242 }
1243 if(strstr(param, "noise") != NULL) {
1244 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1245 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1246 }
1247 if(strstr(param, "channel active time") != NULL) {
1248 ActiveTime = strtol(value, NULL, 10);
1249 }
1250 if(strstr(param, "channel busy time") != NULL) {
1251 BusyTime = strtol(value, NULL, 10);
1252 }
1253 if(strstr(param, "channel transmit time") != NULL) {
1254 TransmitTime = strtol(value, NULL, 10);
1255 }
1256 read = getline(&line, &len, f);
1257 }
1258 pclose(f);
1259
1260 // The file should store the last active, busy and transmit time
1261 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1262 f = fopen(channel_util_file, "r");
1263 if (f != NULL) {
1264 read = getline(&line, &len, f);
1265 preActiveTime = strtol(line, NULL, 10);
1266 read = getline(&line, &len, f);
1267 preBusyTime = strtol(line, NULL, 10);
1268 read = getline(&line, &len, f);
1269 preTransmitTime = strtol(line, NULL, 10);
1270 fclose(f);
1271 }
1272
1273 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1274 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1275
1276 f = fopen(channel_util_file, "w");
1277 if (f != NULL) {
1278 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1279 fclose(f);
1280 }
1281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1282 return RETURN_OK;
1283}
1284
developer06a01d92022-09-07 16:32:39 +08001285/**********************************************************************************
1286 *
1287 * Wifi radio level function prototypes
1288 *
1289**********************************************************************************/
1290
1291//Get the total number of radios in this wifi subsystem
1292INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1293{
1294 if (NULL == output)
1295 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001296 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001297
1298 return RETURN_OK;
1299}
1300
1301//Get the total number of SSID entries in this wifi subsystem
1302INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1303{
1304 if (NULL == output)
1305 return RETURN_ERR;
1306 *output = MAX_APS;
1307
1308 return RETURN_OK;
1309}
1310
1311//Get the Radio enable config parameter
1312INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1313{
developerd946fd62022-12-08 18:03:28 +08001314 char interface_name[16] = {0};
developer7930d352022-12-21 17:55:42 +08001315 char buf[128] = {0}, cmd[128] = {0};
developera77d84b2023-02-22 16:10:50 +08001316 int apIndex;
1317 int max_radio_num = 0;
developer06a01d92022-09-07 16:32:39 +08001318
1319 if (NULL == output_bool)
1320 return RETURN_ERR;
1321
1322 *output_bool = FALSE;
developera77d84b2023-02-22 16:10:50 +08001323
1324 wifi_getMaxRadioNumber(&max_radio_num);
1325
1326 if (radioIndex >= max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001327 return RETURN_ERR;
1328
developera77d84b2023-02-22 16:10:50 +08001329 /* loop all interface in radio, if any is enable, reture true, else return false */
1330 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1331 {
developer643b28f2023-04-04 10:26:01 +08001332 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developera77d84b2023-02-22 16:10:50 +08001333 continue;
1334 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1335 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001336
developera77d84b2023-02-22 16:10:50 +08001337 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 ||
1338 strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0) {
1339 /* return true if any interface is eanble */
1340 *output_bool = TRUE;
1341 break;
1342 }
1343 }
developer06a01d92022-09-07 16:32:39 +08001344 return RETURN_OK;
1345}
1346
1347INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1348{
developerd946fd62022-12-08 18:03:28 +08001349 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001350 char cmd[MAX_CMD_SIZE] = {0};
1351 char buf[MAX_CMD_SIZE] = {0};
1352 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08001353 int max_radio_num = 0;
1354 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001355
1356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001357
1358 phyId = radio_index_to_phy(radioIndex);
1359
1360 wifi_getMaxRadioNumber(&max_radio_num);
1361
developer06a01d92022-09-07 16:32:39 +08001362 if(enable==FALSE)
1363 {
developera77d84b2023-02-22 16:10:50 +08001364 /* disable from max apindex to min, to avoid fail in mbss case */
1365 for(apIndex=(MAX_APS-max_radio_num+radioIndex); apIndex>=0; apIndex-=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001366 {
developer1e125222022-12-29 09:35:25 +08001367 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001368 continue;
developer1e125222022-12-29 09:35:25 +08001369
developer06a01d92022-09-07 16:32:39 +08001370 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001371 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001372 _syscmd(cmd, buf, sizeof(buf));
1373 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001374 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer1e125222022-12-29 09:35:25 +08001375
developer2f18b9f2023-03-17 19:32:57 +08001376 if (!(apIndex/max_radio_num)) {
1377 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
1378 _syscmd(cmd, buf, sizeof(buf));
1379 }
developer06a01d92022-09-07 16:32:39 +08001380 }
developer06a01d92022-09-07 16:32:39 +08001381 }
1382 else
1383 {
developer033b37b2022-10-18 11:27:46 +08001384 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001385 {
developer1e125222022-12-29 09:35:25 +08001386 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001387 continue;
developer1e125222022-12-29 09:35:25 +08001388
developer643b28f2023-04-04 10:26:01 +08001389 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001390 _syscmd(cmd, buf, sizeof(buf));
developera77d84b2023-02-22 16:10:50 +08001391 if(*buf == '1') {
developer2f18b9f2023-03-17 19:32:57 +08001392 if (!(apIndex/max_radio_num)) {
1393 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1394 ret = _syscmd(cmd, buf, sizeof(buf));
1395 if ( ret == RETURN_ERR) {
1396 fprintf(stderr, "VAP interface creation failed\n");
1397 continue;
1398 }
developera77d84b2023-02-22 16:10:50 +08001399 }
developer06a01d92022-09-07 16:32:39 +08001400 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001401 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001402 _syscmd(cmd, buf, sizeof(buf));
1403 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001404 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001405 }
1406 }
1407 }
1408
1409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1410 return RETURN_OK;
1411}
1412
1413//Get the Radio enable status
1414INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1415{
1416 if (NULL == output_bool)
1417 return RETURN_ERR;
1418
1419 return wifi_getRadioEnable(radioIndex, output_bool);
1420}
1421
1422//Get the Radio Interface name from platform, eg "wlan0"
1423INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1424{
developer804c64f2022-10-19 13:54:40 +08001425 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001426 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08001427 return wifi_GetInterfaceName(radioIndex, output_string);
developer06a01d92022-09-07 16:32:39 +08001428}
1429
1430//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1431//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.
1432INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1433{
developerbcc556a2022-09-22 20:02:45 +08001434 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1435 // For max bit rate, we should always choose the best MCS
1436 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001437 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001438 char *tmp = NULL;
1439 UINT mode_map = 0;
1440 UINT num_subcarrier = 0;
1441 UINT code_bits = 0;
1442 float code_rate = 0; // use max code rate
1443 int NSS = 0;
1444 UINT Symbol_duration = 0;
1445 UINT GI_duration = 0;
1446 wifi_band band = band_invalid;
1447 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1448 BOOL enable = FALSE;
1449 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001450
1451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1452 if (NULL == output_string)
1453 return RETURN_ERR;
1454
developerbcc556a2022-09-22 20:02:45 +08001455 wifi_getRadioEnable(radioIndex, &enable);
1456 if (enable == FALSE) {
1457 snprintf(output_string, 64, "0 Mb/s");
1458 return RETURN_OK;
1459 }
1460
1461 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1462 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1463 return RETURN_ERR;
1464 }
1465
1466 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1467 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1468 return RETURN_ERR;
1469 }
1470
1471 if (gi == wifi_guard_interval_3200)
1472 GI_duration = 32;
1473 else if (gi == wifi_guard_interval_1600)
1474 GI_duration = 16;
1475 else if (gi == wifi_guard_interval_800)
1476 GI_duration = 8;
1477 else // auto, 400
1478 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001479
developerbcc556a2022-09-22 20:02:45 +08001480 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1481 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1482 return RETURN_ERR;
1483 }
1484
1485 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1486 strcpy(channel_bandwidth_str, "160");
1487
1488 if (mode_map & WIFI_MODE_AX) {
1489 if (strstr(channel_bandwidth_str, "160") != NULL)
1490 num_subcarrier = 1960;
1491 else if (strstr(channel_bandwidth_str, "80") != NULL)
1492 num_subcarrier = 980;
1493 else if (strstr(channel_bandwidth_str, "40") != NULL)
1494 num_subcarrier = 468;
1495 else if (strstr(channel_bandwidth_str, "20") != NULL)
1496 num_subcarrier = 234;
1497 code_bits = 10;
1498 code_rate = (float)5/6;
1499 Symbol_duration = 128;
1500 } else if (mode_map & WIFI_MODE_AC) {
1501 if (strstr(channel_bandwidth_str, "160") != NULL)
1502 num_subcarrier = 468;
1503 else if (strstr(channel_bandwidth_str, "80") != NULL)
1504 num_subcarrier = 234;
1505 else if (strstr(channel_bandwidth_str, "40") != NULL)
1506 num_subcarrier = 108;
1507 else if (strstr(channel_bandwidth_str, "20") != NULL)
1508 num_subcarrier = 52;
1509 code_bits = 8;
1510 code_rate = (float)5/6;
1511 Symbol_duration = 32;
1512 } else if (mode_map & WIFI_MODE_N) {
1513 if (strstr(channel_bandwidth_str, "160") != NULL)
1514 num_subcarrier = 468;
1515 else if (strstr(channel_bandwidth_str, "80") != NULL)
1516 num_subcarrier = 234;
1517 else if (strstr(channel_bandwidth_str, "40") != NULL)
1518 num_subcarrier = 108;
1519 else if (strstr(channel_bandwidth_str, "20") != NULL)
1520 num_subcarrier = 52;
1521 code_bits = 6;
1522 code_rate = (float)3/4;
1523 Symbol_duration = 32;
1524 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1525 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1526 snprintf(output_string, 64, "65 Mb/s");
1527 return RETURN_OK;
1528 } else {
1529 snprintf(output_string, 64, "0 Mb/s");
1530 return RETURN_OK;
1531 }
developer06a01d92022-09-07 16:32:39 +08001532
developerbcc556a2022-09-22 20:02:45 +08001533 // Spatial streams
1534 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1535 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1536 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001537 }
developerbcc556a2022-09-22 20:02:45 +08001538
1539 // multiple 10 is to align duration unit (0.1 us)
1540 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1541 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1542
developer06a01d92022-09-07 16:32:39 +08001543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1544
1545 return RETURN_OK;
1546}
1547#if 0
1548INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1549{
1550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1551 char cmd[64];
1552 char buf[1024];
1553 int apIndex;
1554
1555 if (NULL == output_string)
1556 return RETURN_ERR;
1557
1558 apIndex=(radioIndex==0)?0:1;
1559
developerd946fd62022-12-08 18:03:28 +08001560 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001561 _syscmd(cmd,buf, sizeof(buf));
1562
1563 snprintf(output_string, 64, "%s", buf);
1564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1565 return RETURN_OK;
1566}
1567#endif
1568
1569
1570//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1571//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.
1572INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1573{
developer963da0c2022-09-13 15:58:27 +08001574 wifi_band band = band_invalid;
1575
developer06a01d92022-09-07 16:32:39 +08001576 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1577 if (NULL == output_string)
1578 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001579
1580 band = wifi_index_to_band(radioIndex);
1581
1582 memset(output_string, 0, 10);
1583 if (band == band_2_4)
1584 strcpy(output_string, "2.4GHz");
1585 else if (band == band_5)
1586 strcpy(output_string, "5GHz");
1587 else if (band == band_6)
1588 strcpy(output_string, "6GHz");
1589 else
1590 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1592
1593 return RETURN_OK;
1594#if 0
1595 char buf[MAX_BUF_SIZE]={'\0'};
1596 char str[MAX_BUF_SIZE]={'\0'};
1597 char cmd[MAX_CMD_SIZE]={'\0'};
1598 char *ch=NULL;
1599 char *ch2=NULL;
1600
1601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1602 if (NULL == output_string)
1603 return RETURN_ERR;
1604
1605
1606 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1607
1608 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1609 {
1610 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1611 return RETURN_ERR;
1612 }
1613 ch=strchr(buf,'\n');
1614 *ch='\0';
1615 ch=strchr(buf,'=');
1616 if(ch==NULL)
1617 return RETURN_ERR;
1618
1619
1620 ch++;
1621
1622 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1623 strcpy(buf,"0");
1624 if(strlen(ch) == 1)
1625 ch=strcat(buf,ch);
1626
1627
1628 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1629
1630 if(_syscmd(cmd,str,64) == RETURN_ERR)
1631 {
1632 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1633 return RETURN_ERR;
1634 }
1635
1636
1637 ch2=strchr(str,'\n');
1638 //replace \n with \0
1639 *ch2='\0';
1640 ch2=strchr(str,'=');
1641 if(ch2==NULL)
1642 {
1643 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1644 return RETURN_ERR;
1645 }
1646 else
1647 wifi_dbg_printf("%s",ch2+1);
1648
1649
1650 ch2++;
1651
1652
1653 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1654
1655 memset(buf,'\0',sizeof(buf));
1656 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1657 {
1658 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1659 return RETURN_ERR;
1660 }
1661 if (strstr(buf,"2.4") != NULL )
1662 strcpy(output_string,"2.4GHz");
1663 else if(strstr(buf,"5.") != NULL )
1664 strcpy(output_string,"5GHz");
1665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1666
1667 return RETURN_OK;
1668#endif
1669}
1670
1671//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1672//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.
1673INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1674{
developerb7593de2022-10-18 09:51:57 +08001675 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1677 if (NULL == output_string)
1678 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001679 band = wifi_index_to_band(radioIndex);
1680
1681 if (band == band_2_4)
1682 snprintf(output_string, 64, "2.4GHz");
1683 else if (band == band_5)
1684 snprintf(output_string, 64, "5GHz");
1685 else if (band == band_6)
1686 snprintf(output_string, 64, "6GHz");
1687
developer06a01d92022-09-07 16:32:39 +08001688 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1689
1690 return RETURN_OK;
1691#if 0
1692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1693 char buf[MAX_BUF_SIZE]={'\0'};
1694 char str[MAX_BUF_SIZE]={'\0'};
1695 char cmd[MAX_CMD_SIZE]={'\0'};
1696 char *ch=NULL;
1697 char *ch2=NULL;
1698 char ch1[5]="0";
1699
1700 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1701
1702 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1703 {
1704 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1705 return RETURN_ERR;
1706 }
1707
1708 ch=strchr(buf,'\n');
1709 *ch='\0';
1710 ch=strchr(buf,'=');
1711 if(ch==NULL)
1712 return RETURN_ERR;
1713 ch++;
1714
1715 if(strlen(ch)==1)
1716 {
1717 strcat(ch1,ch);
1718
1719 }
1720 else
1721 {
1722 strcpy(ch1,ch);
1723 }
1724
1725
1726
1727 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1728 if(_syscmd(cmd,str,64) == RETURN_ERR)
1729 {
1730 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1731 return RETURN_ERR;
1732 }
1733
1734
1735 ch2=strchr(str,'\n');
1736 //replace \n with \0
1737 *ch2='\0';
1738 ch2=strchr(str,'=');
1739 if(ch2==NULL)
1740 {
1741 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1742 return RETURN_ERR;
1743 }
1744 else
1745 wifi_dbg_printf("%s",ch2+1);
1746 ch2++;
1747
1748
1749 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1750 memset(buf,'\0',sizeof(buf));
1751 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1752 {
1753 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1754 return RETURN_ERR;
1755 }
1756
1757
1758 if(strstr(buf,"2.4")!=NULL)
1759 {
1760 strcpy(output_string,"2.4GHz");
1761 }
1762 if(strstr(buf,"5.")!=NULL)
1763 {
1764 strcpy(output_string,"5GHz");
1765 }
1766 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1767 return RETURN_OK;
1768#endif
1769}
1770
1771//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1772//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.
1773INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1774{
developer963da0c2022-09-13 15:58:27 +08001775 char cmd[128]={0};
1776 char buf[128]={0};
1777 char temp_output[128] = {0};
1778 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001779 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001780
1781 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001782 if (NULL == output_string)
1783 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001784
1785 band = wifi_index_to_band(radioIndex);
1786 if (band == band_2_4) {
1787 strcat(temp_output, "b,g,");
1788 } else if (band == band_5) {
1789 strcat(temp_output, "a,");
1790 }
developer033b37b2022-10-18 11:27:46 +08001791 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001792 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001793 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 +08001794 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001795 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001796 strcat(temp_output, "n,");
1797 }
developer06a01d92022-09-07 16:32:39 +08001798
developer963da0c2022-09-13 15:58:27 +08001799 // vht capabilities
1800 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001801 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 +08001802 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001803 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001804 strcat(temp_output, "ac,");
1805 }
1806 }
1807
1808 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001809 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 +08001810 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001811 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001812 strcat(temp_output, "ax,");
1813 }
1814
developer7c4cd202023-03-01 10:56:29 +08001815 // eht capabilities
1816 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);
1817 _syscmd(cmd, buf, sizeof(buf));
1818 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
1819 strcat(temp_output, "be,");
1820 }
1821
developer963da0c2022-09-13 15:58:27 +08001822 // Remove the last comma
1823 if (strlen(temp_output) != 0)
1824 temp_output[strlen(temp_output)-1] = '\0';
1825 strncpy(output_string, temp_output, strlen(temp_output));
1826 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001827 return RETURN_OK;
1828}
1829
1830//Get the radio operating mode, and pure mode flag. eg: "ac"
1831//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.
1832INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1833{
1834 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1835 if (NULL == output_string)
1836 return RETURN_ERR;
1837
1838 if (radioIndex == 0) {
1839 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1840 *gOnly = FALSE;
1841 *nOnly = TRUE;
1842 *acOnly = FALSE;
1843 } else {
1844 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1845 *gOnly = FALSE;
1846 *nOnly = FALSE;
1847 *acOnly = FALSE;
1848 }
1849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1850
1851 return RETURN_OK;
1852#if 0
1853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1854 char buf[64] = {0};
1855 char config_file[MAX_BUF_SIZE] = {0};
1856
1857 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1858 return RETURN_ERR;
1859
1860 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1861 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1862
1863 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1864 if (strlen(buf) == 0)
1865 {
1866 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1867 return RETURN_ERR;
1868 }
1869 if(strcmp(buf,"g")==0)
1870 {
1871 wifi_dbg_printf("\nG\n");
1872 *gOnly=TRUE;
1873 *nOnly=FALSE;
1874 *acOnly=FALSE;
1875 }
1876 else if(strcmp(buf,"n")==0)
1877 {
1878 wifi_dbg_printf("\nN\n");
1879 *gOnly=FALSE;
1880 *nOnly=TRUE;
1881 *acOnly=FALSE;
1882 }
1883 else if(strcmp(buf,"ac")==0)
1884 {
1885 wifi_dbg_printf("\nac\n");
1886 *gOnly=FALSE;
1887 *nOnly=FALSE;
1888 *acOnly=TRUE;
1889 }
1890 /* hostapd-5G.conf has "a" as hw_mode */
1891 else if(strcmp(buf,"a")==0)
1892 {
1893 wifi_dbg_printf("\na\n");
1894 *gOnly=FALSE;
1895 *nOnly=FALSE;
1896 *acOnly=FALSE;
1897 }
1898 else
1899 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1900
1901 //for a,n mode
1902 if(radioIndex == 1)
1903 {
1904 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1905 if(strcmp(buf,"1")==0)
1906 {
1907 strncpy(output_string, "n", 1);
1908 *nOnly=FALSE;
1909 }
1910 }
1911
1912 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1913 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1914 return RETURN_OK;
1915#endif
1916}
1917
developerdb744382022-09-13 15:34:54 +08001918INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1919{
1920 char cmd[128] = {0};
1921 char buf[64] = {0};
1922 char config_file[64] = {0};
1923 wifi_band band;
1924
1925 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1926 if(NULL == output_string || NULL == pureMode)
1927 return RETURN_ERR;
1928
1929 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001930 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer7c4cd202023-03-01 10:56:29 +08001931 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 +08001932 _syscmd(cmd, buf, sizeof(buf));
1933
1934 band = wifi_index_to_band(radioIndex);
1935 // puremode is a bit map
1936 *pureMode = 0;
1937 if (band == band_2_4) {
1938 strcat(output_string, "b,g");
1939 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1940 if (strstr(buf, "n") != NULL) {
1941 strcat(output_string, ",n");
1942 *pureMode |= WIFI_MODE_N;
1943 }
1944 if (strstr(buf, "ax") != NULL) {
1945 strcat(output_string, ",ax");
1946 *pureMode |= WIFI_MODE_AX;
1947 }
developer7c4cd202023-03-01 10:56:29 +08001948 if (strstr(buf, "be") != NULL) {
1949 strcat(output_string, ",be");
1950 *pureMode |= WIFI_MODE_BE;
1951 }
developerdb744382022-09-13 15:34:54 +08001952 } else if (band == band_5) {
1953 strcat(output_string, "a");
1954 *pureMode |= WIFI_MODE_A;
1955 if (strstr(buf, "n") != NULL) {
1956 strcat(output_string, ",n");
1957 *pureMode |= WIFI_MODE_N;
1958 }
1959 if (strstr(buf, "ac") != NULL) {
1960 strcat(output_string, ",ac");
1961 *pureMode |= WIFI_MODE_AC;
1962 }
1963 if (strstr(buf, "ax") != NULL) {
1964 strcat(output_string, ",ax");
1965 *pureMode |= WIFI_MODE_AX;
1966 }
developer7c4cd202023-03-01 10:56:29 +08001967 if (strstr(buf, "be") != NULL) {
1968 strcat(output_string, ",be");
1969 *pureMode |= WIFI_MODE_BE;
1970 }
developerdb744382022-09-13 15:34:54 +08001971 } else if (band == band_6) {
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 }
1981
1982 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1983 return RETURN_OK;
1984}
1985
1986// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001987INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1988{
1989 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1990 if (strcmp (channelMode,"11A") == 0)
1991 {
1992 writeBandWidth(radioIndex,"20MHz");
1993 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1994 printf("\nChannel Mode is 802.11a (5GHz)\n");
1995 }
1996 else if (strcmp (channelMode,"11NAHT20") == 0)
1997 {
1998 writeBandWidth(radioIndex,"20MHz");
1999 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2000 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2001 }
2002 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2003 {
2004 writeBandWidth(radioIndex,"40MHz");
2005 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2006 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2007 }
2008 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2009 {
2010 writeBandWidth(radioIndex,"40MHz");
2011 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2012 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2013 }
2014 else if (strcmp (channelMode,"11ACVHT20") == 0)
2015 {
2016 writeBandWidth(radioIndex,"20MHz");
2017 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2018 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2019 }
2020 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2021 {
2022 writeBandWidth(radioIndex,"40MHz");
2023 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2024 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2025 }
2026 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2027 {
2028 writeBandWidth(radioIndex,"40MHz");
2029 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2030 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2031 }
2032 else if (strcmp (channelMode,"11ACVHT80") == 0)
2033 {
2034 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2035 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2036 }
2037 else if (strcmp (channelMode,"11ACVHT160") == 0)
2038 {
2039 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2040 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2041 }
2042 else if (strcmp (channelMode,"11B") == 0)
2043 {
2044 writeBandWidth(radioIndex,"20MHz");
2045 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2046 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2047 }
2048 else if (strcmp (channelMode,"11G") == 0)
2049 {
2050 writeBandWidth(radioIndex,"20MHz");
2051 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2052 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2053 }
2054 else if (strcmp (channelMode,"11NGHT20") == 0)
2055 {
2056 writeBandWidth(radioIndex,"20MHz");
2057 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2058 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2059 }
2060 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2061 {
2062 writeBandWidth(radioIndex,"40MHz");
2063 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2064 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2065 }
2066 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2067 {
2068 writeBandWidth(radioIndex,"40MHz");
2069 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2070 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2071 }
2072 else
2073 {
2074 return RETURN_ERR;
2075 }
2076 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2077
2078 return RETURN_OK;
2079}
2080
developerdb744382022-09-13 15:34:54 +08002081// Set the radio operating mode, and pure mode flag.
2082INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2083{
developer7c4cd202023-03-01 10:56:29 +08002084 int num_hostapd_support_mode = 4; // n, ac, ax, be
developerdb744382022-09-13 15:34:54 +08002085 struct params list[num_hostapd_support_mode];
2086 char config_file[64] = {0};
2087 char bandwidth[16] = {0};
developer7c4cd202023-03-01 10:56:29 +08002088 char supported_mode[32] = {0};
developerdb744382022-09-13 15:34:54 +08002089 int mode_check_bit = 1 << 3; // n mode
developer7c4cd202023-03-01 10:56:29 +08002090 bool eht_support = FALSE;
developerdb744382022-09-13 15:34:54 +08002091
2092 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2093 // Set radio mode
2094 list[0].name = "ieee80211n";
2095 list[1].name = "ieee80211ac";
2096 list[2].name = "ieee80211ax";
developer7c4cd202023-03-01 10:56:29 +08002097 list[3].name = "ieee80211be";
developerdb744382022-09-13 15:34:54 +08002098 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2099
2100 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002101 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002102 list[0].value = "1";
2103 else
2104 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002105 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002106 list[1].value = "1";
2107 else
2108 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002109 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002110 list[2].value = "1";
2111 else
2112 list[2].value = "0";
developer7c4cd202023-03-01 10:56:29 +08002113 if (pureMode & WIFI_MODE_BE)
2114 list[3].value = "1";
2115 else
2116 list[3].value = "0";
2117
2118 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2119 if (strstr(supported_mode, "be") != NULL)
2120 eht_support = TRUE;
2121
2122 if (eht_support)
2123 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2124 else
2125 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode-1);
developerdb744382022-09-13 15:34:54 +08002126
2127 if (channelMode == NULL || strlen(channelMode) == 0)
2128 return RETURN_OK;
2129 // Set bandwidth
2130 if (strstr(channelMode, "40") != NULL)
2131 strcpy(bandwidth, "40MHz");
2132 else if (strstr(channelMode, "80") != NULL)
2133 strcpy(bandwidth, "80MHz");
2134 else if (strstr(channelMode, "160") != NULL)
2135 strcpy(bandwidth, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002136 else if (strstr(channelMode, "320") != NULL)
2137 strcpy(bandwidth, "320MHz");
developerdb744382022-09-13 15:34:54 +08002138 else // 11A, 11B, 11G....
2139 strcpy(bandwidth, "20MHz");
2140
2141 writeBandWidth(radioIndex, bandwidth);
2142 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2143
2144 wifi_reloadAp(radioIndex);
2145 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2146
2147 return RETURN_OK;
2148}
2149
developer1d12ebf2022-10-04 15:13:38 +08002150INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2151
2152 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002153 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002154 struct params params = {0};
2155 wifi_band band = band_invalid;
2156
2157 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2158
2159 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002160
2161 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002162 return RETURN_ERR;
2163 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2164 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002165 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2166 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002167
2168 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2169 params.name = "hw_mode";
2170 params.value = hw_mode;
2171 wifi_hostapdWrite(config_file, &params, 1);
2172 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2173
developeref938762022-10-19 17:21:01 +08002174 if (band == band_2_4) {
2175 if (strncmp(hw_mode, "b", 1) == 0) {
2176 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2177 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2178 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2179 snprintf(buf, sizeof(buf), "%s", "1,2");
2180 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2181 } else {
2182 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2183
2184 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2185 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2186 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2187 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2188 }
2189 }
2190
developer1d12ebf2022-10-04 15:13:38 +08002191 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2192 return RETURN_OK;
2193}
2194
developere8988ba2022-10-18 17:42:30 +08002195INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2196{
2197 char config_file[64] = {0};
2198 struct params params = {0};
2199 wifi_band band = band_invalid;
2200
2201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2202
2203 band = wifi_index_to_band(radioIndex);
2204
2205 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2206 params.name = "noscan";
2207 params.value = noscan;
2208 wifi_hostapdWrite(config_file, &params, 1);
2209 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2210
2211 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2212 return RETURN_OK;
2213}
2214
developer06a01d92022-09-07 16:32:39 +08002215//Get the list of supported channel. eg: "1-11"
2216//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.
2217INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2218{
developer6318ed52022-09-13 15:17:58 +08002219 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002220 if (NULL == output_string)
2221 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002222 char cmd[256] = {0};
2223 char buf[128] = {0};
2224 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002225 int phyId = 0;
2226
developer6318ed52022-09-13 15:17:58 +08002227 // Parse possible channel number and separate them with commas.
2228 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002229 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002230 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002231 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002232 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer6318ed52022-09-13 15:17:58 +08002233 else
developer033b37b2022-10-18 11:27:46 +08002234 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar\\|no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer6318ed52022-09-13 15:17:58 +08002235
2236 _syscmd(cmd,buf,sizeof(buf));
2237 strncpy(output_string, buf, sizeof(buf));
2238
2239 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2240 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002241}
2242
2243//Get the list for used channel. eg: "1,6,9,11"
2244//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.
2245INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2246{
developerd946fd62022-12-08 18:03:28 +08002247 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002248 char cmd[128] = {0};
2249 char buf[128] = {0};
2250 char config_file[64] = {0};
2251 int channel = 0;
2252 int freq = 0;
2253 int bandwidth = 0;
2254 int center_freq = 0;
2255 int center_channel = 0;
2256 int channel_delta = 0;
2257 wifi_band band = band_invalid;
2258
2259 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2260
developer06a01d92022-09-07 16:32:39 +08002261 if (NULL == output_string)
2262 return RETURN_ERR;
2263
developerac6f1142022-12-20 19:26:35 +08002264 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002265 return RETURN_ERR;
2266 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002267 _syscmd(cmd, buf, sizeof(buf));
2268 if (strlen(buf) == 0) {
2269 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2270 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002271 }
developerf5745ee2022-10-05 16:09:53 +08002272 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2273
2274 if (bandwidth == 20) {
2275 snprintf(output_string, 256, "%d", channel);
2276 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002277 }
developerf5745ee2022-10-05 16:09:53 +08002278
2279 center_channel = ieee80211_frequency_to_channel(center_freq);
2280
2281 band = wifi_index_to_band(radioIndex);
2282 if (band == band_2_4 && bandwidth == 40) {
2283 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2284 memset(buf, 0, sizeof(buf));
2285 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2286
developerf22724d2022-12-22 17:24:14 +08002287 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002288 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002289 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002290 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2291 } else {
2292 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2293 return RETURN_ERR;
2294 }
2295 } else if (band == band_5 || band == band_6){
2296 // 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 +08002297 // 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 +08002298 channel_delta = (bandwidth-20)/10;
developer72ec5572023-01-05 16:27:13 +08002299 memset(output_string, 0, 256);
2300 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2301 // If i is not the last channel, we add a comma.
2302 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2303 strncat(output_string, buf, strlen(buf));
2304 }
developerf5745ee2022-10-05 16:09:53 +08002305 } else
2306 return RETURN_ERR;
2307
2308 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002309 return RETURN_OK;
2310}
2311
2312//Get the running channel number
2313INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2314{
developer5b398df2022-11-17 20:39:48 +08002315 char channel_str[16] = {0};
2316 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002317
developer5b398df2022-11-17 20:39:48 +08002318 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002319 return RETURN_ERR;
2320
developer5b398df2022-11-17 20:39:48 +08002321 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2322 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002323
developer5b398df2022-11-17 20:39:48 +08002324 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002325
developer06a01d92022-09-07 16:32:39 +08002326 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002327}
2328
2329
2330INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2331{
2332 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002333 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002334
2335 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2336 if (NULL == output_ulong)
2337 return RETURN_ERR;
2338
developer06a01d92022-09-07 16:32:39 +08002339 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002340 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2341 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002342 _syscmd(cmd,buf,sizeof(buf));
2343 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2344 if (*output_ulong == 0) {
2345 return RETURN_ERR;
2346 }
2347
2348 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2349 return RETURN_OK;
2350}
2351
2352//Storing the previous channel value
2353INT wifi_storeprevchanval(INT radioIndex)
2354{
2355 char buf[256] = {0};
2356 char output[4]={'\0'};
2357 char config_file[MAX_BUF_SIZE] = {0};
2358 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2359 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2360 if(radioIndex == 0)
2361 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2362 else if(radioIndex == 1)
2363 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2364 system(buf);
2365 Radio_flag = FALSE;
2366 return RETURN_OK;
2367}
2368
2369//Set the running channel number
2370INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2371{
developer76989232022-10-04 14:13:19 +08002372 // We only write hostapd config here
2373 char str_channel[8]={0};
2374 char *list_channel;
2375 char config_file[128] = {0};
2376 char possible_channels[256] = {0};
2377 int max_radio_num = 0;
2378 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002379
developer76989232022-10-04 14:13:19 +08002380 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002381
developer76989232022-10-04 14:13:19 +08002382 // Check valid
2383 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002384
developer76989232022-10-04 14:13:19 +08002385 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2386 list_channel = strtok(possible_channels, ",");
2387 while(true)
developer06a01d92022-09-07 16:32:39 +08002388 {
developer76989232022-10-04 14:13:19 +08002389 if(list_channel == NULL) { // input not in the list
2390 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2391 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002392 }
developer76989232022-10-04 14:13:19 +08002393 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2394 break;
2395 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002396 }
2397
developer76989232022-10-04 14:13:19 +08002398 list.name = "channel";
2399 list.value = str_channel;
2400 wifi_getMaxRadioNumber(&max_radio_num);
2401 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002402 {
developer76989232022-10-04 14:13:19 +08002403 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2404 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002405 }
2406
developer76989232022-10-04 14:13:19 +08002407 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002408 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002409}
developer06a01d92022-09-07 16:32:39 +08002410
2411INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2412{
developer7c4cd202023-03-01 10:56:29 +08002413 struct params list[3];
2414 char str_idx[16] = {0};
2415 char supported_mode[32] = {0};
2416 char config_file[64] = {0};
developer76989232022-10-04 14:13:19 +08002417 int max_num_radios = 0;
2418 wifi_band band = band_invalid;
developer7c4cd202023-03-01 10:56:29 +08002419 bool eht_support = FALSE;
developer76989232022-10-04 14:13:19 +08002420
2421 band = wifi_index_to_band(radioIndex);
2422 if (band == band_2_4)
2423 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002424
developer7c4cd202023-03-01 10:56:29 +08002425 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2426 if (strstr(supported_mode, "be") != NULL)
2427 eht_support = TRUE;
2428
developer30423732022-12-01 16:17:49 +08002429 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002430 list[0].name = "vht_oper_centr_freq_seg0_idx";
2431 list[0].value = str_idx;
2432 list[1].name = "he_oper_centr_freq_seg0_idx";
2433 list[1].value = str_idx;
developer7c4cd202023-03-01 10:56:29 +08002434 list[2].name = "eht_oper_centr_freq_seg0_idx";
2435 list[2].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002436
developer76989232022-10-04 14:13:19 +08002437 wifi_getMaxRadioNumber(&max_num_radios);
2438 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002439 {
developer76989232022-10-04 14:13:19 +08002440 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
developer7c4cd202023-03-01 10:56:29 +08002441 if (eht_support)
2442 wifi_hostapdWrite(config_file, list, 3);
developer76989232022-10-04 14:13:19 +08002443 else
2444 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002445 }
2446
2447 return RETURN_OK;
2448}
2449
2450//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2451//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2452INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2453{
2454 //Set to wifi config only. Wait for wifi reset to apply.
2455 char buf[256] = {0};
2456 char str_channel[256] = {0};
2457 int count = 0;
2458 ULONG Value = 0;
2459 FILE *fp = NULL;
2460 if(enable == TRUE)
2461 {
developer06a01d92022-09-07 16:32:39 +08002462 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002463 }
developer5884e982022-10-06 10:52:50 +08002464 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002465}
2466
developer0b246d12022-09-30 15:24:20 +08002467INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2468{
2469 if (output_bool == NULL)
2470 return RETURN_ERR;
2471
2472 *output_bool = TRUE;
2473
2474 return RETURN_OK;
2475}
2476
developer06a01d92022-09-07 16:32:39 +08002477INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2478{
2479 if (NULL == output_bool)
2480 return RETURN_ERR;
2481 *output_bool=FALSE;
2482 return RETURN_OK;
2483}
2484
2485INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2486{
2487 if (NULL == output_bool)
2488 return RETURN_ERR;
2489 *output_bool=FALSE;
2490 return RETURN_OK;
2491}
2492
2493INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2494{
2495 //Set to wifi config only. Wait for wifi reset to apply.
2496 return RETURN_OK;
2497}
2498
2499INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2500{
2501 return RETURN_OK;
2502}
2503
2504INT wifi_factoryResetAP(int apIndex)
2505{
developer838cca92022-10-03 13:19:57 +08002506 char ap_config_file[64] = {0};
2507 char cmd[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002508 char buf[128] = {0};
developer89df4502023-02-16 20:45:02 +08002509 int max_radio_num = 0;
developer838cca92022-10-03 13:19:57 +08002510
developer06a01d92022-09-07 16:32:39 +08002511 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002512
2513 wifi_setApEnable(apIndex, FALSE);
2514 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2515 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
developer72ec5572023-01-05 16:27:13 +08002516 _syscmd(cmd, buf, sizeof(buf));
developer89df4502023-02-16 20:45:02 +08002517 wifi_getMaxRadioNumber(&max_radio_num);
2518 if (apIndex <= max_radio_num) // The ap is default radio interface, we should default up it.
2519 wifi_setApEnable(apIndex, TRUE);
developer838cca92022-10-03 13:19:57 +08002520
developer06a01d92022-09-07 16:32:39 +08002521 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002522
developer06a01d92022-09-07 16:32:39 +08002523 return RETURN_OK;
2524}
2525
2526//To set Band Steering AP group
2527//To-do
2528INT wifi_setBandSteeringApGroup(char *ApGroup)
2529{
2530 return RETURN_OK;
2531}
2532
developer1e5aa162022-09-13 16:06:24 +08002533INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2534{
2535 char config_file[128] = {'\0'};
2536 char buf[128] = {'\0'};
2537
2538 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2539 if (dtimInterval == NULL)
2540 return RETURN_ERR;
2541
2542 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2543 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2544
2545 if (strlen(buf) == 0) {
2546 *dtimInterval = 2;
2547 } else {
2548 *dtimInterval = strtoul(buf, NULL, 10);
2549 }
2550
2551 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2552 return RETURN_OK;
2553}
2554
developer06a01d92022-09-07 16:32:39 +08002555INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2556{
developer5f222492022-09-13 15:21:52 +08002557 struct params params={0};
2558 char config_file[MAX_BUF_SIZE] = {'\0'};
2559 char buf[MAX_BUF_SIZE] = {'\0'};
2560
2561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2562 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002563 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002564 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002565 }
2566
2567 params.name = "dtim_period";
2568 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2569 params.value = buf;
2570
2571 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2572 wifi_hostapdWrite(config_file, &params, 1);
2573 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2574
2575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2576 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002577}
2578
2579//Check if the driver support the Dfs
2580INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2581{
developer78a15382022-11-02 10:57:40 +08002582 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002583 if (NULL == output_bool)
2584 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002585 *output_bool=FALSE;
2586
2587 band = wifi_index_to_band(radioIndex);
2588 if (band == band_5)
2589 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002590 return RETURN_OK;
2591}
2592
2593//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.
2594//The value of this parameter is a comma seperated list of channel number
2595INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2596{
2597 if (NULL == output_pool)
2598 return RETURN_ERR;
2599 if (radioIndex==1)
2600 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2601 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2602
2603 return RETURN_OK;
2604}
2605
2606INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2607{
2608 //Set to wifi config. And apply instantly.
2609 return RETURN_OK;
2610}
2611
2612INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2613{
2614 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2615 return RETURN_ERR;
2616 *output_interval_seconds=1800;
2617 *output_dwell_milliseconds=40;
2618
2619 return RETURN_OK;
2620}
2621
2622INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2623{
2624 //Set to wifi config. And apply instantly.
2625 return RETURN_OK;
2626}
2627
developerbfc18512022-10-05 17:54:28 +08002628INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2629{
2630 if (output_bool == NULL)
2631 return RETURN_ERR;
2632 *output_bool = true;
2633 return RETURN_OK;
2634}
2635
2636INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2637{
2638 return RETURN_OK;
2639}
2640
developer06a01d92022-09-07 16:32:39 +08002641//Get the Dfs enable status
2642INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2643{
developer9964b5b2022-09-13 15:59:34 +08002644 char buf[16] = {0};
2645 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002646
2647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2648
developer30423732022-12-01 16:17:49 +08002649 if (output_bool == NULL)
2650 return RETURN_ERR;
2651
developer9964b5b2022-09-13 15:59:34 +08002652 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002653 f = fopen(DFS_ENABLE_FILE, "r");
2654 if (f != NULL) {
2655 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002656 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002657 *output_bool = FALSE;
2658 fclose(f);
2659 }
2660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002661 return RETURN_OK;
2662}
2663
2664//Set the Dfs enable status
2665INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2666{
developer9964b5b2022-09-13 15:59:34 +08002667 char config_file[128] = {0};
2668 FILE *f = NULL;
2669 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002670
2671 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2672
developer9964b5b2022-09-13 15:59:34 +08002673 f = fopen(DFS_ENABLE_FILE, "w");
2674 if (f == NULL)
2675 return RETURN_ERR;
2676 fprintf(f, "%d", enable);
2677 fclose(f);
2678
2679 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002680 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002681 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2682 wifi_hostapdWrite(config_file, &params, 1);
2683 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2684
2685 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2686
developer9964b5b2022-09-13 15:59:34 +08002687 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002688 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002689}
2690
2691//Check if the driver support the AutoChannelRefreshPeriod
2692INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2693{
2694 if (NULL == output_bool)
2695 return RETURN_ERR;
2696 *output_bool=FALSE; //not support
2697
2698 return RETURN_OK;
2699}
2700
2701//Get the ACS refresh period in seconds
2702INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2703{
2704 if (NULL == output_ulong)
2705 return RETURN_ERR;
2706 *output_ulong=300;
2707
2708 return RETURN_OK;
2709}
2710
2711//Set the ACS refresh period in seconds
2712INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2713{
2714 return RETURN_ERR;
2715}
2716
developer7c4cd202023-03-01 10:56:29 +08002717INT getEHT320ChannelBandwidthSet(int radioIndex, int *BandwidthSet)
2718{
2719 int center_channel = 0;
2720 char config_file[32] = {0};
2721 char buf[32] = {0};
2722
2723 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2724 wifi_hostapdRead(config_file, "eht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2725
2726 center_channel = strtoul(buf, NULL, 10);
2727 center_channel += 1; // Add 1 to become muiltiple of 16
2728 if (center_channel % 64 == 32)
2729 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_1MHZ;
2730 else if (center_channel % 64 == 0)
2731 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_2MHZ;
2732 else
2733 return RETURN_ERR;
2734 return RETURN_OK;
2735}
2736
developer06a01d92022-09-07 16:32:39 +08002737//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2738//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.
2739INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2740{
developer72ec5572023-01-05 16:27:13 +08002741 char buf[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002742 char extchannel[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002743 char config_file[128] = {0};
developer70490032022-09-13 15:45:20 +08002744 BOOL radio_enable = FALSE;
developerfa41b1f2023-01-06 10:25:51 +08002745 wifi_band band;
developer70490032022-09-13 15:45:20 +08002746
2747 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2748
developer06a01d92022-09-07 16:32:39 +08002749 if (NULL == output_string)
2750 return RETURN_ERR;
2751
developer70490032022-09-13 15:45:20 +08002752 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2753 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002754
developer70490032022-09-13 15:45:20 +08002755 if (radio_enable != TRUE)
2756 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002757
developerfa41b1f2023-01-06 10:25:51 +08002758 band = wifi_index_to_band(radioIndex);
developer72ec5572023-01-05 16:27:13 +08002759 if (band == band_2_4) {
developerfa41b1f2023-01-06 10:25:51 +08002760 wifi_getRadioExtChannel(radioIndex, extchannel);
developer72ec5572023-01-05 16:27:13 +08002761 if (strncmp(extchannel, "Auto", 4) == 0) // Auto means that we did not set ht_capab HT40+/-
2762 snprintf(output_string, 64, "20MHz");
2763 else
2764 snprintf(output_string, 64, "40MHz");
2765
2766 } else {
2767 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2768 wifi_hostapdRead(config_file, "he_oper_chwidth", buf, sizeof(buf));
2769 if (strncmp(buf, "0", 1) == 0) { // Check whether we set central channel
2770 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2771 if (strncmp(buf, "0", 1) == 0)
2772 snprintf(output_string, 64, "20MHz");
2773 else
2774 snprintf(output_string, 64, "40MHz");
2775
2776 } else if (strncmp(buf, "1", 1) == 0)
2777 snprintf(output_string, 64, "80MHz");
developer7c4cd202023-03-01 10:56:29 +08002778 else if (strncmp(buf, "2", 1) == 0) {
developer72ec5572023-01-05 16:27:13 +08002779 snprintf(output_string, 64, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002780 wifi_hostapdRead(config_file, "eht_oper_chwidth", buf, sizeof(buf));
2781 if (strncmp(buf, "9", 1) == 0) {
2782 int BandwidthSet = 0;
2783 if (getEHT320ChannelBandwidthSet(radioIndex, &BandwidthSet) != RETURN_OK)
2784 return RETURN_ERR;
2785 if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_1MHZ)
2786 snprintf(output_string, 64, "320-1MHz");
2787 else if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_2MHZ)
2788 snprintf(output_string, 64, "320-2MHz");
2789 }
2790 }
developer06a01d92022-09-07 16:32:39 +08002791 }
developer72ec5572023-01-05 16:27:13 +08002792
developer06a01d92022-09-07 16:32:39 +08002793 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002794
2795 return RETURN_OK;
2796}
2797
2798//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002799INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002800{
developerf7a466e2022-09-29 11:55:56 +08002801 char config_file[128];
2802 char set_value[16];
developer7c4cd202023-03-01 10:56:29 +08002803 char supported_mode[32] = {0};
2804 struct params params[3];
developerf7a466e2022-09-29 11:55:56 +08002805 int max_radio_num = 0;
developer7c4cd202023-03-01 10:56:29 +08002806 bool eht_support = FALSE;
developerf7a466e2022-09-29 11:55:56 +08002807
developer06a01d92022-09-07 16:32:39 +08002808 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002809
developerf7a466e2022-09-29 11:55:56 +08002810 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002811 return RETURN_ERR;
2812
developer7c4cd202023-03-01 10:56:29 +08002813 if(strstr(bandwidth,"160") != NULL || strstr(bandwidth,"320") != NULL)
developerf7a466e2022-09-29 11:55:56 +08002814 strcpy(set_value, "2");
2815 else if(strstr(bandwidth,"80") != NULL)
2816 strcpy(set_value, "1");
2817 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2818 strcpy(set_value, "0");
developer72ec5572023-01-05 16:27:13 +08002819 else if (strstr(bandwidth, "Auto") != NULL)
2820 return RETURN_OK;
2821 else {
developerf7a466e2022-09-29 11:55:56 +08002822 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002823 return RETURN_ERR;
2824 }
2825
developer7c4cd202023-03-01 10:56:29 +08002826 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2827 if (strstr(supported_mode, "be") != NULL)
2828 eht_support = TRUE;
2829
developerf7a466e2022-09-29 11:55:56 +08002830 params[0].name = "vht_oper_chwidth";
2831 params[0].value = set_value;
2832 params[1].name = "he_oper_chwidth";
2833 params[1].value = set_value;
developer7c4cd202023-03-01 10:56:29 +08002834 params[2].name = "eht_oper_chwidth";
2835 if (strstr(bandwidth,"320") != NULL) // We set oper_chwidth to 9 for EHT320
2836 params[2].value = "9";
2837 else
2838 params[2].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002839
developerf7a466e2022-09-29 11:55:56 +08002840 wifi_getMaxRadioNumber(&max_radio_num);
2841 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002842 {
developer7c4cd202023-03-01 10:56:29 +08002843 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2844 if (eht_support == TRUE)
2845 wifi_hostapdWrite(config_file, params, 3);
2846 else
2847 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002848 }
2849
2850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2851 return RETURN_OK;
2852}
2853
2854//Getting current radio extension channel
2855INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2856{
2857 CHAR buf[150] = {0};
2858 CHAR cmd[150] = {0};
2859 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2860 _syscmd(cmd, buf, sizeof(buf));
2861 if(NULL != strstr(buf,"HT40+"))
2862 strcpy(Value,"AboveControlChannel");
2863 else if(NULL != strstr(buf,"HT40-"))
2864 strcpy(Value,"BelowControlChannel");
2865 return RETURN_OK;
2866}
2867
2868//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2869//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.
2870INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2871{
developerfa41b1f2023-01-06 10:25:51 +08002872 char config_file[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002873 wifi_band band;
developerfa41b1f2023-01-06 10:25:51 +08002874
2875 if (output_string == NULL)
developer06a01d92022-09-07 16:32:39 +08002876 return RETURN_ERR;
2877
developerfa41b1f2023-01-06 10:25:51 +08002878 band = wifi_index_to_band(radioIndex);
2879 if (band == band_invalid)
developer06a01d92022-09-07 16:32:39 +08002880 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002881
2882 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2883
2884 snprintf(output_string, 64, "Auto");
developer72ec5572023-01-05 16:27:13 +08002885 wifi_halgetRadioExtChannel(config_file, output_string);
developer06a01d92022-09-07 16:32:39 +08002886
2887 return RETURN_OK;
2888}
2889
developer57fa24a2023-03-15 17:25:07 +08002890// This function handle 20MHz to remove HT40+/- in hostapd config, other bandwidths are handled in wifi_setRadioExtChannel.
2891INT wifi_RemoveRadioExtChannel(INT radioIndex, CHAR *ext_str)
2892{
2893 struct params params={0};
2894 char config_file[64] = {0};
2895 char ht_capab[128]={0};
2896 char buf[128] = {0};
2897 char cmd[128] = {0};
2898 int max_radio_num =0;
2899 bool stbcEnable = FALSE;
2900
2901 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2902 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2903 _syscmd(cmd, buf, sizeof(buf));
2904 if (strlen(buf) != 0)
2905 stbcEnable = TRUE;
2906
2907 strcpy(ht_capab, HOSTAPD_HT_CAPAB);
2908 params.value = ht_capab;
2909 params.name = "ht_capab";
2910
2911 wifi_getMaxRadioNumber(&max_radio_num);
2912 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2913 {
2914 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2915 wifi_hostapdWrite(config_file, &params, 1);
developer57fa24a2023-03-15 17:25:07 +08002916 }
developer8d7d0862023-05-18 16:50:23 +08002917 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer57fa24a2023-03-15 17:25:07 +08002918 return RETURN_OK;
2919}
2920
developer06a01d92022-09-07 16:32:39 +08002921//Set the extension channel.
2922INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer72ec5572023-01-05 16:27:13 +08002923{
developer06a01d92022-09-07 16:32:39 +08002924 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfa41b1f2023-01-06 10:25:51 +08002925 struct params params={0};
2926 char config_file[64] = {0};
2927 char ext_channel[128]={0};
2928 char buf[128] = {0};
2929 char cmd[128] = {0};
2930 int max_radio_num =0, ret = 0, bandwidth = 0;
developer72ec5572023-01-05 16:27:13 +08002931 unsigned long channel = 0;
developerfa41b1f2023-01-06 10:25:51 +08002932 bool stbcEnable = FALSE;
developer06a01d92022-09-07 16:32:39 +08002933 params.name = "ht_capab";
developerfa41b1f2023-01-06 10:25:51 +08002934 wifi_band band;
2935
2936 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2937 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2938 _syscmd(cmd, buf, sizeof(buf));
2939 if (strlen(buf) != 0)
2940 stbcEnable = TRUE;
developer57fa24a2023-03-15 17:25:07 +08002941
2942 // readBandWidth get empty file will return error, that means we don't set new bandwidth
2943 if (readBandWidth(radioIndex, buf) != RETURN_OK) {
2944 // Get current bandwidth
2945 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2946 return RETURN_ERR;
2947 }
developerfa41b1f2023-01-06 10:25:51 +08002948 bandwidth = strtol(buf, NULL, 10);
2949 // TDK expected to get error with 20MHz
developer57fa24a2023-03-15 17:25:07 +08002950 // we handle 20MHz in function wifi_RemoveRadioExtChannel().
developerfa41b1f2023-01-06 10:25:51 +08002951 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
2952 return RETURN_ERR;
2953
2954 band = wifi_index_to_band(radioIndex);
2955 if (band == band_invalid)
2956 return RETURN_ERR;
2957
2958 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
2959 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002960
developer72ec5572023-01-05 16:27:13 +08002961 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
2962 ret = util_get_sec_chan_offset(channel, buf);
2963 if (ret == -EINVAL)
2964 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002965
2966 if(NULL!= strstr(string,"Above")) {
developer72ec5572023-01-05 16:27:13 +08002967 if ((band == band_2_4 && channel > 9) || (band == band_5 && ret == -1))
2968 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002969 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developerfa41b1f2023-01-06 10:25:51 +08002970 } else if(NULL!= strstr(string,"Below")) {
developer72ec5572023-01-05 16:27:13 +08002971 if ((band == band_2_4 && channel < 5) || (band == band_5 && ret == 1))
2972 return RETURN_OK;
developer033b37b2022-10-18 11:27:46 +08002973 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developerfa41b1f2023-01-06 10:25:51 +08002974 } else {
developer57fa24a2023-03-15 17:25:07 +08002975 fprintf(stderr, "%s: unknow extchannel %s\n", __func__, string);
2976 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002977 }
developer06a01d92022-09-07 16:32:39 +08002978
2979 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002980
2981 wifi_getMaxRadioNumber(&max_radio_num);
2982 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002983 {
developer033b37b2022-10-18 11:27:46 +08002984 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002985 wifi_hostapdWrite(config_file, &params, 1);
2986 }
developer8d7d0862023-05-18 16:50:23 +08002987 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
developer06a01d92022-09-07 16:32:39 +08002988
2989 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2990 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2991 return RETURN_OK;
2992}
2993
2994//Get the guard interval value. eg "400nsec" or "800nsec"
2995//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.
2996INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2997{
developer454b9462022-09-13 15:29:16 +08002998 wifi_guard_interval_t GI;
2999
3000 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3001
3002 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08003003 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08003004
3005 if (GI == wifi_guard_interval_400)
3006 strcpy(output_string, "400nsec");
3007 else if (GI == wifi_guard_interval_800)
3008 strcpy(output_string, "800nsec");
3009 else if (GI == wifi_guard_interval_1600)
3010 strcpy(output_string, "1600nsec");
3011 else if (GI == wifi_guard_interval_3200)
3012 strcpy(output_string, "3200nsec");
3013 else
developer78a15382022-11-02 10:57:40 +08003014 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08003015
developer454b9462022-09-13 15:29:16 +08003016 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003017 return RETURN_OK;
3018}
3019
3020//Set the guard interval value.
3021INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3022{
developer454b9462022-09-13 15:29:16 +08003023 wifi_guard_interval_t GI;
3024 int ret = 0;
3025
3026 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3027
3028 if (strcmp(string, "400nsec") == 0)
3029 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08003030 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08003031 GI = wifi_guard_interval_800;
3032 else if (strcmp(string , "1600nsec") == 0)
3033 GI = wifi_guard_interval_1600;
3034 else if (strcmp(string , "3200nsec") == 0)
3035 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08003036 else
3037 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08003038
3039 ret = wifi_setGuardInterval(radioIndex, GI);
3040
3041 if (ret == RETURN_ERR) {
3042 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3043 return RETURN_ERR;
3044 }
3045
3046 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3047 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003048}
3049
3050//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3051INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3052{
developerf49437e2022-09-29 19:58:21 +08003053 char buf[32]={0};
3054 char mcs_file[64] = {0};
3055 char cmd[64] = {0};
3056 int mode_bitmap = 0;
3057
3058 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3059 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08003060 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08003061 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3062
3063 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3064 _syscmd(cmd, buf, sizeof(buf));
3065 if (strlen(buf) > 0)
3066 *output_int = strtol(buf, NULL, 10);
3067 else {
3068 // output the max MCS for the current radio mode
3069 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3070 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3071 return RETURN_ERR;
3072 }
3073 if (mode_bitmap & WIFI_MODE_AX) {
3074 *output_int = 11;
3075 } else if (mode_bitmap & WIFI_MODE_AC) {
3076 *output_int = 9;
3077 } else if (mode_bitmap & WIFI_MODE_N) {
3078 *output_int = 7;
3079 }
3080 }
3081 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003082
3083 return RETURN_OK;
3084}
3085
3086//Set the Modulation Coding Scheme index
3087INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3088{
developerf49437e2022-09-29 19:58:21 +08003089 // 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).
3090 char config_file[64] = {0};
3091 char set_value[16] = {0};
3092 char mcs_file[32] = {0};
3093 wifi_band band = band_invalid;
3094 struct params set_config = {0};
3095 FILE *f = NULL;
3096
3097 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3098
3099 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3100
developer78a15382022-11-02 10:57:40 +08003101 // -1 means auto
3102 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08003103 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3104 return RETURN_ERR;
3105 }
3106
developer78a15382022-11-02 10:57:40 +08003107 if (MCS > 9 || MCS == -1)
3108 strcpy(set_value, "2");
3109 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08003110 strcpy(set_value, "1");
3111 else
developer78a15382022-11-02 10:57:40 +08003112 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08003113
3114 set_config.name = "he_basic_mcs_nss_set";
3115 set_config.value = set_value;
3116
3117 wifi_hostapdWrite(config_file, &set_config, 1);
3118 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3119
3120 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3121 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3122 f = fopen(mcs_file, "w");
3123 if (f == NULL) {
3124 fprintf(stderr, "%s: fopen failed\n", __func__);
3125 return RETURN_ERR;
3126 }
3127 fprintf(f, "%d", MCS);
3128 fclose(f);
3129
3130 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3131 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003132}
3133
3134//Get supported Transmit Power list, eg : "0,25,50,75,100"
3135//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.
3136INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3137{
3138 if (NULL == output_list)
3139 return RETURN_ERR;
developer5c97d532023-09-28 11:19:30 +08003140 snprintf(output_list, 64,"0,12,25,50,75,100");
developer06a01d92022-09-07 16:32:39 +08003141 return RETURN_OK;
3142}
3143
developer5c97d532023-09-28 11:19:30 +08003144// Get current Transmit Power in percent
developer06a01d92022-09-07 16:32:39 +08003145INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3146{
developer5c97d532023-09-28 11:19:30 +08003147 char cmd[128]={'\0'};
3148 char buf[128]={'\0'};
3149 int phyIndex = -1;
3150 bool enabled = false;
3151 int cur_tx_dbm = 0;
3152
developera5005b62022-09-13 15:43:35 +08003153 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003154
developera5005b62022-09-13 15:43:35 +08003155 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003156 return RETURN_ERR;
3157
developer5c97d532023-09-28 11:19:30 +08003158 phyIndex = radio_index_to_phy(radioIndex);
3159
3160 // Get the maximum tx power of the device
3161 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
3162 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developer06a01d92022-09-07 16:32:39 +08003163 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003164 if (strcmp(buf, "enable") == 0)
3165 enabled = true;
developer06a01d92022-09-07 16:32:39 +08003166
developer5c97d532023-09-28 11:19:30 +08003167 if (!enabled) {
3168 *output_ulong = 100;
3169 return RETURN_OK;
3170 }
developera5005b62022-09-13 15:43:35 +08003171
developer5c97d532023-09-28 11:19:30 +08003172 memset(cmd, 0, sizeof(cmd));
3173 memset(buf, 0, sizeof(buf));
3174 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
3175 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
3176 _syscmd(cmd, buf, sizeof(buf));
3177 cur_tx_dbm = strtol(buf, NULL, 10);
3178
3179 switch (cur_tx_dbm) {
3180 case 0:
3181 *output_ulong = 100; // range 91-100
3182 break;
3183 case 1:
3184 *output_ulong = 75; // range 61-90
3185 break;
3186 case 3:
3187 *output_ulong = 50; // range 31-60
3188 break;
3189 case 6:
3190 *output_ulong = 25; // range 16-30
3191 break;
3192 case 9:
3193 *output_ulong = 12; // range 10-15
3194 break;
3195 case 12:
3196 *output_ulong = 6; // range 1-9
3197 break;
3198 default:
3199 *output_ulong = 100; // 0
3200 }
3201
developer06a01d92022-09-07 16:32:39 +08003202 return RETURN_OK;
3203}
3204
developer5c97d532023-09-28 11:19:30 +08003205// TransmitPower: the the percentage relative to the maximum power,
3206// only support 0,12,25,50,75,100, But 0 means disable Power limit,
3207// so the power is 100%
developer06a01d92022-09-07 16:32:39 +08003208INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3209{
developerd946fd62022-12-08 18:03:28 +08003210 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003211 char *support;
developer06a01d92022-09-07 16:32:39 +08003212 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003213 char buf[128]={0};
3214 char txpower_str[64] = {0};
developer033b37b2022-10-18 11:27:46 +08003215 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003216
3217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003218
developerac6f1142022-12-20 19:26:35 +08003219 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003220 return RETURN_ERR;
developera5005b62022-09-13 15:43:35 +08003221
3222 // Get the Tx power supported list and check that is the input in the list
3223 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3224 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3225 support = strtok(buf, ",");
3226 while(true)
3227 {
3228 if(support == NULL) { // input not in the list
3229 wifi_dbg_printf("Input value is invalid.\n");
3230 return RETURN_ERR;
3231 }
3232 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3233 break;
3234 }
3235 support = strtok(NULL, ",");
3236 }
developer5c97d532023-09-28 11:19:30 +08003237
developer033b37b2022-10-18 11:27:46 +08003238 phyId = radio_index_to_phy(radioIndex);
developer5c97d532023-09-28 11:19:30 +08003239 snprintf(cmd, sizeof(cmd), "echo %lu > /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_level",
3240 TransmitPower, phyId);
developera5005b62022-09-13 15:43:35 +08003241 _syscmd(cmd, buf, sizeof(buf));
developer5c97d532023-09-28 11:19:30 +08003242
developera5005b62022-09-13 15:43:35 +08003243 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003244
3245 return RETURN_OK;
3246}
3247
3248//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3249INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3250{
3251 if (NULL == Supported)
3252 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003253 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003254
3255 return RETURN_OK;
3256}
3257
3258//Get 80211h feature enable
3259INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3260{
developer3885fec2022-09-13 15:13:47 +08003261 char buf[64]={'\0'};
3262 char config_file[64] = {'\0'};
3263
3264 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3265 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003266 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003267
3268 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3269 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003270
developer3885fec2022-09-13 15:13:47 +08003271 if (strncmp(buf, "1", 1) == 0)
3272 *enable = TRUE;
3273 else
3274 *enable = FALSE;
3275
3276 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003277 return RETURN_OK;
3278}
3279
3280//Set 80211h feature enable
3281INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3282{
developer3885fec2022-09-13 15:13:47 +08003283 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3284 struct params params={'\0'};
3285 char config_file[MAX_BUF_SIZE] = {0};
3286
3287 params.name = "ieee80211h";
3288
3289 if (enable) {
3290 params.value = "1";
3291 } else {
3292 params.value = "0";
3293 }
3294
3295 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3296 wifi_hostapdWrite(config_file, &params, 1);
3297
3298 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3299 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3300 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003301}
3302
3303//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.
3304INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3305{
3306 if (NULL == output)
3307 return RETURN_ERR;
3308 *output=100;
3309
3310 return RETURN_OK;
3311}
3312
3313//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.
3314INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3315{
3316 if (NULL == output)
3317 return RETURN_ERR;
3318 *output = -99;
3319
3320 return RETURN_OK;
3321}
3322
3323INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3324{
3325 return RETURN_ERR;
3326}
3327
3328
3329//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3330INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3331{
developerd946fd62022-12-08 18:03:28 +08003332 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003333 char cmd[MAX_BUF_SIZE]={'\0'};
3334 char buf[MAX_CMD_SIZE]={'\0'};
3335
3336 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3337 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003338 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003339
developerac6f1142022-12-20 19:26:35 +08003340 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003341 return RETURN_ERR;
3342 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 +08003343 _syscmd(cmd, buf, sizeof(buf));
3344 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003345
developer5f222492022-09-13 15:21:52 +08003346 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003347 return RETURN_OK;
3348}
3349
3350INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3351{
developer5f222492022-09-13 15:21:52 +08003352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3353 struct params params={'\0'};
3354 char buf[MAX_BUF_SIZE] = {'\0'};
3355 char config_file[MAX_BUF_SIZE] = {'\0'};
3356
developer5b398df2022-11-17 20:39:48 +08003357 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3358 return RETURN_ERR;
3359
developer5f222492022-09-13 15:21:52 +08003360 params.name = "beacon_int";
3361 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3362 params.value = buf;
3363
3364 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3365 wifi_hostapdWrite(config_file, &params, 1);
3366
3367 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3368 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3369 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003370}
3371
3372//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.
3373INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3374{
developer06a01d92022-09-07 16:32:39 +08003375 //TODO: need to revisit below implementation
3376 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003377 char temp_output[128] = {0};
3378 char temp_TransmitRates[64] = {0};
3379 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003380
3381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3382 if (NULL == output)
3383 return RETURN_ERR;
3384 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003385 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3386
3387 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3388 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3389 } else {
3390 temp = strtok(temp_TransmitRates," ");
3391 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003392 {
developere9d0abd2022-09-13 15:40:57 +08003393 // Convert 100 kbps to Mbps
3394 temp[strlen(temp)-1]=0;
3395 if((temp[0]=='5') && (temp[1]=='\0'))
3396 {
3397 temp="5.5";
3398 }
3399 strcat(temp_output,temp);
3400 temp = strtok(NULL," ");
3401 if(temp!=NULL)
3402 {
3403 strcat(temp_output,",");
3404 }
developer06a01d92022-09-07 16:32:39 +08003405 }
developere9d0abd2022-09-13 15:40:57 +08003406 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003407 }
developer06a01d92022-09-07 16:32:39 +08003408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003409 return RETURN_OK;
3410}
3411
3412INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3413{
3414 char *temp;
3415 char temp1[128];
3416 char temp_output[128];
3417 char temp_TransmitRates[128];
3418 char set[128];
3419 char sub_set[128];
3420 int set_count=0,subset_count=0;
3421 int set_index=0,subset_index=0;
3422 char *token;
3423 int flag=0, i=0;
3424 struct params params={'\0'};
3425 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003426 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003427
3428 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3429 if(NULL == TransmitRates)
3430 return RETURN_ERR;
3431 strcpy(sub_set,TransmitRates);
3432
3433 //Allow only supported Data transmit rate to be set
3434 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3435 token = strtok(sub_set,",");
3436 while( token != NULL ) /* split the basic rate to be set, by comma */
3437 {
3438 sub_set[subset_count]=atoi(token);
3439 subset_count++;
3440 token=strtok(NULL,",");
3441 }
3442 token=strtok(set,",");
3443 while(token!=NULL) /* split the supported rate by comma */
3444 {
3445 set[set_count]=atoi(token);
3446 set_count++;
3447 token=strtok(NULL,",");
3448 }
3449 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3450 {
3451 for(set_index=0;set_index < set_count;set_index++)
3452 {
3453 flag=0;
3454 if(sub_set[subset_index]==set[set_index])
3455 break;
3456 else
3457 flag=1; /* No match found */
3458 }
3459 if(flag==1)
3460 return RETURN_ERR; //If value not found return Error
3461 }
3462 strcpy(temp_TransmitRates,TransmitRates);
3463
3464 for(i=0;i<strlen(temp_TransmitRates);i++)
3465 {
3466 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003467 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003468 {
3469 continue;
3470 }
3471 else
3472 {
3473 return RETURN_ERR;
3474 }
3475 }
3476 strcpy(temp_output,"");
3477 temp = strtok(temp_TransmitRates,",");
3478 while(temp!=NULL)
3479 {
3480 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003481 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003482 {
developeref938762022-10-19 17:21:01 +08003483 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003484 {
3485 return RETURN_ERR;
3486 }
3487 }
3488
3489 if(strcmp(temp,"5.5")==0)
3490 {
3491 strcpy(temp1,"55");
3492 }
3493 else
3494 {
3495 strcat(temp1,"0");
3496 }
3497 strcat(temp_output,temp1);
3498 temp = strtok(NULL,",");
3499 if(temp!=NULL)
3500 {
3501 strcat(temp_output," ");
3502 }
3503 }
3504 strcpy(TransmitRates,temp_output);
3505
3506 params.name= "basic_rates";
3507 params.value =TransmitRates;
3508
3509 wifi_dbg_printf("\n%s:",__func__);
3510 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3511 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3512 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3513 wifi_hostapdWrite(config_file,&params,1);
3514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3515 return RETURN_OK;
3516}
3517
3518//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003519INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003520{
3521 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3522 FILE *fp = NULL;
3523 char path[256] = {0}, output_string[256] = {0};
3524 int count = 0;
3525 char *interface = NULL;
3526
3527 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3528 if (fp == NULL)
3529 {
3530 printf("Failed to run command in Function %s\n", __FUNCTION__);
3531 return RETURN_ERR;
3532 }
3533 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3534 {
3535 interface = strchr(path, '=');
3536
3537 if (interface != NULL)
3538 {
3539 strcpy(output_string, interface + 1);
developer72ec5572023-01-05 16:27:13 +08003540 for (count = 0; output_string[count] != '\n' && output_string[count] != '\0'; count++)
developer06a01d92022-09-07 16:32:39 +08003541 interface_name[count] = output_string[count];
3542
3543 interface_name[count] = '\0';
3544 }
3545 }
3546 pclose(fp);
3547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3548 return RETURN_OK;
3549}
3550
3551INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3552{
3553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3554 output_struct->radio_BytesSent = 0;
3555 output_struct->radio_BytesReceived = 0;
3556 output_struct->radio_PacketsSent = 0;
3557 output_struct->radio_PacketsReceived = 0;
3558 output_struct->radio_ErrorsSent = 0;
3559 output_struct->radio_ErrorsReceived = 0;
3560 output_struct->radio_DiscardPacketsSent = 0;
3561 output_struct->radio_DiscardPacketsReceived = 0;
3562 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3563 return RETURN_OK;
3564}
3565
developer7c4c40e2023-10-25 10:17:04 +08003566static ULONG File_ReadValuefromMultiLine(CHAR *file)
3567{
3568 FILE *fp = NULL;
3569 char buf[MAX_BUF_SIZE] = {0};
3570 int buf_len = 0;
3571 ULONG sum = 0, num = 0;
3572
3573 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3574 fp = popen(file,"r");
3575 if(fp == NULL)
3576 return 0;
3577
3578 while(fgets(buf,MAX_BUF_SIZE,fp) != NULL)
3579 {
3580 buf_len = strlen(buf);
3581 if(buf_len) {
3582 num= strtoul(buf, NULL, 10);
3583 sum += num;
3584 WIFI_ENTRY_EXIT_DEBUG("%s sum=%ld num=%ld\n", __func__, sum, num);
3585 memset(buf, 0, MAX_BUF_SIZE);
3586 }
3587 }
3588
3589 pclose(fp);
3590 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3591
3592 return sum;
3593}
developer06a01d92022-09-07 16:32:39 +08003594
3595INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3596{
3597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer7c4c40e2023-10-25 10:17:04 +08003598 CHAR buf[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08003599 FILE *fp = NULL;
3600
3601 if (ifname == NULL || strlen(ifname) <= 1)
3602 return RETURN_OK;
3603
developer7c4c40e2023-10-25 10:17:04 +08003604 snprintf(buf, sizeof(buf), "iw dev %s station dump > /tmp/Radio_Stats.txt", ifname);
developer06a01d92022-09-07 16:32:39 +08003605 system(buf);
3606
3607 fp = fopen("/tmp/Radio_Stats.txt", "r");
3608 if(fp == NULL)
3609 {
3610 printf("/tmp/Radio_Stats.txt not exists \n");
3611 return RETURN_ERR;
3612 }
3613 fclose(fp);
3614
developer7c4c40e2023-10-25 10:17:04 +08003615 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3616 pStats->radio_PacketsReceived = File_ReadValuefromMultiLine(buf);
developer06a01d92022-09-07 16:32:39 +08003617
developer7c4c40e2023-10-25 10:17:04 +08003618 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3619 pStats->radio_PacketsSent = File_ReadValuefromMultiLine(buf);
developer06a01d92022-09-07 16:32:39 +08003620
developer7c4c40e2023-10-25 10:17:04 +08003621 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3622 pStats->radio_BytesReceived = File_ReadValuefromMultiLine(buf);
developer06a01d92022-09-07 16:32:39 +08003623
developer7c4c40e2023-10-25 10:17:04 +08003624 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3625 pStats->radio_BytesSent = File_ReadValuefromMultiLine(buf);
developer06a01d92022-09-07 16:32:39 +08003626
developer7c4c40e2023-10-25 10:17:04 +08003627 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'rx drop misc' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3628 pStats->radio_ErrorsReceived = File_ReadValuefromMultiLine(buf);
developer06a01d92022-09-07 16:32:39 +08003629
developer7c4c40e2023-10-25 10:17:04 +08003630 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3631 pStats->radio_ErrorsSent = File_ReadValuefromMultiLine(buf);
developer06a01d92022-09-07 16:32:39 +08003632
developer7c4c40e2023-10-25 10:17:04 +08003633 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'rx drop misc' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3634 pStats->radio_DiscardPacketsReceived = File_ReadValuefromMultiLine(buf);
developer06a01d92022-09-07 16:32:39 +08003635
developer7c4c40e2023-10-25 10:17:04 +08003636 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3637 pStats->radio_DiscardPacketsSent = File_ReadValuefromMultiLine(buf);
developer06a01d92022-09-07 16:32:39 +08003638
3639 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3640 return RETURN_OK;
3641}
3642
3643INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3644{
3645 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3646 CHAR buf[MAX_CMD_SIZE] = {0};
3647 FILE *fp = NULL;
3648 INT count = 0;
3649
3650 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3651 {
3652 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3653 File_Reading(buf, status);
3654 }
3655 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3656 return RETURN_OK;
3657}
3658
3659//Get detail radio traffic static info
3660INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3661{
3662
3663#if 0
3664 //ifconfig radio_x
3665 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3666 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3667 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3668 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3669
3670 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3671 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3672 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.
3673 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.
3674
3675 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3676 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].
3677 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3678 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.
3679 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
3680 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
3681 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
3682 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
3683 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
3684
3685 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
3686 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
3687 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
3688 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.
3689
3690 return RETURN_OK;
3691#endif
3692
developera91d99f2022-09-29 15:59:10 +08003693 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003694 BOOL iface_status = FALSE;
3695 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer7c4c40e2023-10-25 10:17:04 +08003696 INT max_radio_num = 0, apIndex = 0;
developer06a01d92022-09-07 16:32:39 +08003697
3698 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3699 if (NULL == output_struct)
3700 return RETURN_ERR;
3701
developer7c4c40e2023-10-25 10:17:04 +08003702 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08003703
developer7c4c40e2023-10-25 10:17:04 +08003704 memset(output_struct, 0, sizeof(wifi_radioTrafficStats2_t));
developer06a01d92022-09-07 16:32:39 +08003705
developer7c4c40e2023-10-25 10:17:04 +08003706 for(apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
3707 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
3708 continue;
3709 wifi_getApEnable(radioIndex, &iface_status);
3710
3711 if (iface_status == TRUE)
3712 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3713 else
3714 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003715
developer7c4c40e2023-10-25 10:17:04 +08003716 output_struct->radio_BytesSent += radioTrafficStats.radio_BytesSent;
3717 output_struct->radio_BytesReceived += radioTrafficStats.radio_BytesReceived;
3718 output_struct->radio_PacketsSent += radioTrafficStats.radio_PacketsSent;
3719 output_struct->radio_PacketsReceived += radioTrafficStats.radio_PacketsReceived;
3720 output_struct->radio_ErrorsSent += radioTrafficStats.radio_ErrorsSent;
3721 output_struct->radio_ErrorsReceived += radioTrafficStats.radio_ErrorsReceived;
3722 output_struct->radio_DiscardPacketsSent += radioTrafficStats.radio_DiscardPacketsSent;
3723 output_struct->radio_DiscardPacketsReceived += radioTrafficStats.radio_DiscardPacketsReceived;
3724 }
developer06a01d92022-09-07 16:32:39 +08003725
3726 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3727 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].
3728 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3729 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.
3730 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
3731 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
3732 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
3733 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
3734 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
3735
3736 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
3737 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
3738 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
3739 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.
3740
3741 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3742
3743 return RETURN_OK;
3744}
3745
3746//Set radio traffic static Measureing rules
3747INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3748{
3749 //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
3750 // Else, save the MeasuringRate and MeasuringInterval for future usage
3751
3752 return RETURN_OK;
3753}
3754
3755//To start or stop RadioTrafficStats
3756INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3757{
3758 //zqiu: If the RadioTrafficStats process running
3759 // if(enable)
3760 // return RETURN_OK.
3761 // else
3762 // Stop RadioTrafficStats process
3763 // Else
3764 // if(enable)
3765 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3766 // else
3767 // return RETURN_OK.
3768
3769 return RETURN_OK;
3770}
3771
3772//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
3773INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3774{
3775 //zqiu: Please ignor signalIndex.
3776 if (NULL == SignalLevel)
3777 return RETURN_ERR;
3778 *SignalLevel=(radioIndex==0)?-19:-19;
3779
3780 return RETURN_OK;
3781}
3782
3783//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3784INT wifi_applyRadioSettings(INT radioIndex)
3785{
3786 return RETURN_OK;
3787}
3788
3789//Get the radio index assocated with this SSID entry
3790INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3791{
developer5b398df2022-11-17 20:39:48 +08003792 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003793 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003794 int max_radio_num = 0;
3795 wifi_getMaxRadioNumber(&max_radio_num);
3796 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003797 return RETURN_OK;
3798}
3799
3800//Device.WiFi.SSID.{i}.Enable
3801//Get SSID enable configuration parameters (not the SSID enable status)
3802INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3803{
3804 if (NULL == output_bool)
3805 return RETURN_ERR;
3806
developer06a01d92022-09-07 16:32:39 +08003807 return wifi_getApEnable(ssidIndex, output_bool);
3808}
3809
3810//Device.WiFi.SSID.{i}.Enable
3811//Set SSID enable configuration parameters
3812INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3813{
developer06a01d92022-09-07 16:32:39 +08003814 return wifi_setApEnable(ssidIndex, enable);
3815}
3816
3817//Device.WiFi.SSID.{i}.Status
3818//Get the SSID enable status
3819INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3820{
3821 char cmd[MAX_CMD_SIZE]={0};
3822 char buf[MAX_BUF_SIZE]={0};
3823 BOOL output_bool;
3824
3825 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3826 if (NULL == output_string)
3827 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003828
developer06a01d92022-09-07 16:32:39 +08003829 wifi_getApEnable(ssidIndex,&output_bool);
3830 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3831
3832 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3833 return RETURN_OK;
3834}
3835
3836// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3837INT wifi_getSSIDName(INT apIndex, CHAR *output)
3838{
3839 char config_file[MAX_BUF_SIZE] = {0};
3840
3841 if (NULL == output)
3842 return RETURN_ERR;
3843
3844 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3845 wifi_hostapdRead(config_file,"ssid",output,32);
3846
3847 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3848 return RETURN_OK;
3849}
3850
3851// Set a max 32 byte string and sets an internal variable to the SSID name
3852INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3853{
3854 char str[MAX_BUF_SIZE]={'\0'};
3855 char cmd[MAX_CMD_SIZE]={'\0'};
3856 struct params params;
3857 char config_file[MAX_BUF_SIZE] = {0};
3858
3859 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer89df4502023-02-16 20:45:02 +08003860 if(NULL == ssid_string || strlen(ssid_string) > 32 || strlen(ssid_string) == 0 )
developer06a01d92022-09-07 16:32:39 +08003861 return RETURN_ERR;
3862
3863 params.name = "ssid";
3864 params.value = ssid_string;
3865 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3866 wifi_hostapdWrite(config_file, &params, 1);
3867 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3868 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3869
3870 return RETURN_OK;
3871}
3872
3873//Get the BSSID
3874INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3875{
3876 char cmd[MAX_CMD_SIZE]="";
3877
3878 if (NULL == output_string)
3879 return RETURN_ERR;
3880
3881 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3882 {
developer1d57d002022-10-12 18:03:15 +08003883 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 +08003884 _syscmd(cmd, output_string, 64);
3885 return RETURN_OK;
3886 }
3887 strncpy(output_string, "\0", 1);
3888
3889 return RETURN_ERR;
3890}
3891
3892//Get the MAC address associated with this Wifi SSID
3893INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3894{
3895 wifi_getBaseBSSID(ssidIndex,output_string);
3896 return RETURN_OK;
3897}
3898
3899//Get the basic SSID traffic static info
3900//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3901//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3902INT wifi_applySSIDSettings(INT ssidIndex)
3903{
developerd946fd62022-12-08 18:03:28 +08003904 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003905 BOOL status = false;
3906 char cmd[MAX_CMD_SIZE] = {0};
3907 char buf[MAX_CMD_SIZE] = {0};
3908 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003909 int max_radio_num = 0;
3910 int radioIndex = 0;
3911
3912 wifi_getMaxRadioNumber(&max_radio_num);
3913
3914 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003915
3916 wifi_getApEnable(ssidIndex,&status);
3917 // Do not apply when ssid index is disabled
3918 if (status == false)
3919 return RETURN_OK;
3920
3921 /* Doing full remove and add for ssid Index
3922 * Not all hostapd options are supported with reload
3923 * for example macaddr_acl
3924 */
3925 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3926 return RETURN_ERR;
3927
3928 ret = wifi_setApEnable(ssidIndex,true);
3929
3930 /* Workaround for hostapd issue with multiple bss definitions
3931 * when first created interface will be removed
3932 * then all vaps other vaps on same phy are removed
3933 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003934 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003935 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003936 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08003937 continue;
developer643b28f2023-04-04 10:26:01 +08003938 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003939 _syscmd(cmd, buf, sizeof(buf));
3940 if(*buf == '1')
3941 wifi_setApEnable(apIndex, true);
3942 }
3943
3944 return ret;
3945}
3946
developera3c68b92022-09-13 15:27:29 +08003947struct channels_noise {
3948 int channel;
3949 int noise;
3950};
3951
3952// Return noise array for each channel
3953int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3954{
developerd946fd62022-12-08 18:03:28 +08003955 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003956 FILE *f = NULL;
3957 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003958 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003959 size_t len = 0;
3960 ssize_t read = 0;
3961 int tmp = 0, arr_index = -1;
3962
developerac6f1142022-12-20 19:26:35 +08003963 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003964 return RETURN_ERR;
3965 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003966
3967 if ((f = popen(cmd, "r")) == NULL) {
3968 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3969 return RETURN_ERR;
3970 }
developer5550e242022-09-30 09:59:32 +08003971
3972 while(fgets(line, sizeof(line), f) != NULL) {
3973 if(arr_index < channels_num){
3974 sscanf(line, "%d", &tmp);
3975 if (tmp > 0) { // channel frequency, the first line must be frequency
3976 arr_index++;
3977 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3978 } else { // noise
3979 channels_noise_arr[arr_index].noise = tmp;
3980 }
3981 }else{
3982 break;
developera3c68b92022-09-13 15:27:29 +08003983 }
3984 }
developera3c68b92022-09-13 15:27:29 +08003985 pclose(f);
3986 return RETURN_OK;
3987}
3988
developer06a01d92022-09-07 16:32:39 +08003989//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3990//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3991INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3992{
developera3c68b92022-09-13 15:27:29 +08003993 int index = -1;
3994 wifi_neighbor_ap2_t *scan_array = NULL;
3995 char cmd[256]={0};
3996 char buf[128]={0};
3997 char file_name[32] = {0};
3998 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003999 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004000 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08004001 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08004002 int freq=0;
4003 FILE *f = NULL;
4004 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08004005 int channels_num = 0;
4006 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08004007 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08004008 bool filter_enable = false;
4009 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08004010 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004011
developer615510b2022-09-27 10:14:35 +08004012 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004013
developerac6f1142022-12-20 19:26:35 +08004014 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004015 return RETURN_ERR;
4016
developera3c68b92022-09-13 15:27:29 +08004017 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4018 f = fopen(file_name, "r");
4019 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08004020 fgets(buf, sizeof(file_name), f);
4021 if ((strncmp(buf, "0", 1)) != 0) {
4022 fgets(filter_SSID, sizeof(file_name), f);
4023 if (strlen(filter_SSID) != 0)
4024 filter_enable = true;
4025 }
developera3c68b92022-09-13 15:27:29 +08004026 fclose(f);
4027 }
4028
developer033b37b2022-10-18 11:27:46 +08004029 phyId = radio_index_to_phy(radioIndex);
4030 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08004031 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08004032 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004033
developer5550e242022-09-30 09:59:32 +08004034
developer06a01d92022-09-07 16:32:39 +08004035
developerd946fd62022-12-08 18:03:28 +08004036 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4037 // 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 +08004038 fprintf(stderr, "cmd: %s\n", cmd);
4039 if ((f = popen(cmd, "r")) == NULL) {
4040 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4041 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004042 }
developer5550e242022-09-30 09:59:32 +08004043
4044 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4045 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
4046
developer615510b2022-09-27 10:14:35 +08004047 ret = fgets(line, sizeof(line), f);
4048 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08004049 if(strstr(line, "BSS") != NULL) { // new neighbor info
4050 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
4051 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4052 // 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 +08004053
developera3c68b92022-09-13 15:27:29 +08004054 if (!filter_BSS) {
4055 index++;
4056 wifi_neighbor_ap2_t *tmp;
4057 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4058 if (tmp == NULL) { // no more memory to use
4059 index--;
4060 wifi_dbg_printf("%s: realloc failed\n", __func__);
4061 break;
4062 }
4063 scan_array = tmp;
4064 }
4065 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4066
4067 filter_BSS = false;
4068 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4069 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4070 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4071 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4072 } else if (strstr(line, "freq") != NULL) {
4073 sscanf(line," freq: %d", &freq);
4074 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4075
4076 if (freq >= 2412 && freq <= 2484) {
4077 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4078 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4079 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4080 }
4081 else if (freq >= 5160 && freq <= 5805) {
4082 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4083 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4084 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4085 }
4086
4087 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08004088 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08004089 for (int i = 0; i < channels_num; i++) {
4090 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4091 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4092 break;
4093 }
4094 }
4095 }
4096 } else if (strstr(line, "beacon interval") != NULL) {
4097 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4098 } else if (strstr(line, "signal") != NULL) {
4099 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4100 } else if (strstr(line,"SSID") != NULL) {
4101 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4102 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4103 filter_BSS = true;
4104 }
4105 } else if (strstr(line, "Supported rates") != NULL) {
4106 char SRate[80] = {0}, *tmp = NULL;
4107 memset(buf, 0, sizeof(buf));
4108 strcpy(SRate, line);
4109 tmp = strtok(SRate, ":");
4110 tmp = strtok(NULL, ":");
4111 strcpy(buf, tmp);
4112 memset(SRate, 0, sizeof(SRate));
4113
4114 tmp = strtok(buf, " \n");
4115 while (tmp != NULL) {
4116 strcat(SRate, tmp);
4117 if (SRate[strlen(SRate) - 1] == '*') {
4118 SRate[strlen(SRate) - 1] = '\0';
4119 }
4120 strcat(SRate, ",");
4121
4122 tmp = strtok(NULL, " \n");
4123 }
4124 SRate[strlen(SRate) - 1] = '\0';
4125 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4126 } else if (strstr(line, "DTIM") != NULL) {
4127 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4128 } else if (strstr(line, "VHT capabilities") != NULL) {
4129 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4130 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4131 } else if (strstr(line, "HT capabilities") != NULL) {
4132 strcat(scan_array[index].ap_SupportedStandards, ",n");
4133 strcpy(scan_array[index].ap_OperatingStandards, "n");
4134 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004135 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004136 sscanf(line," * channel width: %d", &vht_channel_width);
4137 if(vht_channel_width == 1) {
4138 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4139 } else {
4140 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4141 }
4142 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4143 continue;
4144 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004145 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004146 sscanf(line," * secondary channel offset: %s", &buf);
4147 if (!strcmp(buf, "above")) {
4148 //40Mhz +
4149 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4150 }
4151 else if (!strcmp(buf, "below")) {
4152 //40Mhz -
4153 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4154 } else {
4155 //20Mhz
4156 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4157 }
4158 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4159 continue;
4160 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08004161 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4162 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4163 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004164 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4165 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004166 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08004167 else
developer615510b2022-09-27 10:14:35 +08004168 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08004169 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08004170 if (strstr(line, "HE80/5GHz") != NULL) {
4171 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4172 ret = fgets(line, sizeof(line), f);
4173 } else
4174 continue;
developera3c68b92022-09-13 15:27:29 +08004175 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004176 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08004177 }
developer615510b2022-09-27 10:14:35 +08004178 continue;
developera3c68b92022-09-13 15:27:29 +08004179 } else if (strstr(line, "WPA") != NULL) {
4180 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4181 } else if (strstr(line, "RSN") != NULL) {
4182 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4183 } else if (strstr(line, "Group cipher") != NULL) {
4184 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4185 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4186 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4187 }
4188 }
developer615510b2022-09-27 10:14:35 +08004189 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004190 }
4191
4192 if (!filter_BSS) {
4193 *output_array_size = index + 1;
4194 } else {
4195 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4196 *output_array_size = index;
4197 }
4198 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08004199 pclose(f);
developer5550e242022-09-30 09:59:32 +08004200 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08004201 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004202 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004203}
4204
4205//>> Deprecated: used for old RDKB code.
4206INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4207{
4208 INT status = RETURN_ERR;
4209
4210 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4211 output_struct->wifi_PLCPErrorCount = 0;
4212 output_struct->wifi_FCSErrorCount = 0;
4213 output_struct->wifi_InvalidMACCount = 0;
4214 output_struct->wifi_PacketsOtherReceived = 0;
4215 output_struct->wifi_Noise = 0;
4216 status = RETURN_OK;
4217 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4218 return status;
4219}
4220
4221INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4222{
developerd946fd62022-12-08 18:03:28 +08004223 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004224 char cmd[128] = {0};
4225 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004226 char *pos = NULL;
4227
4228 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4229 if (NULL == output_struct)
4230 return RETURN_ERR;
4231
developerac6f1142022-12-20 19:26:35 +08004232 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004233 return RETURN_ERR;
4234
developer06a01d92022-09-07 16:32:39 +08004235 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4236
developerd946fd62022-12-08 18:03:28 +08004237 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004238 _syscmd(cmd, buf, sizeof(buf));
4239
4240 pos = buf;
4241 if ((pos = strstr(pos, "RX packets:")) == NULL)
4242 return RETURN_ERR;
4243 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4244
4245 if ((pos = strstr(pos, "TX packets:")) == NULL)
4246 return RETURN_ERR;
4247 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4248
4249 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4250 return RETURN_ERR;
4251 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4252
4253 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4254 return RETURN_ERR;
4255 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4256
developerd946fd62022-12-08 18:03:28 +08004257 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004258 _syscmd(cmd, buf, sizeof(buf));
4259 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4260
4261#if 0
4262 //TODO: need to revisit below implementation
4263 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4264 char interface_name[MAX_BUF_SIZE] = {0};
4265 char interface_status[MAX_BUF_SIZE] = {0};
4266 char Value[MAX_BUF_SIZE] = {0};
4267 char buf[MAX_CMD_SIZE] = {0};
4268 char cmd[MAX_CMD_SIZE] = {0};
4269 FILE *fp = NULL;
4270
4271 if (NULL == output_struct) {
4272 return RETURN_ERR;
4273 }
4274
4275 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4276
4277 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4278 {
4279 if(apIndex == 0) //private_wifi for 2.4G
4280 {
developerac6f1142022-12-20 19:26:35 +08004281 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004282 }
4283 else if(apIndex == 1) //private_wifi for 5G
4284 {
developerac6f1142022-12-20 19:26:35 +08004285 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004286 }
4287 else if(apIndex == 4) //public_wifi for 2.4G
4288 {
4289 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4290 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4291 {
4292 return RETURN_ERR;
4293 }
4294 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004295 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004296 else//tenda
developerac6f1142022-12-20 19:26:35 +08004297 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004298 }
4299 else if(apIndex == 5) //public_wifi for 5G
4300 {
developerac6f1142022-12-20 19:26:35 +08004301 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004302 }
4303
4304 GetIfacestatus(interface_name, interface_status);
4305
4306 if(0 != strcmp(interface_status, "1"))
4307 return RETURN_ERR;
4308
4309 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4310 system(cmd);
4311
4312 fp = fopen("/tmp/SSID_Stats.txt", "r");
4313 if(fp == NULL)
4314 {
4315 printf("/tmp/SSID_Stats.txt not exists \n");
4316 return RETURN_ERR;
4317 }
4318 fclose(fp);
4319
4320 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4321 File_Reading(buf, Value);
4322 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4323
4324 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4325 File_Reading(buf, Value);
4326 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4327
4328 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4329 File_Reading(buf, Value);
4330 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4331
4332 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4333 File_Reading(buf, Value);
4334 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4335
4336 /* There is no specific parameter from caller to associate the value wifi_Associations */
4337 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4338 //_syscmd(cmd, buf, sizeof(buf));
4339 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4340 }
4341#endif
4342 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4343 return RETURN_OK;
4344}
4345
4346INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4347{
4348 char interface_name[MAX_BUF_SIZE] = {0};
4349 char interface_status[MAX_BUF_SIZE] = {0};
4350 char Value[MAX_BUF_SIZE] = {0};
4351 char buf[MAX_CMD_SIZE] = {0};
4352 char cmd[MAX_CMD_SIZE] = {0};
4353 FILE *fp = NULL;
4354
4355 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4356 if (NULL == output_struct)
4357 return RETURN_ERR;
4358
4359 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4360
developerac6f1142022-12-20 19:26:35 +08004361 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004362 return RETURN_ERR;
4363 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004364
developerd946fd62022-12-08 18:03:28 +08004365 if(0 != strcmp(interface_status, "1"))
4366 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004367
developerd946fd62022-12-08 18:03:28 +08004368 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4369 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004370
developerd946fd62022-12-08 18:03:28 +08004371 fp = fopen("/tmp/SSID_Stats.txt", "r");
4372 if(fp == NULL)
4373 {
4374 printf("/tmp/SSID_Stats.txt not exists \n");
4375 return RETURN_ERR;
4376 }
4377 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004378
developerd946fd62022-12-08 18:03:28 +08004379 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4380 File_Reading(buf, Value);
4381 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004382
developerd946fd62022-12-08 18:03:28 +08004383 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4384 File_Reading(buf, Value);
4385 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004386
developerd946fd62022-12-08 18:03:28 +08004387 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4388 File_Reading(buf, Value);
4389 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004390
developerd946fd62022-12-08 18:03:28 +08004391 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4392 File_Reading(buf, Value);
4393 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004394
4395 output_struct->wifi_UnicastPacketsSent = 0;
4396 output_struct->wifi_UnicastPacketsReceived = 0;
4397 output_struct->wifi_MulticastPacketsSent = 0;
4398 output_struct->wifi_MulticastPacketsReceived = 0;
4399 output_struct->wifi_BroadcastPacketsSent = 0;
4400 output_struct->wifi_BroadcastPacketsRecevied = 0;
4401 output_struct->wifi_UnknownPacketsReceived = 0;
4402
4403 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4404 return RETURN_OK;
4405}
4406
4407INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4408{
4409 INT status = RETURN_ERR;
4410
4411 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4412 //Below values should get updated from hal
4413 output_struct->wifi_RetransCount=0;
4414 output_struct->wifi_FailedRetransCount=0;
4415 output_struct->wifi_RetryCount=0;
4416 output_struct->wifi_MultipleRetryCount=0;
4417 output_struct->wifi_ACKFailureCount=0;
4418 output_struct->wifi_AggregatedPacketCount=0;
4419
4420 status = RETURN_OK;
4421 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4422
4423 return status;
4424}
4425
4426INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4427{
4428 INT status = RETURN_ERR;
4429 UINT index;
4430 wifi_neighbor_ap_t *pt=NULL;
4431
4432 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4433 *output_array_size=2;
4434 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4435 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4436 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4437 strcpy(pt->ap_Radio,"");
4438 strcpy(pt->ap_SSID,"");
4439 strcpy(pt->ap_BSSID,"");
4440 strcpy(pt->ap_Mode,"");
4441 pt->ap_Channel=1;
4442 pt->ap_SignalStrength=0;
4443 strcpy(pt->ap_SecurityModeEnabled,"");
4444 strcpy(pt->ap_EncryptionMode,"");
4445 strcpy(pt->ap_OperatingFrequencyBand,"");
4446 strcpy(pt->ap_SupportedStandards,"");
4447 strcpy(pt->ap_OperatingStandards,"");
4448 strcpy(pt->ap_OperatingChannelBandwidth,"");
4449 pt->ap_BeaconPeriod=1;
4450 pt->ap_Noise=0;
4451 strcpy(pt->ap_BasicDataTransferRates,"");
4452 strcpy(pt->ap_SupportedDataTransferRates,"");
4453 pt->ap_DTIMPeriod=1;
4454 pt->ap_ChannelUtilization = 1;
4455 }
4456
4457 status = RETURN_OK;
4458 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4459
4460 return status;
4461}
4462
4463//----------------- AP HAL -------------------------------
4464
4465//>> Deprecated: used for old RDKB code.
4466INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4467{
4468 if (NULL == output_ulong || NULL == output_struct)
4469 return RETURN_ERR;
4470 *output_ulong = 0;
4471 *output_struct = NULL;
4472 return RETURN_OK;
4473}
4474
4475#ifdef HAL_NETLINK_IMPL
4476static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4477 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4478 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4479 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4480 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4481 char mac_addr[20];
4482 static int count=0;
4483 int rate=0;
4484
4485 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4486
4487 nla_parse(tb,
4488 NL80211_ATTR_MAX,
4489 genlmsg_attrdata(gnlh, 0),
4490 genlmsg_attrlen(gnlh, 0),
4491 NULL);
4492
4493 if(!tb[NL80211_ATTR_STA_INFO]) {
4494 fprintf(stderr, "sta stats missing!\n");
4495 return NL_SKIP;
4496 }
4497
4498
4499 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4500 fprintf(stderr, "failed to parse nested attributes!\n");
4501 return NL_SKIP;
4502 }
4503
4504 //devIndex starts from 1
4505 if( ++count == out->wifi_devIndex )
4506 {
4507 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4508 //Getting the mac addrress
4509 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4510
4511 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4512 fprintf(stderr, "failed to parse nested rate attributes!");
4513 return NL_SKIP;
4514 }
4515
4516 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4517 if(rinfo[NL80211_RATE_INFO_BITRATE])
4518 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4519 out->wifi_devTxRate = rate/10;
4520 }
4521
4522 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4523 fprintf(stderr, "failed to parse nested rate attributes!");
4524 return NL_SKIP;
4525 }
4526
4527 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4528 if(rinfo[NL80211_RATE_INFO_BITRATE])
4529 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4530 out->wifi_devRxRate = rate/10;
4531 }
4532 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4533 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4534
4535 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4536 count = 0; //starts the count for next cycle
4537 return NL_STOP;
4538 }
4539
4540 return NL_SKIP;
4541
4542}
4543#endif
4544
4545INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4546{
4547#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004548 Netlink nl = {0};
4549 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004550 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004551
developer30423732022-12-01 16:17:49 +08004552 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004553 info.wifi_devIndex = devIndex;
4554
developerac6f1142022-12-20 19:26:35 +08004555 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004556 return RETURN_ERR;
4557
4558 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004559
4560 nl.id = initSock80211(&nl);
4561
4562 if (nl.id < 0) {
4563 fprintf(stderr, "Error initializing netlink \n");
4564 return -1;
4565 }
4566
4567 struct nl_msg* msg = nlmsg_alloc();
4568
4569 if (!msg) {
4570 fprintf(stderr, "Failed to allocate netlink message.\n");
4571 nlfree(&nl);
4572 return -2;
4573 }
4574
4575 genlmsg_put(msg,
4576 NL_AUTO_PORT,
4577 NL_AUTO_SEQ,
4578 nl.id,
4579 0,
4580 NLM_F_DUMP,
4581 NL80211_CMD_GET_STATION,
4582 0);
4583
4584 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4585 nl_send_auto(nl.socket, msg);
4586 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4587 nl_recvmsgs(nl.socket, nl.cb);
4588 nlmsg_free(msg);
4589 nlfree(&nl);
4590
4591 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4592 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4593 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4594 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4595 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4596 return RETURN_OK;
4597#else
4598 //iw utility to retrieve station information
4599#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4600#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4601#define MACFILE "/tmp/wifi_AssoMac.txt"
4602#define TXRATEFILE "/tmp/wifi_txrate.txt"
4603#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4604 FILE *file = NULL;
4605 char if_name[10] = {'\0'};
4606 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004607 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004608 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004609 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004610
developerac6f1142022-12-20 19:26:35 +08004611 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004612 return RETURN_ERR;
4613
4614 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004615
4616 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4617 file = popen(pipeCmd, "r");
4618
4619 if(file == NULL)
4620 return RETURN_ERR; //popen failed
4621
4622 fgets(line, sizeof line, file);
4623 device = atoi(line);
4624 pclose(file);
4625
4626 if(device == 0)
4627 return RETURN_ERR; //No devices are connected
4628
4629 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4630 system(pipeCmd);
4631
4632 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4633
4634 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4635
4636 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4637
4638 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4639
4640 //devIndex starts from 1, ++count
4641 if((file = fopen(SIGNALFILE, "r")) != NULL )
4642 {
4643 for(count =0;fgets(line, sizeof line, file) != NULL;)
4644 {
4645 if (++count == devIndex)
4646 {
4647 output_struct->wifi_devSignalStrength = atoi(line);
4648 break;
4649 }
4650 }
4651 fclose(file);
4652 }
4653 else
4654 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4655
4656 if((file = fopen(MACFILE, "r")) != NULL )
4657 {
4658 for(count =0;fgets(line, sizeof line, file) != NULL;)
4659 {
4660 if (++count == devIndex)
4661 {
4662 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]);
4663 break;
4664 }
4665 }
4666 fclose(file);
4667 }
4668 else
4669 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4670
4671 if((file = fopen(TXRATEFILE, "r")) != NULL )
4672 {
4673 for(count =0;fgets(line, sizeof line, file) != NULL;)
4674 {
4675 if (++count == devIndex)
4676 {
4677 output_struct->wifi_devTxRate = atoi(line);
4678 break;
4679 }
4680 }
4681 fclose(file);
4682 }
4683 else
4684 fprintf(stderr,"fopen wifi_txrate.txt failed");
4685
4686 if((file = fopen(RXRATEFILE, "r")) != NULL)
4687 {
4688 for(count =0;fgets(line, sizeof line, file) != NULL;)
4689 {
4690 if (++count == devIndex)
4691 {
4692 output_struct->wifi_devRxRate = atoi(line);
4693 break;
4694 }
4695 }
4696 fclose(file);
4697 }
4698 else
4699 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4700
4701 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4702
4703 return RETURN_OK;
4704#endif
4705}
4706
4707INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4708{
4709 if (NULL == device)
4710 return RETURN_ERR;
4711 return RETURN_OK;
4712}
4713//<<
4714
4715
4716//--------------wifi_ap_hal-----------------------------
4717//enables CTS protection for the radio used by this AP
4718INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4719{
4720 //save config and Apply instantly
4721 return RETURN_ERR;
4722}
4723
4724// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4725INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4726{
developer463d39a2022-09-13 15:32:51 +08004727 char config_file[64] = {'\0'};
4728 char buf[64] = {'\0'};
4729 struct params list;
4730
4731 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4732 list.name = "ht_coex";
4733 snprintf(buf, sizeof(buf), "%d", enable);
4734 list.value = buf;
4735
4736 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4737 wifi_hostapdWrite(config_file, &list, 1);
4738 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4739
4740 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4741
4742 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004743}
4744
4745//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4746INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4747{
developerea4bcce2022-09-13 15:26:13 +08004748 char config_file[MAX_BUF_SIZE] = {'\0'};
4749 char buf[MAX_BUF_SIZE] = {'\0'};
4750 struct params list;
4751
4752 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4753 if (threshold < 256 || threshold > 2346 )
4754 return RETURN_ERR;
4755 list.name = "fragm_threshold";
4756 snprintf(buf, sizeof(buf), "%d", threshold);
4757 list.value = buf;
4758
4759 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4760 wifi_hostapdWrite(config_file, &list, 1);
4761 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004762
developerea4bcce2022-09-13 15:26:13 +08004763 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004764
4765 return RETURN_OK;
4766}
4767
4768// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4769INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4770{
developer51a927d2022-09-13 15:42:22 +08004771 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004772 char cmd[512] = {'\0'};
4773 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004774 char stbc_config[16] = {'\0'};
4775 wifi_band band;
4776 int iterator = 0;
4777 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004778 int ant_count = 0;
4779 int ant_bitmap = 0;
4780 struct params list;
developer51a927d2022-09-13 15:42:22 +08004781
4782 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4783
4784 band = wifi_index_to_band(radioIndex);
4785 if (band == band_invalid)
4786 return RETURN_ERR;
4787
4788 if (band == band_2_4)
4789 iterator = 1;
4790 else if (band == band_5)
4791 iterator = 2;
4792 else
4793 return RETURN_OK;
4794
developer110b8a32022-12-26 15:56:44 +08004795 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4796 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4797 ant_count += ant_bitmap & 1;
4798
4799 if (ant_count == 1 && STBC_Enable == TRUE) {
4800 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4801 return RETURN_OK;
4802 }
4803
developer51a927d2022-09-13 15:42:22 +08004804 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4805
4806 // set ht and vht config
4807 for (int i = 0; i < iterator; i++) {
4808 memset(stbc_config, 0, sizeof(stbc_config));
4809 memset(cmd, 0, sizeof(cmd));
4810 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004811 list.name = (i == 0)?"ht_capab":"vht_capab";
4812 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004813 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4814 _syscmd(cmd, buf, sizeof(buf));
4815 if (strlen(buf) != 0)
4816 current_stbc = TRUE;
4817 if (current_stbc == STBC_Enable)
4818 continue;
4819
4820 if (STBC_Enable == TRUE) {
4821 // Append the STBC flags in capab config
4822 memset(cmd, 0, sizeof(cmd));
4823 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004824 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004825 else
developer6372c2b2022-10-27 17:39:51 +08004826 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 +08004827 _syscmd(cmd, buf, sizeof(buf));
4828 } else if (STBC_Enable == FALSE) {
4829 // Remove the STBC flags and remain other flags in capab
4830 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004831 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004832 _syscmd(cmd, buf, sizeof(buf));
4833 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004834 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004835 _syscmd(cmd, buf, sizeof(buf));
4836 }
developer110b8a32022-12-26 15:56:44 +08004837 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4838 list.value = buf;
4839 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004840 }
4841
4842 wifi_reloadAp(radioIndex);
4843
4844 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4845 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004846}
4847
4848// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4849INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4850{
developerfe7aefc2022-12-23 17:13:37 +08004851 char cmd[128] = {0};
4852 char buf[128] = {0};
4853 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004854
4855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4856
4857 if(output_bool == NULL)
4858 return RETURN_ERR;
4859
developerfe7aefc2022-12-23 17:13:37 +08004860 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4861 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004862
developerfe7aefc2022-12-23 17:13:37 +08004863 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4864 _syscmd(cmd, buf, sizeof(buf));
4865
4866 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004867 *output_bool = TRUE;
4868 else
4869 *output_bool = FALSE;
4870
4871 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4872 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004873}
4874
4875// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4876INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4877{
developerfe7aefc2022-12-23 17:13:37 +08004878 char config_file[128] = {0};
4879 struct params list = {0};
4880 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004881
4882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4883
developerfe7aefc2022-12-23 17:13:37 +08004884 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004885 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004886
developerfe7aefc2022-12-23 17:13:37 +08004887 if (amsduEnable == enable)
4888 return RETURN_OK;
4889
4890 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4891 list.name = "amsdu";
4892 list.value = amsduEnable? "1":"0";
4893 wifi_hostapdWrite(config_file, &list, 1);
4894 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4895 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004896
4897 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4898 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004899}
4900
4901//P2 // outputs the number of Tx streams
4902INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4903{
developer2de97692022-09-26 14:00:03 +08004904 char buf[8] = {0};
4905 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004906 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004907
4908 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4909
developer033b37b2022-10-18 11:27:46 +08004910 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004911 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004912 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004913
developer110b8a32022-12-26 15:56:44 +08004914 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004915
4916 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4917
4918 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004919}
4920
developer110b8a32022-12-26 15:56:44 +08004921INT fitChainMask(INT radioIndex, int antcount)
4922{
4923 char buf[128] = {0};
4924 char cmd[128] = {0};
4925 char config_file[64] = {0};
4926 wifi_band band;
4927 struct params list[2] = {0};
4928
4929 band = wifi_index_to_band(radioIndex);
4930 if (band == band_invalid)
4931 return RETURN_ERR;
4932
4933 list[0].name = "he_mu_beamformer";
4934 list[1].name = "he_su_beamformer";
4935
4936 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4937 if (antcount == 1) {
4938 // remove config about multiple antennas
4939 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4940 _syscmd(cmd, buf, sizeof(buf));
4941
4942 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4943 _syscmd(cmd, buf, sizeof(buf));
4944
4945 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4946 _syscmd(cmd, buf, sizeof(buf));
4947
4948 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4949 _syscmd(cmd, buf, sizeof(buf));
4950
4951 list[0].value = "0";
4952 list[1].value = "0";
4953 } else {
4954 // 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.
4955 if (band == band_2_4 || band == band_5) {
4956 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4957 _syscmd(cmd, buf, sizeof(buf));
4958 if (strlen(buf) > 0) {
4959 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4960 _syscmd(cmd, buf, sizeof(buf));
4961 }
4962 }
4963 if (band == band_5) {
4964 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4965 _syscmd(cmd, buf, sizeof(buf));
4966 if (strlen(buf) > 0) {
4967 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4968 _syscmd(cmd, buf, sizeof(buf));
4969 }
4970 }
4971
4972 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4973 _syscmd(cmd, buf, sizeof(buf));
4974 if (strlen(buf) == 0) {
4975 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4976 _syscmd(cmd, buf, sizeof(buf));
4977 }
4978
4979 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4980 _syscmd(cmd, buf, sizeof(buf));
4981 if (strlen(buf) == 0) {
4982 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4983 _syscmd(cmd, buf, sizeof(buf));
4984 }
4985
4986 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4987 _syscmd(cmd, buf, sizeof(buf));
4988 if (strlen(buf) == 0) {
4989 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4990 } else {
4991 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4992 }
4993 _syscmd(cmd, buf, sizeof(buf));
4994
4995 list[0].value = "1";
4996 list[1].value = "1";
4997 }
4998 wifi_hostapdWrite(config_file, list, 2);
4999}
5000
developer06a01d92022-09-07 16:32:39 +08005001//P2 // sets the number of Tx streams to an enviornment variable
5002INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5003{
developer2de97692022-09-26 14:00:03 +08005004 char cmd[128] = {0};
5005 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08005006 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08005007 int cur_mask = 0;
5008 int antcount = 0;
5009 wifi_band band;
developer2de97692022-09-26 14:00:03 +08005010
5011 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5012
developer110b8a32022-12-26 15:56:44 +08005013 if (numStreams <= 0) {
5014 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08005015 return RETURN_ERR;
5016 }
developer110b8a32022-12-26 15:56:44 +08005017
5018 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
5019 if (cur_mask == numStreams)
5020 return RETURN_OK;
5021
developer2de97692022-09-26 14:00:03 +08005022 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08005023
5024 phyId = radio_index_to_phy(radioIndex);
5025 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08005026 _syscmd(cmd, buf, sizeof(buf));
5027
5028 if (strlen(buf) > 0) {
5029 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5030 return RETURN_ERR;
5031 }
developer2de97692022-09-26 14:00:03 +08005032
developer110b8a32022-12-26 15:56:44 +08005033 // if chain mask changed, we need to make the hostapd config valid.
5034 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
5035 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08005036 }
developer110b8a32022-12-26 15:56:44 +08005037 fitChainMask(radioIndex, antcount);
5038
5039 wifi_setRadioEnable(radioIndex, TRUE);
5040
developer2de97692022-09-26 14:00:03 +08005041 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5042 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005043}
5044
5045//P2 // outputs the number of Rx streams
5046INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5047{
developer110b8a32022-12-26 15:56:44 +08005048 char buf[8] = {0};
5049 char cmd[128] = {0};
5050 int phyId = 0;
5051
developer2de97692022-09-26 14:00:03 +08005052 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005053
5054 phyId = radio_index_to_phy(radioIndex);
5055 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5056 _syscmd(cmd, buf, sizeof(buf));
5057
5058 *output_int = (INT)strtol(buf, NULL, 16);
5059
developer2de97692022-09-26 14:00:03 +08005060 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005061
developer06a01d92022-09-07 16:32:39 +08005062 return RETURN_OK;
5063}
5064
5065//P2 // sets the number of Rx streams to an enviornment variable
5066INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5067{
developer2de97692022-09-26 14:00:03 +08005068 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5069 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5070 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5071 return RETURN_ERR;
5072 }
5073 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005074 return RETURN_ERR;
5075}
5076
5077//Get radio RDG enable setting
5078INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5079{
5080 if (NULL == output_bool)
5081 return RETURN_ERR;
5082 *output_bool = TRUE;
5083 return RETURN_OK;
5084}
5085
5086//Get radio RDG enable setting
5087INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5088{
5089 if (NULL == output_bool)
5090 return RETURN_ERR;
5091 *output_bool = TRUE;
5092 return RETURN_OK;
5093}
5094
5095//Set radio RDG enable setting
5096INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5097{
5098 return RETURN_ERR;
5099}
5100
5101//Get radio ADDBA enable setting
5102INT wifi_getRadioDeclineBARequestEnable(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 ADDBA enable setting
5111INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5112{
5113 return RETURN_ERR;
5114}
5115
5116//Get radio auto block ack enable setting
5117INT wifi_getRadioAutoBlockAckEnable(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 auto block ack enable setting
5126INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5127{
5128 return RETURN_ERR;
5129}
5130
5131//Get radio 11n pure mode enable support
5132INT wifi_getRadio11nGreenfieldSupported(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//Get radio 11n pure mode enable setting
5141INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5142{
5143 if (NULL == output_bool)
5144 return RETURN_ERR;
5145 *output_bool = TRUE;
5146 return RETURN_OK;
5147}
5148
5149//Set radio 11n pure mode enable setting
5150INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5151{
5152 return RETURN_ERR;
5153}
5154
5155//Get radio IGMP snooping enable setting
5156INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5157{
developerd946fd62022-12-08 18:03:28 +08005158 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005159 char cmd[128]={0};
5160 char buf[4]={0};
5161 bool bridge = FALSE, mac80211 = FALSE;
5162 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5163
5164 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08005165 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08005166
5167 *output_bool = FALSE;
5168
5169 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5170 _syscmd(cmd, buf, sizeof(buf));
5171 if (strncmp(buf, "1", 1) == 0)
5172 bridge = TRUE;
5173
developerac6f1142022-12-20 19:26:35 +08005174 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005175 return RETURN_ERR;
5176 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 +08005177 _syscmd(cmd, buf, sizeof(buf));
5178 if (strncmp(buf, "1", 1) == 0)
5179 mac80211 = TRUE;
5180
5181 if (bridge && mac80211)
5182 *output_bool = TRUE;
5183
5184 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005185 return RETURN_OK;
5186}
5187
5188//Set radio IGMP snooping enable setting
5189INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5190{
developerd946fd62022-12-08 18:03:28 +08005191 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005192 char cmd[128]={0};
5193 char buf[4]={0};
developer894affa2023-05-10 18:13:19 +08005194 int max_num_radios = 0;
5195 int apIndex = 0;
developer81bf2ed2022-09-13 15:31:14 +08005196 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5197
5198 // bridge
developerfb09ba62023-06-09 17:03:21 +08005199 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
developer81bf2ed2022-09-13 15:31:14 +08005200 _syscmd(cmd, buf, sizeof(buf));
5201
developer804c64f2022-10-19 13:54:40 +08005202 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08005203 // mac80211
developer894affa2023-05-10 18:13:19 +08005204 for (int i = 0; i < MAX_NUM_VAP_PER_RADIO; i++) {
5205 apIndex = radioIndex + i*max_num_radios;
5206 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5207 continue;
developerfb09ba62023-06-09 17:03:21 +08005208 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 +08005209 _syscmd(cmd, buf, sizeof(buf));
5210 }
5211 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5212 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005213}
5214
5215//Get the Reset count of radio
5216INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5217{
5218 if (NULL == output_int)
5219 return RETURN_ERR;
5220 *output_int = (radioIndex==0)? 1: 3;
5221
5222 return RETURN_OK;
5223}
5224
5225
5226//---------------------------------------------------------------------------------------------------
5227//
5228// Additional Wifi AP level APIs used for Access Point devices
5229//
5230//---------------------------------------------------------------------------------------------------
5231
5232// creates a new ap and pushes these parameters to the hardware
5233INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5234{
developer7930d352022-12-21 17:55:42 +08005235 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005236 return RETURN_OK;
5237}
5238
5239// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5240INT wifi_deleteAp(INT apIndex)
5241{
developerd946fd62022-12-08 18:03:28 +08005242 char interface_name[16] = {0};
developer89df4502023-02-16 20:45:02 +08005243 char buf[128] = {0};
5244 char cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08005245
developerac6f1142022-12-20 19:26:35 +08005246 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005247 return RETURN_ERR;
developera77d84b2023-02-22 16:10:50 +08005248
developer89df4502023-02-16 20:45:02 +08005249 if (wifi_setApEnable(apIndex, FALSE) != RETURN_OK)
5250 return RETURN_ERR;
5251
developer7930d352022-12-21 17:55:42 +08005252 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005253 _syscmd(cmd, buf, sizeof(buf));
5254
5255 wifi_removeApSecVaribles(apIndex);
developer06a01d92022-09-07 16:32:39 +08005256 return RETURN_OK;
5257}
5258
5259// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5260INT wifi_getApName(INT apIndex, CHAR *output_string)
5261{
developerd946fd62022-12-08 18:03:28 +08005262 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005263 if(NULL == output_string)
5264 return RETURN_ERR;
5265
developerac6f1142022-12-20 19:26:35 +08005266 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005267 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005268 else
5269 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005270 return RETURN_OK;
5271}
5272
5273// Outputs the index number in that corresponds to the SSID string
5274INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5275{
developerd946fd62022-12-08 18:03:28 +08005276 char cmd [128] = {0};
5277 char buf[32] = {0};
5278 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005279 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005280
developerd946fd62022-12-08 18:03:28 +08005281 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5282 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005283
developerac6f1142022-12-20 19:26:35 +08005284 if (strlen(buf) != 0) {
5285 apIndex_str = strtok(buf, "\n");
5286 *output_int = strtoul(apIndex_str, NULL, 10);
5287 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005288 }
developer67b8ee92022-12-20 10:48:43 +08005289
5290 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5291 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5292 if (apIndex_str) {
5293 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5294 return RETURN_OK;
5295 }
developerd946fd62022-12-08 18:03:28 +08005296 *output_int = -1;
5297 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005298}
5299
5300INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5301{
5302 return wifi_getIndexFromName(inputSsidString, output_int);
5303}
5304
5305// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5306INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5307{
5308 char buf[MAX_BUF_SIZE] = {0};
5309 char cmd[MAX_CMD_SIZE] = {0};
5310 char config_file[MAX_BUF_SIZE] = {0};
5311
5312 if(NULL == output_string)
5313 return RETURN_ERR;
5314
5315 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5316 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5317 if((strcmp(buf,"3")==0))
5318 snprintf(output_string, 32, "WPAand11i");
5319 else if((strcmp(buf,"2")==0))
5320 snprintf(output_string, 32, "11i");
5321 else if((strcmp(buf,"1")==0))
5322 snprintf(output_string, 32, "WPA");
5323 else
5324 snprintf(output_string, 32, "None");
5325
5326 return RETURN_OK;
5327}
5328
5329// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5330INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5331{
5332 char config_file[MAX_BUF_SIZE] = {0};
5333 struct params list;
5334
5335 if (NULL == beaconTypeString)
5336 return RETURN_ERR;
5337 list.name = "wpa";
5338 list.value = "0";
5339
5340 if((strcmp(beaconTypeString,"WPAand11i")==0))
5341 list.value="3";
5342 else if((strcmp(beaconTypeString,"11i")==0))
5343 list.value="2";
5344 else if((strcmp(beaconTypeString,"WPA")==0))
5345 list.value="1";
5346
5347 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5348 wifi_hostapdWrite(config_file, &list, 1);
5349 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5350 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5351 return RETURN_OK;
5352}
5353
5354// sets the beacon interval on the hardware for this AP
5355INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5356{
developer5f222492022-09-13 15:21:52 +08005357 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5358 struct params params={'\0'};
5359 char buf[MAX_BUF_SIZE] = {'\0'};
5360 char config_file[MAX_BUF_SIZE] = {'\0'};
5361
5362 params.name = "beacon_int";
5363 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5364 params.value = buf;
5365
5366 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5367 wifi_hostapdWrite(config_file, &params, 1);
5368
5369 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5370 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5371 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005372}
5373
5374INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5375{
developer5b398df2022-11-17 20:39:48 +08005376 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5377 return RETURN_ERR;
5378 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005379}
5380
5381// Get the packet size threshold supported.
5382INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5383{
5384 //save config and apply instantly
5385 if (NULL == output_bool)
5386 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005387 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005388 return RETURN_OK;
5389}
5390
5391// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5392INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5393{
developer514406b2022-12-05 17:20:21 +08005394 char buf[16] = {0};
5395 char config_file[128] = {0};
5396 struct params param = {0};
5397
5398 if (threshold > 65535) {
5399 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5400 return RETURN_ERR;
5401 }
developer06a01d92022-09-07 16:32:39 +08005402
developer23e71282023-01-18 10:25:19 +08005403 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer514406b2022-12-05 17:20:21 +08005404 snprintf(buf, sizeof(buf), "%u", threshold);
5405 param.name = "rts_threshold";
5406 param.value = buf;
5407 wifi_hostapdWrite(config_file, &param, 1);
5408 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5409 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005410
5411 return RETURN_OK;
5412}
5413
5414// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5415INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5416{
5417 if (NULL == output_string)
5418 return RETURN_ERR;
5419 snprintf(output_string, 32, "TKIPandAESEncryption");
5420 return RETURN_OK;
5421
5422}
5423
5424// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5425INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5426{
5427 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005428 char *param_name = NULL;
5429 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005430
5431 if(NULL == output_string)
5432 return RETURN_ERR;
5433
5434 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5435 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5436
5437 if(strcmp(buf,"0")==0)
5438 {
5439 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5440 snprintf(output_string, 32, "None");
5441 return RETURN_OK;
5442 }
5443 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5444 param_name = "rsn_pairwise";
5445 else if((strcmp(buf,"1")==0))
5446 param_name = "wpa_pairwise";
5447 else
5448 return RETURN_ERR;
5449 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005450 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005451 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5452 param_name = "wpa_pairwise";
5453 memset(output_string, '\0', 32);
5454 wifi_hostapdRead(config_file, param_name, output_string, 32);
5455 }
developer06a01d92022-09-07 16:32:39 +08005456 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5457
developer72ec5572023-01-05 16:27:13 +08005458 if(strcmp(output_string,"TKIP CCMP") == 0)
5459 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5460 else if(strcmp(output_string,"TKIP") == 0)
developer06a01d92022-09-07 16:32:39 +08005461 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5462 else if(strcmp(output_string,"CCMP") == 0)
5463 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer06a01d92022-09-07 16:32:39 +08005464
5465 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5466 return RETURN_OK;
5467}
5468
5469// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5470INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5471{
5472 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5473 struct params params={'\0'};
5474 char output_string[32];
developer72ec5572023-01-05 16:27:13 +08005475 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08005476
5477 memset(output_string,'\0',32);
developer72ec5572023-01-05 16:27:13 +08005478 wifi_getApBeaconType(apIndex,output_string);
developer06a01d92022-09-07 16:32:39 +08005479
5480 if(strcmp(encMode, "TKIPEncryption") == 0)
5481 params.value = "TKIP";
5482 else if(strcmp(encMode,"AESEncryption") == 0)
5483 params.value = "CCMP";
5484 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5485 params.value = "TKIP CCMP";
5486
5487 if((strcmp(output_string,"WPAand11i")==0))
5488 {
5489 params.name = "wpa_pairwise";
5490 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5491 wifi_hostapdWrite(config_file, &params, 1);
5492 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5493
developer30423732022-12-01 16:17:49 +08005494 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005495 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5496 wifi_hostapdWrite(config_file, &params, 1);
5497 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5498
5499 return RETURN_OK;
5500 }
5501 else if((strcmp(output_string,"11i")==0))
5502 {
5503 params.name = "rsn_pairwise";
5504 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5505 wifi_hostapdWrite(config_file, &params, 1);
5506 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5507 return RETURN_OK;
5508 }
5509 else if((strcmp(output_string,"WPA")==0))
5510 {
5511 params.name = "wpa_pairwise";
5512 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5513 wifi_hostapdWrite(config_file, &params, 1);
5514 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5515 return RETURN_OK;
5516 }
5517
5518 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5519 return RETURN_OK;
5520}
5521
5522// deletes internal security varable settings for this ap
5523INT wifi_removeApSecVaribles(INT apIndex)
5524{
5525 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005526 //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 +08005527 //_syscmd(cmd, buf, sizeof(buf));
5528
developerd946fd62022-12-08 18:03:28 +08005529 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005530 //_syscmd(cmd, buf, sizeof(buf));
5531 return RETURN_ERR;
5532}
5533
5534// changes the hardware settings to disable encryption on this ap
5535INT wifi_disableApEncryption(INT apIndex)
5536{
5537 //Apply instantly
5538 return RETURN_ERR;
5539}
5540
5541// set the authorization mode on this ap
5542// mode mapping as: 1: open, 2: shared, 4:auto
5543INT wifi_setApAuthMode(INT apIndex, INT mode)
5544{
developeraf95c502022-09-13 16:18:22 +08005545 struct params params={0};
5546 char config_file[64] = {0};
5547 int ret;
5548
5549 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5550
5551 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5552 params.name = "auth_algs";
5553
developer72ec5572023-01-05 16:27:13 +08005554 if ((mode & 1 && mode & 2) || mode & 4)
developeraf95c502022-09-13 16:18:22 +08005555 params.value = "3";
5556 else if (mode & 2)
5557 params.value = "2";
5558 else if (mode & 1)
5559 params.value = "1";
5560 else
5561 params.value = "0";
5562
5563 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5564 wifi_hostapdWrite(config_file, &params, 1);
5565 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer72ec5572023-01-05 16:27:13 +08005566 wifi_reloadAp(apIndex);
developeraf95c502022-09-13 16:18:22 +08005567 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5568
5569 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005570}
5571
5572// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5573INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5574{
5575 //save to wifi config, and wait for wifi restart to apply
5576 struct params params={'\0'};
5577 char config_file[MAX_BUF_SIZE] = {0};
5578 int ret;
5579
5580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5581 if(authMode == NULL)
5582 return RETURN_ERR;
5583
5584 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5585 params.name = "wpa_key_mgmt";
5586
5587 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5588 params.value = "WPA-PSK";
5589 else if(strcmp(authMode,"EAPAuthentication") == 0)
5590 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005591 else if (strcmp(authMode, "SAEAuthentication") == 0)
5592 params.value = "SAE";
5593 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5594 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005595 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5596 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005597 else if (strcmp(authMode, "Enhanced_Open") == 0)
5598 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005599 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5600 return RETURN_OK; //This is taken careof in beaconType
5601
5602 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5603 ret=wifi_hostapdWrite(config_file,&params,1);
5604 if(!ret)
5605 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5606 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5607
5608 return ret;
5609}
5610
5611// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5612INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5613{
5614 //save to wifi config, and wait for wifi restart to apply
5615 char BeaconType[50] = {0};
5616 char config_file[MAX_BUF_SIZE] = {0};
5617
5618 *authMode = 0;
5619 wifi_getApBeaconType(apIndex,BeaconType);
5620 printf("%s____%s \n",__FUNCTION__,BeaconType);
5621
5622 if(strcmp(BeaconType,"None") == 0)
5623 strcpy(authMode,"None");
5624 else
5625 {
5626 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5627 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5628 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5629 if(strcmp(authMode,"WPA-PSK") == 0)
5630 strcpy(authMode,"SharedAuthentication");
5631 else if(strcmp(authMode,"WPA-EAP") == 0)
5632 strcpy(authMode,"EAPAuthentication");
5633 }
5634
5635 return RETURN_OK;
5636}
5637
5638// Outputs the number of stations associated per AP
5639INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5640{
developerd946fd62022-12-08 18:03:28 +08005641 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005642 char cmd[128]={0};
5643 char buf[128]={0};
5644 BOOL status = false;
5645
5646 if(apIndex > MAX_APS)
5647 return RETURN_ERR;
5648
5649 wifi_getApEnable(apIndex,&status);
5650 if (!status)
5651 return RETURN_OK;
5652
developerd946fd62022-12-08 18:03:28 +08005653 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005654 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005655 return RETURN_ERR;
5656 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005657 _syscmd(cmd, buf, sizeof(buf));
5658 sscanf(buf,"%lu", output_ulong);
5659
5660 return RETURN_OK;
5661}
5662
5663// manually removes any active wi-fi association with the device specified on this ap
5664INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5665{
developerd946fd62022-12-08 18:03:28 +08005666 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005667 char buf[126]={'\0'};
5668
developerac6f1142022-12-20 19:26:35 +08005669 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005670 return RETURN_ERR;
5671 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005672 system(buf);
5673
5674 return RETURN_OK;
5675}
5676
5677// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5678INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5679{
5680 if(NULL == output_int)
5681 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005682 int max_radio_num = 0;
5683 wifi_getMaxRadioNumber(&max_radio_num);
5684 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005685 return RETURN_OK;
5686}
5687
5688// sets the radio index for the specific ap
5689INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5690{
5691 //set to config only and wait for wifi reset to apply settings
5692 return RETURN_ERR;
5693}
5694
5695// Get the ACL MAC list per AP
5696INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5697{
developerd946fd62022-12-08 18:03:28 +08005698 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005699 char cmd[MAX_CMD_SIZE]={'\0'};
5700 int ret = 0;
5701
developerac6f1142022-12-20 19:26:35 +08005702 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005703 return RETURN_ERR;
5704 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005705 ret = _syscmd(cmd,macArray,buf_size);
5706 if (ret != 0)
5707 return RETURN_ERR;
5708
5709 return RETURN_OK;
5710}
5711
developere6aafda2022-09-13 14:59:28 +08005712INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5713{
developerd946fd62022-12-08 18:03:28 +08005714 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005715 char cmd[MAX_CMD_SIZE]={'\0'};
5716 int ret = 0;
5717
developerac6f1142022-12-20 19:26:35 +08005718 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005719 return RETURN_ERR;
5720 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005721 ret = _syscmd(cmd,macArray,buf_size);
5722 if (ret != 0)
5723 return RETURN_ERR;
5724
5725 return RETURN_OK;
5726}
5727
developer06a01d92022-09-07 16:32:39 +08005728// Get the list of stations associated per AP
5729INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5730{
developerd946fd62022-12-08 18:03:28 +08005731 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005732 char cmd[128];
5733
5734 if(apIndex > 3) //Currently supporting apIndex upto 3
5735 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005736 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005737 return RETURN_ERR;
5738 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5739 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005740 _syscmd(cmd, macArray, buf_size);
5741
5742 return RETURN_OK;
5743}
5744
developer2f995fb2023-02-24 10:40:44 +08005745INT getAddressControlMode(INT apIndex, INT *mode)
5746{
5747 char buf [16] = {0};
5748 char config_file[64] = {0};
5749
5750 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5751 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
5752
5753 *mode = -1;
5754 // 0 use deny file, 1 use accept file
5755 if (strncmp(buf, "0", 1) == 0 || strncmp(buf, "1", 1) == 0)
5756 *mode = (INT)strtol(buf, NULL, 10);
5757
5758 return RETURN_OK;
5759}
5760
developer06a01d92022-09-07 16:32:39 +08005761// adds the mac address to the filter list
5762//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5763INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5764{
5765 char cmd[MAX_CMD_SIZE]={'\0'};
5766 char buf[MAX_BUF_SIZE]={'\0'};
5767
developer2f995fb2023-02-24 10:40:44 +08005768 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +08005769 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005770
developer06a01d92022-09-07 16:32:39 +08005771 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5772 if(_syscmd(cmd,buf,sizeof(buf)))
5773 return RETURN_ERR;
5774
5775 return RETURN_OK;
5776}
5777
developer2f995fb2023-02-24 10:40:44 +08005778INT wifi_addApDenyAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5779{
5780 char cmd[MAX_CMD_SIZE]={'\0'};
5781 char buf[MAX_BUF_SIZE]={'\0'};
5782
5783 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
5784 return RETURN_ERR;
5785
5786 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5787 if(_syscmd(cmd,buf,sizeof(buf)))
5788 return RETURN_ERR;
5789
5790 return RETURN_OK;
5791}
5792
developer06a01d92022-09-07 16:32:39 +08005793// deletes the mac address from the filter list
5794//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5795INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5796{
5797 char cmd[MAX_CMD_SIZE]={'\0'};
5798 char buf[MAX_BUF_SIZE]={'\0'};
5799
5800#if 0
developerd946fd62022-12-08 18:03:28 +08005801 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005802 if(_syscmd(cmd,buf,sizeof(buf)))
5803 return RETURN_ERR;
5804
5805#endif
developer2f995fb2023-02-24 10:40:44 +08005806 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005807 if(_syscmd(cmd,buf,sizeof(buf)))
5808 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005809 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5810 if(_syscmd(cmd,buf,sizeof(buf)))
5811 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005812
5813 return RETURN_OK;
5814}
5815
5816// outputs the number of devices in the filter list
5817INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5818{
developere6aafda2022-09-13 14:59:28 +08005819 char cmd[MAX_BUF_SIZE]={0};
5820 char buf[MAX_CMD_SIZE]={0};
developer2f995fb2023-02-24 10:40:44 +08005821 int mode = -1;
developere6aafda2022-09-13 14:59:28 +08005822
5823 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5824 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005825 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005826
developer2f995fb2023-02-24 10:40:44 +08005827 getAddressControlMode(apIndex, &mode);
5828 if (mode == -1)
5829 return RETURN_OK;
5830
5831 if (mode == 0)
5832 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", DENY_PREFIX, apIndex);
5833 else if (mode == 1)
5834 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +08005835 _syscmd(cmd, buf, sizeof(buf));
5836
developer2f995fb2023-02-24 10:40:44 +08005837 *output_uint = strtol(buf, NULL, 10);
developere6aafda2022-09-13 14:59:28 +08005838
5839 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5840 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005841}
5842
5843INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5844{
5845 char cmd[128]={'\0'};
5846 char buf[128]={'\0'};
5847
5848 if(strcmp(action,"DENY")==0)
5849 {
5850 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5851 system(buf);
5852 return RETURN_OK;
5853 }
5854
5855 if(strcmp(action,"ALLOW")==0)
5856 {
5857 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5858 system(buf);
5859 return RETURN_OK;
5860 }
5861
5862 return RETURN_ERR;
5863
5864}
5865
5866// enable kick for devices on acl black list
5867INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5868{
5869 char aclArray[512] = {0}, *acl = NULL;
5870 char assocArray[512] = {0}, *asso = NULL;
5871
developere6aafda2022-09-13 14:59:28 +08005872 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005873 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5874
5875 // if there are no devices connected there is nothing to do
5876 if (strlen(assocArray) < 17)
5877 return RETURN_OK;
5878
5879 if (enable == TRUE)
5880 {
5881 //kick off the MAC which is in ACL array (deny list)
5882 acl = strtok(aclArray, "\r\n");
5883 while (acl != NULL) {
5884 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5885 wifi_kickApAssociatedDevice(apIndex, acl);
5886
5887 acl = strtok(NULL, "\r\n");
5888 }
developere6aafda2022-09-13 14:59:28 +08005889 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005890 }
5891 else
5892 {
developere6aafda2022-09-13 14:59:28 +08005893 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005894 }
5895
5896#if 0
5897 //TODO: need to revisit below implementation
5898 char aclArray[512]={0}, *acl=NULL;
5899 char assocArray[512]={0}, *asso=NULL;
5900 char buf[256]={'\0'};
5901 char action[10]={'\0'};
5902 FILE *fr=NULL;
5903 char interface[10]={'\0'};
5904 char config_file[MAX_BUF_SIZE] = {0};
5905
5906 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5907 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5908 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5909 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5910
5911 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5912 system(buf);
5913 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5914 system(buf);
5915 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5916 system(buf);
5917 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5918 system(buf);
5919 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5920 system(buf);
5921
5922 if ( enable == TRUE )
5923 {
5924 int device_count=0;
5925 strcpy(action,"DENY");
5926 //kick off the MAC which is in ACL array (deny list)
5927 acl = strtok (aclArray,",");
5928 while (acl != NULL) {
5929 if(strlen(acl)>=17)
5930 {
5931 apply_rules(apIndex, acl,action,interface);
5932 device_count++;
5933 //Register mac to be blocked ,in syscfg.db persistent storage
5934 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5935 system(buf);
5936 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5937 system(buf);
5938 system("syscfg commit");
5939
5940 wifi_kickApAssociatedDevice(apIndex, acl);
5941 }
5942 acl = strtok (NULL, ",");
5943 }
5944 }
5945 else
5946 {
5947 int device_count=0;
5948 char cmdmac[20]={'\0'};
5949 strcpy(action,"ALLOW");
5950 //kick off the MAC which is not in ACL array (allow list)
5951 acl = strtok (aclArray,",");
5952 while (acl != NULL) {
5953 if(strlen(acl)>=17)
5954 {
5955 apply_rules(apIndex, acl,action,interface);
5956 device_count++;
5957 //Register mac to be Allowed ,in syscfg.db persistent storage
5958 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5959 system(buf);
5960 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5961 system(buf);
5962 sprintf(cmdmac,"%s",acl);
5963 }
5964 acl = strtok (NULL, ",");
5965 }
5966 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5967 system(buf);
5968
5969 //Disconnect the mac which is not in ACL
5970 asso = strtok (assocArray,",");
5971 while (asso != NULL) {
5972 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5973 wifi_kickApAssociatedDevice(apIndex, asso);
5974 asso = strtok (NULL, ",");
5975 }
5976 }
5977#endif
5978 return RETURN_OK;
5979}
5980
5981INT wifi_setPreferPrivateConnection(BOOL enable)
5982{
developer06a01d92022-09-07 16:32:39 +08005983 return RETURN_OK;
5984}
5985
5986// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5987INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5988{
developerd946fd62022-12-08 18:03:28 +08005989 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005990 int items = 1;
5991 struct params list[2];
5992 char buf[MAX_BUF_SIZE] = {0};
5993 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005994 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005995
5996 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005997
developer10adcc12022-09-13 14:39:17 +08005998 if (filterMode == 0) {
5999 sprintf(buf, "%d", 0);
6000 list[0].value = buf;
6001
developer2f995fb2023-02-24 10:40:44 +08006002 char cmd[128] = {0};
developerac6f1142022-12-20 19:26:35 +08006003 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006004 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08006005 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR 2> /dev/null", interface_name);
6006 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08006007 memset(cmd,0,sizeof(cmd));
6008 // Delete deny_mac_file in hostapd configuration
6009 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
developer2f995fb2023-02-24 10:40:44 +08006010 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08006011 }
6012 else if (filterMode == 1) {
6013 sprintf(buf, "%d", filterMode);
6014 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08006015 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
6016 list[1].name = "accept_mac_file";
6017 list[1].value = acl_file;
6018 items = 2;
developer10adcc12022-09-13 14:39:17 +08006019 } else if (filterMode == 2) {
6020 //TODO: deny_mac_file
6021 sprintf(buf, "%d", 0);
6022 list[0].value = buf;
6023 list[1].name = "deny_mac_file";
6024 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
6025 list[1].value = deny_file;
6026 items = 2;
6027 } else {
6028 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006029 }
developer10adcc12022-09-13 14:39:17 +08006030
developer06a01d92022-09-07 16:32:39 +08006031 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6032 wifi_hostapdWrite(config_file, list, items);
developer2f995fb2023-02-24 10:40:44 +08006033 if (multiple_set == FALSE) {
6034 wifi_setApEnable(apIndex, FALSE);
6035 wifi_setApEnable(apIndex, TRUE);
6036 }
developer06a01d92022-09-07 16:32:39 +08006037
6038 return RETURN_OK;
6039
6040#if 0
6041 if(apIndex==0 || apIndex==1)
6042 {
6043 //set the filtermode
6044 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
6045 system(buf);
6046 system("syscfg commit");
6047
6048 if(filterMode==0)
6049 {
6050 sprintf(buf,"iptables -F WifiServices%d",apIndex);
6051 system(buf);
6052 return RETURN_OK;
6053 }
6054 }
6055 return RETURN_OK;
6056#endif
6057}
6058
6059// 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.
6060INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6061{
6062 return RETURN_ERR;
6063}
6064
6065// gets the vlan ID for this ap from an internal enviornment variable
6066INT wifi_getApVlanID(INT apIndex, INT *output_int)
6067{
developer30423732022-12-01 16:17:49 +08006068 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08006069 {
6070 *output_int=100;
6071 return RETURN_OK;
6072 }
6073
6074 return RETURN_ERR;
6075}
6076
6077// sets the vlan ID for this ap to an internal enviornment variable
6078INT wifi_setApVlanID(INT apIndex, INT vlanId)
6079{
6080 //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)
6081 return RETURN_ERR;
6082}
6083
6084// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6085INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6086{
6087 snprintf(bridgeName, 32, "brlan0");
6088 snprintf(IP, 32, "10.0.0.1");
6089 snprintf(subnet, 32, "255.255.255.0");
6090
6091 return RETURN_OK;
6092}
6093
6094//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6095INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6096{
6097 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6098 return RETURN_ERR;
6099}
6100
6101// reset the vlan configuration for this ap
6102INT wifi_resetApVlanCfg(INT apIndex)
6103{
developerf5fef612022-09-20 19:38:26 +08006104 char original_config_file[64] = {0};
6105 char current_config_file[64] = {0};
6106 char buf[64] = {0};
6107 char cmd[64] = {0};
6108 char vlan_file[64] = {0};
6109 char vlan_tagged_interface[16] = {0};
6110 char vlan_bridge[16] = {0};
6111 char vlan_naming[16] = {0};
6112 struct params list[4] = {0};
6113 wifi_band band;
6114
6115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6116
6117 band = wifi_index_to_band(apIndex);
6118 if (band == band_2_4)
6119 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006120 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08006121 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006122 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08006123 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6124
6125 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6126
6127 if (strlen(vlan_file) == 0)
6128 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08006129
developerf5fef612022-09-20 19:38:26 +08006130 // The file should exist or this vap would not work.
6131 if (access(vlan_file, F_OK) != 0) {
6132 sprintf(cmd, "touch %s", vlan_file);
6133 _syscmd(cmd, buf, sizeof(buf));
6134 }
6135 list[0].name = "vlan_file";
6136 list[0].value = vlan_file;
6137
6138 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6139 list[1].name = "vlan_tagged_interface";
6140 list[1].value = vlan_tagged_interface;
6141
6142 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6143 list[2].name = "vlan_bridge";
6144 list[2].value = vlan_bridge;
6145
6146 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6147 list[3].name = "vlan_naming";
6148 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08006149
developerf5fef612022-09-20 19:38:26 +08006150 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6151 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08006152 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08006153 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08006154
developerf5fef612022-09-20 19:38:26 +08006155 // restart this ap
6156 wifi_setApEnable(apIndex, FALSE);
6157 wifi_setApEnable(apIndex, TRUE);
6158
6159 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6160
6161 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006162}
6163
6164// 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.
6165INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6166{
6167 return RETURN_ERR;
6168}
6169
6170// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6171INT wifi_startHostApd()
6172{
6173 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6174 system("systemctl start hostapd.service");
6175 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6176 return RETURN_OK;
6177 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6178}
6179
6180// stops hostapd
6181INT wifi_stopHostApd()
6182{
6183 char cmd[128] = {0};
6184 char buf[128] = {0};
6185
6186 sprintf(cmd,"systemctl stop hostapd");
6187 _syscmd(cmd, buf, sizeof(buf));
6188
6189 return RETURN_OK;
6190}
6191
6192// restart hostapd dummy function
6193INT wifi_restartHostApd()
6194{
6195 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6196 system("systemctl restart hostapd-global");
6197 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6198
6199 return RETURN_OK;
6200}
6201
6202static int align_hostapd_config(int index)
6203{
6204 ULONG lval;
6205 wifi_getRadioChannel(index%2, &lval);
6206 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08006207 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006208}
6209
6210// sets the AP enable status variable for the specified ap.
6211INT wifi_setApEnable(INT apIndex, BOOL enable)
6212{
developerd946fd62022-12-08 18:03:28 +08006213 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006214 char config_file[MAX_BUF_SIZE] = {0};
6215 char cmd[MAX_CMD_SIZE] = {0};
6216 char buf[MAX_BUF_SIZE] = {0};
6217 BOOL status;
developer033b37b2022-10-18 11:27:46 +08006218 int max_radio_num = 0;
6219 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08006220
6221 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08006222
6223 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08006224 if (enable == status)
6225 return RETURN_OK;
6226
developerac6f1142022-12-20 19:26:35 +08006227 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006228 return RETURN_ERR;
6229
developer06a01d92022-09-07 16:32:39 +08006230 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08006231 int radioIndex = apIndex % max_radio_num;
6232 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08006233 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6234 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08006235 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006236 _syscmd(cmd, buf, sizeof(buf));
developer2f18b9f2023-03-17 19:32:57 +08006237 if (!(apIndex/max_radio_num)) {
6238 sprintf(cmd, "iw %s del", interface_name);
6239 _syscmd(cmd, buf, sizeof(buf));
6240 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6241 _syscmd(cmd, buf, sizeof(buf));
6242 }
developer033b37b2022-10-18 11:27:46 +08006243 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08006244 _syscmd(cmd, buf, sizeof(buf));
6245 }
6246 else {
developerd946fd62022-12-08 18:03:28 +08006247 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006248 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006249 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006250 _syscmd(cmd, buf, sizeof(buf));
6251 }
developera77d84b2023-02-22 16:10:50 +08006252
developer431128d2022-12-16 15:30:41 +08006253 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006254 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006255 _syscmd(cmd, buf, sizeof(buf));
6256 //Wait for wifi up/down to apply
6257 return RETURN_OK;
6258}
6259
6260// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6261INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6262{
developerd946fd62022-12-08 18:03:28 +08006263 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006264 char cmd[MAX_CMD_SIZE] = {'\0'};
6265 char buf[MAX_BUF_SIZE] = {'\0'};
6266
6267 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6268 return RETURN_ERR;
6269
6270 *output_bool = 0;
6271
6272 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6273 {
developerac6f1142022-12-20 19:26:35 +08006274 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006275 *output_bool = FALSE;
6276 return RETURN_OK;
6277 }
6278 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006279 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6280 }
6281
6282 return RETURN_OK;
6283}
6284
6285// Outputs the AP "Enabled" "Disabled" status from driver
6286INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6287{
6288 char cmd[128] = {0};
6289 char buf[128] = {0};
6290 BOOL output_bool;
6291
6292 if ( NULL == output_string)
6293 return RETURN_ERR;
6294 wifi_getApEnable(apIndex,&output_bool);
6295
6296 if(output_bool == 1)
6297 snprintf(output_string, 32, "Up");
6298 else
6299 snprintf(output_string, 32, "Disable");
6300
6301 return RETURN_OK;
6302}
6303
6304//Indicates whether or not beacons include the SSID name.
6305// outputs a 1 if SSID on the AP is enabled, else outputs 0
6306INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6307{
6308 //get the running status
6309 char config_file[MAX_BUF_SIZE] = {0};
6310 char buf[16] = {0};
6311
6312 if (!output)
6313 return RETURN_ERR;
6314
6315 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6316 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006317 // default is enable
6318 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6319 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006320
6321 return RETURN_OK;
6322}
6323
6324// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6325INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6326{
6327 //store the config, apply instantly
6328 char config_file[MAX_BUF_SIZE] = {0};
6329 struct params list;
6330
6331 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6332 list.name = "ignore_broadcast_ssid";
6333 list.value = enable?"0":"1";
6334
6335 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6336 wifi_hostapdWrite(config_file, &list, 1);
6337 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6338 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006339 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08006340 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6341
6342 return RETURN_OK;
6343}
6344
6345//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6346INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6347{
6348 //get the running status
6349 if(!output_uint)
6350 return RETURN_ERR;
6351 *output_uint=16;
6352 return RETURN_OK;
6353}
6354
6355INT wifi_setApRetryLimit(INT apIndex, UINT number)
6356{
6357 //apply instantly
6358 return RETURN_ERR;
6359}
6360
6361//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6362INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6363{
6364 if(!output)
6365 return RETURN_ERR;
6366 *output=TRUE;
6367 return RETURN_OK;
6368}
6369
6370//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6371INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6372{
6373 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006374 char cmd[128] = {0};
6375 char buf[128] = {0};
6376 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006377 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006378
developer0b246d12022-09-30 15:24:20 +08006379 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006380
developer0b246d12022-09-30 15:24:20 +08006381 wifi_getMaxRadioNumber(&max_radio_num);
6382 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006383 phyId = radio_index_to_phy(radioIndex);
6384 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006385 _syscmd(cmd,buf, sizeof(buf));
6386
6387 if (strlen(buf) > 0)
6388 *output = true;
6389
6390 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006391
developer06a01d92022-09-07 16:32:39 +08006392 return RETURN_OK;
6393}
6394
6395//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6396INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6397{
6398 //get the running status from driver
6399 if(!output)
6400 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006401
6402 char config_file[MAX_BUF_SIZE] = {0};
6403 char buf[16] = {0};
6404
6405 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6406 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006407 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006408 *output = TRUE;
6409 else
6410 *output = FALSE;
6411
developer06a01d92022-09-07 16:32:39 +08006412 return RETURN_OK;
6413}
6414
6415// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6416INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6417{
6418 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006419 char config_file[MAX_BUF_SIZE] = {0};
6420 struct params list;
6421
6422 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6423 list.name = "wmm_enabled";
6424 list.value = enable?"1":"0";
6425
6426 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6427 wifi_hostapdWrite(config_file, &list, 1);
6428 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6429 wifi_reloadAp(apIndex);
6430 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6431
6432 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006433}
6434
6435//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.
6436INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6437{
6438 //get the running status from driver
6439 if(!output)
6440 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006441
6442 char config_file[128] = {0};
6443 char buf[16] = {0};
6444
6445 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6446 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6447 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6448 *output = TRUE;
6449 else
6450 *output = FALSE;
6451
developer06a01d92022-09-07 16:32:39 +08006452 return RETURN_OK;
6453}
6454
6455// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6456INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6457{
6458 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006459 char config_file[MAX_BUF_SIZE] = {0};
6460 struct params list;
6461
6462 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6463 list.name = "uapsd_advertisement_enabled";
6464 list.value = enable?"1":"0";
6465
6466 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6467 wifi_hostapdWrite(config_file, &list, 1);
6468 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6469 wifi_reloadAp(apIndex);
6470 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6471
6472 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006473}
6474
developer6daeb3f2022-09-30 13:36:39 +08006475// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006476INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6477{
developerd946fd62022-12-08 18:03:28 +08006478 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006479 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6480 char cmd[128] = {0};
6481 char buf[128] = {0};
6482 char ack_filepath[128] = {0};
6483 uint16_t bitmap = 0;
6484 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6485 FILE *f = NULL;
6486
6487 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6488
6489 // Get current setting
6490 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6491 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6492 _syscmd(cmd, buf, sizeof(buf));
6493 if (strlen(buf) > 0)
6494 bitmap = strtoul(buf, NULL, 10);
6495
6496 bitmap = strtoul(buf, NULL, 10);
6497
6498 if (ackPolicy == TRUE) { // True, unset this class
6499 bitmap &= ~class_map[class];
6500 } else { // False, set this class
6501 bitmap |= class_map[class];
6502 }
6503
6504 f = fopen(ack_filepath, "w");
6505 if (f == NULL) {
6506 fprintf(stderr, "%s: fopen failed\n", __func__);
6507 return RETURN_ERR;
6508 }
6509 fprintf(f, "%hu", bitmap);
6510 fclose(f);
6511
developerac6f1142022-12-20 19:26:35 +08006512 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006513 return RETURN_ERR;
6514 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006515 _syscmd(cmd, buf, sizeof(buf));
6516
6517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6518 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006519}
6520
6521//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.
6522INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6523{
6524 //get the running status from driver
6525 if(!output_uint)
6526 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006527
6528 char output[16]={'\0'};
6529 char config_file[MAX_BUF_SIZE] = {0};
6530
6531 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6532 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6533 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6534 else {
6535 int device_num = atoi(output);
6536 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6537 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6538 return RETURN_ERR;
6539 }
6540 else {
6541 *output_uint = device_num;
6542 }
6543 }
6544
developer06a01d92022-09-07 16:32:39 +08006545 return RETURN_OK;
6546}
6547
6548INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6549{
6550 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006551 char str[MAX_BUF_SIZE]={'\0'};
6552 char cmd[MAX_CMD_SIZE]={'\0'};
6553 struct params params;
6554 char config_file[MAX_BUF_SIZE] = {0};
6555
6556 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006557 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006558 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006559 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006560 }
6561 sprintf(str, "%d", number);
6562 params.name = "max_num_sta";
6563 params.value = str;
6564
6565 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6566 int ret = wifi_hostapdWrite(config_file, &params, 1);
6567 if (ret) {
6568 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6569 ,__func__, ret);
6570 }
6571
6572 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6573 if (ret) {
6574 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6575 ,__func__, ret);
6576 }
6577 wifi_reloadAp(apIndex);
6578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6579
6580 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006581}
6582
6583//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.
6584INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6585{
6586 //get the current threshold
6587 if(!output_uint)
6588 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006589 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6590 if (*output_uint == 0)
6591 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006592 return RETURN_OK;
6593}
6594
6595INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6596{
6597 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006598 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6599 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006600 return RETURN_ERR;
6601}
6602
6603//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.
6604INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6605{
6606 if(!output_uint)
6607 return RETURN_ERR;
6608 *output_uint = 3;
6609 return RETURN_OK;
6610}
6611
6612//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6613INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6614{
6615 if(!output_uint)
6616 return RETURN_ERR;
6617 *output_uint = 3;
6618 return RETURN_OK;
6619}
6620
6621//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.
6622INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6623{
6624 if(!output_in_seconds)
6625 return RETURN_ERR;
6626 *output_in_seconds = 0;
6627 return RETURN_OK;
6628}
6629
6630//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
6631INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6632{
6633 if(!output || apIndex>=MAX_APS)
6634 return RETURN_ERR;
6635 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006636 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006637 return RETURN_OK;
6638}
6639
6640//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6641INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6642{
developer587c1b62022-09-27 15:58:59 +08006643 char config_file[128] = {0};
6644 char wpa[16] = {0};
6645 char key_mgmt[64] = {0};
6646 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006647 if (!output)
6648 return RETURN_ERR;
6649
6650 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006651 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006652
developer587c1b62022-09-27 15:58:59 +08006653 strcpy(output, "None");//Copying "None" to output string for default case
6654 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006655 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006656 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006657 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006658 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006659 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006660 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006661 snprintf(output, 32, "WPA-WPA2-Personal");
6662
developer72ec5572023-01-05 16:27:13 +08006663 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6664 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006665 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006666 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006667 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006668 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006669 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006670 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006671 snprintf(output, 32, "WPA-WPA2-Enterprise");
6672 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006673 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006674 snprintf(output, 32, "WPA3-Personal");
6675 else
developer4a359672022-10-13 15:30:46 +08006676 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006677 }
developer06a01d92022-09-07 16:32:39 +08006678
6679 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6680 return RETURN_OK;
6681#if 0
6682 //TODO: need to revisit below implementation
6683 char securityType[32], authMode[32];
6684 int enterpriseMode=0;
6685
6686 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6687 if(!output)
6688 return RETURN_ERR;
6689
6690 wifi_getApBeaconType(apIndex, securityType);
6691 strcpy(output,"None");//By default, copying "None" to output string
6692 if (strncmp(securityType,"None", strlen("None")) == 0)
6693 return RETURN_OK;
6694
6695 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6696 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6697
6698 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6699 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6700 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6701 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6702 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6703 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6704 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6705
6706 return RETURN_OK;
6707#endif
6708}
6709
6710INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6711{
6712 char securityType[32];
6713 char authMode[32];
6714
6715 //store settings and wait for wifi up to apply
6716 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6717 if(!encMode)
6718 return RETURN_ERR;
6719
developer06a01d92022-09-07 16:32:39 +08006720 if (strcmp(encMode, "None")==0)
6721 {
6722 strcpy(securityType,"None");
6723 strcpy(authMode,"None");
6724 }
6725 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6726 {
6727 strcpy(securityType,"WPAand11i");
6728 strcpy(authMode,"PSKAuthentication");
6729 }
6730 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6731 {
6732 strcpy(securityType,"WPAand11i");
6733 strcpy(authMode,"EAPAuthentication");
6734 }
6735 else if (strcmp(encMode, "WPA-Personal")==0)
6736 {
6737 strcpy(securityType,"WPA");
6738 strcpy(authMode,"PSKAuthentication");
6739 }
6740 else if (strcmp(encMode, "WPA-Enterprise")==0)
6741 {
6742 strcpy(securityType,"WPA");
6743 strcpy(authMode,"EAPAuthentication");
6744 }
6745 else if (strcmp(encMode, "WPA2-Personal")==0)
6746 {
6747 strcpy(securityType,"11i");
6748 strcpy(authMode,"PSKAuthentication");
6749 }
6750 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6751 {
6752 strcpy(securityType,"11i");
6753 strcpy(authMode,"EAPAuthentication");
6754 }
developer587c1b62022-09-27 15:58:59 +08006755 else if (strcmp(encMode, "WPA3-Personal") == 0)
6756 {
6757 strcpy(securityType,"11i");
6758 strcpy(authMode,"SAEAuthentication");
6759 }
developer4a359672022-10-13 15:30:46 +08006760 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006761 {
6762 strcpy(securityType, "11i");
6763 strcpy(authMode, "PSK-SAEAuthentication");
6764 }
developer587c1b62022-09-27 15:58:59 +08006765 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6766 {
6767 strcpy(securityType,"11i");
6768 strcpy(authMode,"EAP_192-bit_Authentication");
6769 }
developer5c9fee82023-01-13 14:44:16 +08006770 else if (strcmp(encMode, "OWE") == 0)
6771 {
6772 strcpy(securityType,"11i");
6773 strcpy(authMode,"Enhanced_Open");
6774 }
developer06a01d92022-09-07 16:32:39 +08006775 else
6776 {
6777 strcpy(securityType,"None");
6778 strcpy(authMode,"None");
6779 }
6780 wifi_setApBeaconType(apIndex, securityType);
6781 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6782 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6783
6784 return RETURN_OK;
6785}
6786
6787
developer4b102122023-02-15 10:53:03 +08006788// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006789//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006790INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6791{
developer30423732022-12-01 16:17:49 +08006792 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006793 char config_file[MAX_BUF_SIZE] = {0};
6794
6795 if(output_string==NULL)
6796 return RETURN_ERR;
6797
6798 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6799 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6800
6801 if(strcmp(buf,"0")==0)
6802 {
6803 printf("wpa_mode is %s ......... \n",buf);
6804 return RETURN_ERR;
6805 }
6806
6807 wifi_dbg_printf("\nFunc=%s\n",__func__);
6808 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006809 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006810 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6811
6812 return RETURN_OK;
6813}
6814
developer4b102122023-02-15 10:53:03 +08006815// Set PreSharedKey associated with a Access Point.
6816// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006817INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6818{
6819 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6820 struct params params={'\0'};
6821 int ret;
6822 char config_file[MAX_BUF_SIZE] = {0};
6823
6824 if(NULL == preSharedKey)
6825 return RETURN_ERR;
6826
developer4b102122023-02-15 10:53:03 +08006827 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006828
developer4b102122023-02-15 10:53:03 +08006829 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006830 {
developer4b102122023-02-15 10:53:03 +08006831 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006832 return RETURN_ERR;
6833 }
6834 params.value = preSharedKey;
6835 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6836 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006837 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006838 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006839 wifi_reloadAp(apIndex);
6840 }
developer06a01d92022-09-07 16:32:39 +08006841 return ret;
6842 //TODO: call hostapd_cli for dynamic_config_control
6843}
6844
6845//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6846// outputs the passphrase, maximum 63 characters
6847INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6848{
6849 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6850
6851 wifi_dbg_printf("\nFunc=%s\n",__func__);
6852 if (NULL == output_string)
6853 return RETURN_ERR;
6854
6855 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6856 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6857 if(strcmp(buf,"0")==0)
6858 {
6859 printf("wpa_mode is %s ......... \n",buf);
6860 return RETURN_ERR;
6861 }
6862
6863 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6864 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6865
6866 return RETURN_OK;
6867}
6868
6869// sets the passphrase enviornment variable, max 63 characters
6870INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6871{
6872 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6873 struct params params={'\0'};
6874 char config_file[MAX_BUF_SIZE] = {0};
6875 int ret;
6876
6877 if(NULL == passPhrase)
6878 return RETURN_ERR;
6879
6880 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6881 {
6882 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6883 return RETURN_ERR;
6884 }
6885 params.name = "wpa_passphrase";
6886 params.value = passPhrase;
6887 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6888 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006889 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006890 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006891 wifi_reloadAp(apIndex);
6892 }
developer06a01d92022-09-07 16:32:39 +08006893
6894 return ret;
6895}
6896
6897//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.
6898INT wifi_setApSecurityReset(INT apIndex)
6899{
developer8d583982022-09-20 11:28:22 +08006900 char original_config_file[64] = {0};
6901 char current_config_file[64] = {0};
6902 char buf[64] = {0};
6903 char cmd[64] = {0};
6904 char wpa[4] = {0};
6905 char wpa_psk[64] = {0};
6906 char wpa_passphrase[64] = {0};
6907 char wpa_psk_file[128] = {0};
6908 char wpa_key_mgmt[64] = {0};
6909 char wpa_pairwise[32] = {0};
6910 wifi_band band;
6911 struct params list[6];
6912
6913 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6914
6915 band = wifi_index_to_band(apIndex);
6916 if (band == band_2_4)
6917 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006918 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006919 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006920 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006921 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6922 else
6923 return RETURN_ERR;
6924
6925 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6926 list[0].name = "wpa";
6927 list[0].value = wpa;
6928
6929 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6930 list[1].name = "wpa_psk";
6931 list[1].value = wpa_psk;
6932
6933 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6934 list[2].name = "wpa_passphrase";
6935 list[2].value = wpa_passphrase;
6936
6937 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6938
6939 if (strlen(wpa_psk_file) == 0)
6940 strcpy(wpa_psk_file, PSK_FILE);
6941
6942 if (access(wpa_psk_file, F_OK) != 0) {
6943 sprintf(cmd, "touch %s", wpa_psk_file);
6944 _syscmd(cmd, buf, sizeof(buf));
6945 }
6946 list[3].name = "wpa_psk_file";
6947 list[3].value = wpa_psk_file;
6948
6949 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6950 list[4].name = "wpa_key_mgmt";
6951 list[4].value = wpa_key_mgmt;
6952
6953 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6954 list[5].name = "wpa_pairwise";
6955 list[5].value = wpa_pairwise;
6956
6957 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6958 wifi_hostapdWrite(current_config_file, list, 6);
6959
6960 wifi_setApEnable(apIndex, FALSE);
6961 wifi_setApEnable(apIndex, TRUE);
6962
6963 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6964 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006965}
6966
6967//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).
6968INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6969{
developer8f2ddd52022-09-13 15:39:24 +08006970 char config_file[64] = {0};
6971 char buf[64] = {0};
6972 char cmd[256] = {0};
6973
6974 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6975
developer06a01d92022-09-07 16:32:39 +08006976 if(!IP_output || !Port_output || !RadiusSecret_output)
6977 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006978
developer8f2ddd52022-09-13 15:39:24 +08006979 // Read the first matched config
6980 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6981 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6982 _syscmd(cmd, buf, sizeof(buf));
6983 strncpy(IP_output, buf, 64);
6984
6985 memset(buf, 0, sizeof(buf));
6986 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6987 _syscmd(cmd, buf, sizeof(buf));
6988 *Port_output = atoi(buf);
6989
6990 memset(buf, 0, sizeof(buf));
6991 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6992 _syscmd(cmd, buf, sizeof(buf));
6993 strncpy(RadiusSecret_output, buf, 64);
6994
6995 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006996 return RETURN_OK;
6997}
6998
6999INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7000{
developer8f2ddd52022-09-13 15:39:24 +08007001 char config_file[64] = {0};
7002 char port_str[8] = {0};
7003 char cmd[256] = {0};
7004 char buf[128] = {0};
7005
7006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007007 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7008 return RETURN_ERR;
7009
7010 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7011 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007012
7013 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7014
7015 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7016 _syscmd(cmd, buf, sizeof(buf));
7017 memset(cmd, 0, sizeof(cmd));
7018
7019 snprintf(port_str, sizeof(port_str), "%d", port);
7020 if (strlen(buf) == 0)
7021 // Append
7022 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7023 "auth_server_addr=%s\\n"
7024 "auth_server_port=%s\\n"
7025 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7026 else {
7027 // Delete the three lines setting after the "# radius 1" comment
7028 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7029 _syscmd(cmd, buf, sizeof(buf));
7030 memset(cmd, 0, sizeof(cmd));
7031 // Use "# radius 1" comment to find the location to insert the radius setting
7032 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7033 "# radius 1\\n"
7034 "auth_server_addr=%s\\n"
7035 "auth_server_port=%s\\n"
7036 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7037 }
7038 if(_syscmd(cmd, buf, sizeof(buf))) {
7039 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7040 return RETURN_ERR;
7041 }
7042
7043 wifi_reloadAp(apIndex);
7044 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7045 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007046}
7047
7048INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7049{
developer8f2ddd52022-09-13 15:39:24 +08007050 char config_file[64] = {0};
7051 char buf[64] = {0};
7052 char cmd[256] = {0};
7053
7054 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7055
developer06a01d92022-09-07 16:32:39 +08007056 if(!IP_output || !Port_output || !RadiusSecret_output)
7057 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007058
7059 // Read the second matched config
7060 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7061 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7062 _syscmd(cmd, buf, sizeof(buf));
7063 strncpy(IP_output, buf, 64);
7064
7065 memset(buf, 0, sizeof(buf));
7066 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7067 _syscmd(cmd, buf, sizeof(buf));
7068 *Port_output = atoi(buf);
7069
7070 memset(buf, 0, sizeof(buf));
7071 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7072 _syscmd(cmd, buf, sizeof(buf));
7073 strncpy(RadiusSecret_output, buf, 64);
7074
7075 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007076 return RETURN_OK;
7077}
7078
7079INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7080{
developer8f2ddd52022-09-13 15:39:24 +08007081 char config_file[64] = {0};
7082 char port_str[8] = {0};
7083 char cmd[256] = {0};
7084 char buf[128] = {0};
7085
7086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007087 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7088 return RETURN_ERR;
7089
7090 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7091 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007092
7093 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7094
7095 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7096 _syscmd(cmd, buf, sizeof(buf));
7097 memset(cmd, 0, sizeof(cmd));
7098
7099 snprintf(port_str, sizeof(port_str), "%d", port);
7100 if (strlen(buf) == 0)
7101 // Append
7102 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7103 "auth_server_addr=%s\\n"
7104 "auth_server_port=%s\\n"
7105 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7106 else {
7107 // Delete the three lines setting after the "# radius 2" comment
7108 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7109 _syscmd(cmd, buf, sizeof(buf));
7110 memset(cmd, 0, sizeof(cmd));
7111 // Use "# radius 2" comment to find the location to insert the radius setting
7112 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7113 "# radius 2\\n"
7114 "auth_server_addr=%s\\n"
7115 "auth_server_port=%s\\n"
7116 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7117 }
7118 if(_syscmd(cmd, buf, sizeof(buf))) {
7119 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7120 return RETURN_ERR;
7121 }
7122
7123 wifi_reloadAp(apIndex);
7124 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7125 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007126}
7127
7128//RadiusSettings
7129INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7130{
7131 if(!output)
7132 return RETURN_ERR;
7133
7134 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7135 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7136 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7137 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7138 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7139 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.
7140 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7141 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7142 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7143 //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.
7144
7145 return RETURN_OK;
7146}
7147
7148INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7149{
7150 //store the paramters, and apply instantly
7151 return RETURN_ERR;
7152}
7153
7154//Device.WiFi.AccessPoint.{i}.WPS.Enable
7155//Enables or disables WPS functionality for this access point.
7156// outputs the WPS enable state of this ap in output_bool
7157INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7158{
developerd946fd62022-12-08 18:03:28 +08007159 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007160 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer613892e2023-09-21 16:33:35 +08007161
7162 *output_bool=FALSE;
developer5b398df2022-11-17 20:39:48 +08007163 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08007164 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08007165 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer613892e2023-09-21 16:33:35 +08007166 return RETURN_OK;
developerd946fd62022-12-08 18:03:28 +08007167 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007168 _syscmd(cmd, buf, sizeof(buf));
7169 if(strstr(buf, "configured"))
7170 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08007171
7172 return RETURN_OK;
developer613892e2023-09-21 16:33:35 +08007173}
developer06a01d92022-09-07 16:32:39 +08007174
7175//Device.WiFi.AccessPoint.{i}.WPS.Enable
7176// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7177INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7178{
7179 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08007180 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08007181 struct params params;
7182
developer06a01d92022-09-07 16:32:39 +08007183 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7184 //store the paramters, and wait for wifi up to apply
7185 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08007186 if (enable == TRUE) {
7187 wifi_getApBeaconType(apIndex, buf);
7188 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7189 params.value = "1";
7190 else // If ap set encryption
7191 params.value = "2";
7192 } else {
7193 params.value = "0";
7194 }
developer06a01d92022-09-07 16:32:39 +08007195
7196 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7197 wifi_hostapdWrite(config_file, &params, 1);
7198 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7199 wifi_reloadAp(apIndex);
7200
7201 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7202 return RETURN_OK;
7203}
7204
7205//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
7206INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7207{
7208 if(!output)
7209 return RETURN_ERR;
7210 snprintf(output, 128, "PushButton,PIN");
7211 return RETURN_OK;
7212}
7213
7214//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7215//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.
7216// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7217INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7218{
7219 if(!output)
7220 return RETURN_ERR;
7221 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7222
7223 return RETURN_OK;
7224}
7225
7226//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7227// 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
7228INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7229{
7230 //apply instantly. No setting need to be stored.
7231 char methods[MAX_BUF_SIZE], *token, *next_token;
7232 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7233 struct params params;
7234
developer5b398df2022-11-17 20:39:48 +08007235 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08007236 return RETURN_ERR;
7237 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7238 //store the paramters, and wait for wifi up to apply
7239
7240 snprintf(methods, sizeof(methods), "%s", methodString);
7241 for(token=methods; *token; token=next_token)
7242 {
7243 strtok_r(token, ",", &next_token);
7244 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7245 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7246 else if(*token=='E')
7247 {
7248 if(!strcmp(methods, "Ethernet"))
7249 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7250 else if(!strcmp(methods, "ExternalNFCToken"))
7251 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7252 else
7253 printf("%s: Unknown WpsConfigMethod\n", __func__);
7254 }
7255 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7256 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7257 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7258 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7259 else if(*token=='P' )
7260 {
7261 if(!strcmp(token, "PushButton"))
developer894affa2023-05-10 18:13:19 +08007262 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer06a01d92022-09-07 16:32:39 +08007263 else if(!strcmp(token, "PIN"))
7264 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7265 else
7266 printf("%s: Unknown WpsConfigMethod\n", __func__);
7267 }
7268 else
7269 printf("%s: Unknown WpsConfigMethod\n", __func__);
7270 }
7271 params.name = "config_methods";
7272 params.value = config_methods;
7273 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7274 wifi_hostapdWrite(config_file, &params, 1);
7275 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7276 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7277
7278 return RETURN_OK;
7279}
7280
7281// outputs the pin value, ulong_pin must be allocated by the caller
7282INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7283{
7284 char buf[MAX_BUF_SIZE] = {0};
7285 char cmd[MAX_CMD_SIZE] = {0};
7286
developer5b398df2022-11-17 20:39:48 +08007287 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007288 return RETURN_ERR;
7289 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7290 _syscmd(cmd, buf, sizeof(buf));
7291 if(strlen(buf) > 0)
7292 *output_ulong=strtoul(buf, NULL, 10);
7293
7294 return RETURN_OK;
7295}
7296
7297// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7298INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7299{
7300 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7301 char ap_pin[16] = {0};
7302 char buf[MAX_BUF_SIZE] = {0};
7303 char config_file[MAX_BUF_SIZE] = {0};
7304 ULONG prev_pin = 0;
7305 struct params params;
7306
developer06a01d92022-09-07 16:32:39 +08007307 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7308 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7309 params.name = "ap_pin";
7310 params.value = ap_pin;
7311 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7312 wifi_hostapdWrite(config_file, &params, 1);
7313 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7314 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7315
7316 return RETURN_OK;
7317}
7318
7319// Output string is either Not configured or Configured, max 32 characters
7320INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7321{
developerd946fd62022-12-08 18:03:28 +08007322 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007323 char cmd[MAX_CMD_SIZE];
7324 char buf[MAX_BUF_SIZE]={0};
7325
developer5b398df2022-11-17 20:39:48 +08007326 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007327 return RETURN_ERR;
7328 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7329 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007330 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007331 return RETURN_ERR;
7332 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007333 _syscmd(cmd, buf, sizeof(buf));
7334
developer348e3d92022-09-13 14:48:41 +08007335 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007336 snprintf(output_string, 32, "Configured");
7337 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7338
7339 return RETURN_OK;
7340}
7341
7342// sets the WPS pin for this AP
7343INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7344{
developerd946fd62022-12-08 18:03:28 +08007345 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007346 char cmd[MAX_CMD_SIZE];
7347 char buf[MAX_BUF_SIZE]={0};
7348 BOOL enable;
7349
developer06a01d92022-09-07 16:32:39 +08007350 wifi_getApEnable(apIndex, &enable);
7351 if (!enable)
7352 return RETURN_ERR;
7353 wifi_getApWpsEnable(apIndex, &enable);
7354 if (!enable)
7355 return RETURN_ERR;
7356
developerac6f1142022-12-20 19:26:35 +08007357 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007358 return RETURN_ERR;
7359 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007360 _syscmd(cmd, buf, sizeof(buf));
7361 if((strstr(buf, "OK"))!=NULL)
7362 return RETURN_OK;
7363
7364 return RETURN_ERR;
7365}
7366
7367// This function is called when the WPS push button has been pressed for this AP
7368INT wifi_setApWpsButtonPush(INT apIndex)
7369{
7370 char cmd[MAX_CMD_SIZE];
7371 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007372 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007373 BOOL enable=FALSE;
7374
developer06a01d92022-09-07 16:32:39 +08007375 wifi_getApEnable(apIndex, &enable);
7376 if (!enable)
7377 return RETURN_ERR;
7378
7379 wifi_getApWpsEnable(apIndex, &enable);
7380 if (!enable)
7381 return RETURN_ERR;
7382
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
developer900e2b72023-05-23 10:23:48 +08007386 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 +08007387 _syscmd(cmd, buf, sizeof(buf));
7388
7389 if((strstr(buf, "OK"))!=NULL)
7390 return RETURN_OK;
7391 return RETURN_ERR;
7392}
7393
7394// cancels WPS mode for this AP
7395INT wifi_cancelApWPS(INT apIndex)
7396{
developerd946fd62022-12-08 18:03:28 +08007397 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007398 char cmd[MAX_CMD_SIZE];
7399 char buf[MAX_BUF_SIZE]={0};
7400
developerac6f1142022-12-20 19:26:35 +08007401 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007402 return RETURN_ERR;
7403 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007404 _syscmd(cmd,buf, sizeof(buf));
7405
7406 if((strstr(buf, "OK"))!=NULL)
7407 return RETURN_OK;
7408 return RETURN_ERR;
7409}
7410
7411//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7412//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7413INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7414{
developerd946fd62022-12-08 18:03:28 +08007415 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007416 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007417 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007418 char cmd[256] = {0}, buf[2048] = {0};
7419 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007420 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007421 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007422 wifi_associated_dev_t *dev=NULL;
7423
7424 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7425 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007426 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007427 return RETURN_ERR;
7428 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007429 _syscmd(cmd,buf,sizeof(buf));
7430 *output_array_size = atoi(buf);
7431
7432 if (*output_array_size <= 0)
7433 return RETURN_OK;
7434
7435 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7436 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007437 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007438 _syscmd(cmd,buf,sizeof(buf));
7439 f = fopen("/tmp/connected_devices.txt", "r");
7440 if (f==NULL)
7441 {
7442 *output_array_size=0;
7443 return RETURN_ERR;
7444 }
developer30423732022-12-01 16:17:49 +08007445 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007446 {
7447 param = strtok(line,"=");
7448 value = strtok(NULL,"=");
7449
7450 if( strcmp("flags",param) == 0 )
7451 {
7452 value[strlen(value)-1]='\0';
7453 if(strstr (value,"AUTHORIZED") != NULL )
7454 {
7455 dev[auth_temp].cli_AuthenticationState = 1;
7456 dev[auth_temp].cli_Active = 1;
7457 auth_temp++;
7458 read_flag=1;
7459 }
7460 }
7461 if(read_flag==1)
7462 {
7463 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7464 {
7465 value[strlen(value)-1]='\0';
7466 sscanf(value, "%x:%x:%x:%x:%x:%x",
7467 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7468 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7469 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7470 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7471 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7472 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7473 mac_temp++;
7474 read_flag=0;
7475 }
7476 }
7477 }
7478 *output_array_size = auth_temp;
7479 auth_temp=0;
7480 mac_temp=0;
7481 free(line);
7482 fclose(f);
7483 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7484 return RETURN_OK;
7485}
7486
7487#define MACADDRESS_SIZE 6
7488
7489INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7490{
7491 FILE *fp = NULL;
7492 char str[MAX_BUF_SIZE] = {0};
7493 int wificlientindex = 0 ;
7494 int count = 0;
7495 int signalstrength = 0;
7496 int arr[MACADDRESS_SIZE] = {0};
7497 unsigned char mac[MACADDRESS_SIZE] = {0};
7498 UINT wifi_count = 0;
7499 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7500 char pipeCmd[MAX_CMD_SIZE] = {0};
7501
7502 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7503 *output_array_size = 0;
7504 *associated_dev_array = NULL;
7505
7506 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7507 fp = popen(pipeCmd, "r");
7508 if (fp == NULL)
7509 {
7510 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7511 return RETURN_ERR;
7512 }
7513
7514 /* Read the output a line at a time - output it. */
7515 fgets(str, sizeof(str)-1, fp);
7516 wifi_count = (unsigned int) atoi ( str );
7517 *output_array_size = wifi_count;
7518 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7519 pclose(fp);
7520
7521 if(wifi_count == 0)
7522 {
7523 return RETURN_OK;
7524 }
7525 else
7526 {
7527 wifi_associated_dev3_t* temp = NULL;
7528 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7529 if(temp == NULL)
7530 {
7531 printf("Error Statement. Insufficient memory \n");
7532 return RETURN_ERR;
7533 }
7534
7535 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7536 system(pipeCmd);
7537 memset(pipeCmd,0,sizeof(pipeCmd));
7538 if(apIndex == 0)
7539 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7540 else if(apIndex == 1)
7541 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7542 system(pipeCmd);
7543
7544 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7545 if(fp == NULL)
7546 {
7547 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007548 free(temp);
developer06a01d92022-09-07 16:32:39 +08007549 return RETURN_ERR;
7550 }
7551 fclose(fp);
7552
developer30423732022-12-01 16:17:49 +08007553 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007554 fp = popen(pipeCmd, "r");
7555 if(fp)
7556 {
7557 for(count =0 ; count < wifi_count; count++)
7558 {
7559 fgets(str, MAX_BUF_SIZE, fp);
7560 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7561 {
7562 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7563 {
7564 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7565
7566 }
7567 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7568 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]);
7569 }
7570 temp[count].cli_AuthenticationState = 1; //TODO
7571 temp[count].cli_Active = 1; //TODO
7572 }
7573 pclose(fp);
7574 }
7575
developer30423732022-12-01 16:17:49 +08007576 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 +08007577 fp = popen(pipeCmd, "r");
7578 if(fp)
7579 {
7580 pclose(fp);
7581 }
7582 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7583 if(fp)
7584 {
7585 for(count =0 ; count < wifi_count ;count++)
7586 {
7587 fgets(str, MAX_BUF_SIZE, fp);
7588 signalstrength = atoi(str);
7589 temp[count].cli_SignalStrength = signalstrength;
7590 temp[count].cli_RSSI = signalstrength;
7591 temp[count].cli_SNR = signalstrength + 95;
7592 }
7593 pclose(fp);
7594 }
7595
7596
7597 if((apIndex == 0) || (apIndex == 4))
7598 {
7599 for(count =0 ; count < wifi_count ;count++)
7600 {
7601 strcpy(temp[count].cli_OperatingStandard,"g");
7602 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7603 }
7604
7605 //BytesSent
developer30423732022-12-01 16:17:49 +08007606 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 +08007607 fp = popen(pipeCmd, "r");
7608 if(fp)
7609 {
7610 pclose(fp);
7611 }
7612 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7613 if(fp)
7614 {
7615 for (count = 0; count < wifi_count; count++)
7616 {
7617 fgets(str, MAX_BUF_SIZE, fp);
7618 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7619 }
7620 pclose(fp);
7621 }
7622
7623 //BytesReceived
developer30423732022-12-01 16:17:49 +08007624 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 +08007625 fp = popen(pipeCmd, "r");
7626 if (fp)
7627 {
7628 pclose(fp);
7629 }
7630 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7631 if (fp)
7632 {
7633 for (count = 0; count < wifi_count; count++)
7634 {
7635 fgets(str, MAX_BUF_SIZE, fp);
7636 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7637 }
7638 pclose(fp);
7639 }
7640
7641 //PacketsSent
developer30423732022-12-01 16:17:49 +08007642 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 +08007643 fp = popen(pipeCmd, "r");
7644 if (fp)
7645 {
7646 pclose(fp);
7647 }
7648
7649 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7650 if (fp)
7651 {
7652 for (count = 0; count < wifi_count; count++)
7653 {
7654 fgets(str, MAX_BUF_SIZE, fp);
7655 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7656 }
7657 pclose(fp);
7658 }
7659
7660 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007661 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 +08007662 fp = popen(pipeCmd, "r");
7663 if (fp)
7664 {
7665 pclose(fp);
7666 }
7667 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7668 if (fp)
7669 {
7670 for (count = 0; count < wifi_count; count++)
7671 {
7672 fgets(str, MAX_BUF_SIZE, fp);
7673 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7674 }
7675 pclose(fp);
7676 }
7677
7678 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007679 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 +08007680 fp = popen(pipeCmd, "r");
7681 if (fp)
7682 {
7683 pclose(fp);
7684 }
7685 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7686 if (fp)
7687 {
7688 for (count = 0; count < wifi_count; count++)
7689 {
7690 fgets(str, MAX_BUF_SIZE, fp);
7691 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7692 }
7693 pclose(fp);
7694 }
7695
7696 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007697 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 +08007698 fp = popen(pipeCmd, "r");
7699 if (fp)
7700 {
7701 pclose(fp);
7702 }
7703 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7704 if (fp)
7705 {
7706 for (count = 0; count < wifi_count; count++)
7707 {
7708 fgets(str, MAX_BUF_SIZE, fp);
7709 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7710 }
7711 pclose(fp);
7712 }
7713
7714 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007715 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 +08007716 fp = popen(pipeCmd, "r");
7717 if (fp)
7718 {
7719 pclose(fp);
7720 }
7721 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7722 if (fp)
7723 {
7724 for (count = 0; count < wifi_count; count++)
7725 {
7726 fgets(str, MAX_BUF_SIZE, fp);
7727 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7728 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7729 }
7730 pclose(fp);
7731 }
7732
7733 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007734 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 +08007735 fp = popen(pipeCmd, "r");
7736 if (fp)
7737 {
7738 pclose(fp);
7739 }
7740 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7741 if (fp)
7742 {
7743 for (count = 0; count < wifi_count; count++)
7744 {
7745 fgets(str, MAX_BUF_SIZE, fp);
7746 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7747 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7748 }
7749 pclose(fp);
7750 }
7751
7752 }
7753 else if ((apIndex == 1) || (apIndex == 5))
7754 {
7755 for (count = 0; count < wifi_count; count++)
7756 {
7757 strcpy(temp[count].cli_OperatingStandard, "a");
7758 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7759 temp[count].cli_BytesSent = 0;
7760 temp[count].cli_BytesReceived = 0;
7761 temp[count].cli_LastDataUplinkRate = 0;
7762 temp[count].cli_LastDataDownlinkRate = 0;
7763 temp[count].cli_PacketsSent = 0;
7764 temp[count].cli_PacketsReceived = 0;
7765 temp[count].cli_ErrorsSent = 0;
7766 }
7767 }
7768
7769 for (count = 0; count < wifi_count; count++)
7770 {
7771 temp[count].cli_Retransmissions = 0;
7772 temp[count].cli_DataFramesSentAck = 0;
7773 temp[count].cli_DataFramesSentNoAck = 0;
7774 temp[count].cli_MinRSSI = 0;
7775 temp[count].cli_MaxRSSI = 0;
7776 strncpy(temp[count].cli_InterferenceSources, "", 64);
7777 memset(temp[count].cli_IPAddress, 0, 64);
7778 temp[count].cli_RetransCount = 0;
7779 temp[count].cli_FailedRetransCount = 0;
7780 temp[count].cli_RetryCount = 0;
7781 temp[count].cli_MultipleRetryCount = 0;
7782 }
7783 *associated_dev_array = temp;
7784 }
7785 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7786 return RETURN_OK;
7787}
7788
7789int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7790{
7791 FILE *fp = NULL;
7792 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7793 char cmd[MAX_CMD_SIZE];
7794 int count = 0;
7795
7796 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7797 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7798 fp = popen(cmd,"r");
7799 if(fp == NULL)
7800 {
7801 printf("Failed to run command in Function %s\n",__FUNCTION__);
7802 return 0;
7803 }
7804 if(fgets(path, sizeof(path)-1, fp) != NULL)
7805 {
7806 for(count=0;path[count]!='\n';count++)
7807 status[count]=path[count];
7808 status[count]='\0';
7809 }
7810 strcpy(wifi_status,status);
7811 pclose(fp);
7812 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7813 return RETURN_OK;
7814}
7815
7816/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7817struct hostapd_sta_param {
7818 char key[50];
7819 char value[100];
7820}
7821
7822static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7823 int i = 0;
7824
7825 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7826 if (strncmp(params[i].key,key,50) == 0){
7827 return &params[i].value;
7828 }
7829 i++;
7830 }
7831 return NULL;
7832
7833} */
7834
7835static unsigned int count_occurences(const char *buf, const char *word)
7836{
7837 unsigned int n = 0;
7838 char *ptr = strstr(buf, word);
7839
7840 while (ptr++) {
7841 n++;
7842 ptr = strstr(ptr, word);
7843 }
7844
7845 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7846 return n;
7847}
7848
7849static const char *get_line_from_str_buf(const char *buf, char *line)
7850{
7851 int i;
7852 int n = strlen(buf);
7853
7854 for (i = 0; i < n; i++) {
7855 line[i] = buf[i];
7856 if (buf[i] == '\n') {
7857 line[i] = '\0';
7858 return &buf[i + 1];
7859 }
7860 }
7861
7862 return NULL;
7863}
7864
7865INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7866{
7867 unsigned int assoc_cnt = 0;
7868 char interface_name[50] = {0};
7869 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7870 char cmd[MAX_CMD_SIZE] = {'\0'};
7871 char line[256] = {'\0'};
7872 int i = 0;
7873 int ret = 0;
7874 const char *ptr = NULL;
7875 char *key = NULL;
7876 char *val = NULL;
7877 wifi_associated_dev3_t *temp = NULL;
7878 int rssi;
7879
7880 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7881
7882 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7883 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7884 return RETURN_ERR;
7885 }
7886
7887 // Example filtered output of 'iw dev' command:
7888 // Station 0a:69:72:10:d2:fa (on wifi0)
7889 // signal avg:-67 [-71, -71] dBm
7890 // Station 28:c2:1f:25:5f:99 (on wifi0)
7891 // signal avg:-67 [-71, -70] dBm
7892 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7893 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7894 return RETURN_ERR;
7895 }
7896
7897 ret = _syscmd(cmd, buf, sizeof(buf));
7898 if (ret == RETURN_ERR) {
7899 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7900 return RETURN_ERR;
7901 }
7902
7903 *output_array_size = count_occurences(buf, "Station");
7904 if (*output_array_size == 0) return RETURN_OK;
7905
7906 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7907 if (temp == NULL) {
7908 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7909 return RETURN_ERR;
7910 }
7911 *associated_dev_array = temp;
7912
7913 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7914 ptr = get_line_from_str_buf(buf, line);
7915 i = -1;
7916 while (ptr) {
7917 if (strstr(line, "Station")) {
7918 i++;
7919 key = strtok(line, " ");
7920 val = strtok(NULL, " ");
7921 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7922 &temp[i].cli_MACAddress[0],
7923 &temp[i].cli_MACAddress[1],
7924 &temp[i].cli_MACAddress[2],
7925 &temp[i].cli_MACAddress[3],
7926 &temp[i].cli_MACAddress[4],
7927 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7928 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7929 free(*associated_dev_array);
7930 return RETURN_ERR;
7931 }
7932 }
7933 else if (i < 0) {
7934 ptr = get_line_from_str_buf(ptr, line);
7935 continue; // We didn't detect 'station' entry yet
7936 }
7937 else if (strstr(line, "signal avg")) {
7938 key = strtok(line, ":");
7939 val = strtok(NULL, " ");
7940 if (sscanf(val, "%d", &rssi) <= 0 ) {
7941 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7942 free(*associated_dev_array);
7943 return RETURN_ERR;
7944 }
7945 temp[i].cli_RSSI = rssi;
7946 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7947 }
7948 // Here other fields can be parsed if added to filter of 'iw dev' command
7949
7950 ptr = get_line_from_str_buf(ptr, line);
7951 };
7952
7953 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7954
7955 return RETURN_OK;
7956}
7957
7958#if 0
7959//To-do
7960INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7961{
7962 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7963
7964 //Using different approach to get required WiFi Parameters from system available commands
7965#if 0
7966 FILE *f;
7967 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7968 char cmd[256], buf[2048];
7969 char *param , *value, *line=NULL;
7970 size_t len = 0;
7971 ssize_t nread;
7972 wifi_associated_dev3_t *dev=NULL;
7973 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007974 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007975 _syscmd(cmd,buf,sizeof(buf));
7976 *output_array_size = atoi(buf);
7977
7978 if (*output_array_size <= 0)
7979 return RETURN_OK;
7980
7981 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7982 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007983 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007984 _syscmd(cmd,buf,sizeof(buf));
7985 f = fopen("/tmp/connected_devices.txt", "r");
7986 if (f==NULL)
7987 {
7988 *output_array_size=0;
7989 return RETURN_ERR;
7990 }
7991 while ((nread = getline(&line, &len, f)) != -1)
7992 {
7993 param = strtok(line,"=");
7994 value = strtok(NULL,"=");
7995
7996 if( strcmp("flags",param) == 0 )
7997 {
7998 value[strlen(value)-1]='\0';
7999 if(strstr (value,"AUTHORIZED") != NULL )
8000 {
8001 dev[auth_temp].cli_AuthenticationState = 1;
8002 dev[auth_temp].cli_Active = 1;
8003 auth_temp++;
8004 read_flag=1;
8005 }
8006 }
8007 if(read_flag==1)
8008 {
8009 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8010 {
8011 value[strlen(value)-1]='\0';
8012 sscanf(value, "%x:%x:%x:%x:%x:%x",
8013 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8014 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8015 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8016 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8017 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8018 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8019
8020 }
8021 else if( strcmp("rx_packets",param) == 0 )
8022 {
8023 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8024 }
8025
8026 else if( strcmp("tx_packets",param) == 0 )
8027 {
8028 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
8029 }
8030
8031 else if( strcmp("rx_bytes",param) == 0 )
8032 {
8033 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8034 }
8035
8036 else if( strcmp("tx_bytes",param) == 0 )
8037 {
8038 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
8039 mac_temp++;
8040 read_flag=0;
8041 }
8042 }
8043 }
8044
8045 *output_array_size = auth_temp;
8046 auth_temp=0;
8047 mac_temp=0;
8048 free(line);
8049 fclose(f);
8050#endif
8051 char interface_name[MAX_BUF_SIZE] = {0};
8052 char wifi_status[MAX_BUF_SIZE] = {0};
8053 char hostapdconf[MAX_BUF_SIZE] = {0};
8054
8055 wifi_associated_dev3_t *dev_array = NULL;
8056 ULONG wifi_count = 0;
8057
8058 *associated_dev_array = NULL;
8059 *output_array_size = 0;
8060
8061 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8062 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8063 {
8064 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8065
developerac6f1142022-12-20 19:26:35 +08008066 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08008067
8068 if(strlen(interface_name) > 1)
8069 {
8070 wifihal_interfacestatus(wifi_status,interface_name);
8071 if(strcmp(wifi_status,"RUNNING") == 0)
8072 {
8073 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8074
8075 *associated_dev_array = dev_array;
8076 *output_array_size = wifi_count;
8077 }
8078 else
8079 {
8080 *associated_dev_array = NULL;
8081 }
8082 }
8083 }
8084
8085 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8086 return RETURN_OK;
8087}
8088#endif
8089
8090/* getIPAddress function */
8091/**
8092* @description Returning IpAddress of the Matched String
8093*
8094* @param
8095* @str Having MacAddress
8096* @ipaddr Having ipaddr
8097* @return The status of the operation
8098* @retval RETURN_OK if successful
8099* @retval RETURN_ERR if any error is detected
8100*
8101*/
8102
8103INT getIPAddress(char *str,char *ipaddr)
8104{
8105 FILE *fp = NULL;
8106 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8107 int LeaseTime = 0,ret = 0;
8108 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8109 {
8110 return RETURN_ERR;
8111 }
8112
8113 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8114 {
8115 /*
8116 Sample:sss
8117 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8118 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8119 */
8120 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008121 &(LeaseTime),
8122 phyAddr,
8123 ipAddr,
8124 hostName
8125 );
developer06a01d92022-09-07 16:32:39 +08008126 if(ret != 4)
8127 continue;
8128 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008129 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008130 }
developerd946fd62022-12-08 18:03:28 +08008131 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008132 return RETURN_OK;
8133}
8134
8135/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8136/**
8137* @description Returning Inactive wireless connected clients informations
8138*
8139* @param
8140* @filename Holding private_wifi 2g/5g content files
8141* @associated_dev_array Having inactiv wireless clients informations
8142* @output_array_size Returning Inactive wireless counts
8143* @return The status of the operation
8144* @retval RETURN_OK if successful
8145* @retval RETURN_ERR if any error is detected
8146*
8147*/
8148
8149INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8150{
8151 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8152 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8153 FILE *fp = NULL;
8154 int arr[MACADDRESS_SIZE] = {0};
8155 unsigned char mac[MACADDRESS_SIZE] = {0};
8156 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8157 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8158 fp = popen(buf,"r");
8159 if(fp == NULL)
8160 return RETURN_ERR;
8161 else
8162 {
8163 fgets(path,sizeof(path),fp);
8164 maccount = atoi(path);
8165 }
8166 pclose(fp);
8167 *output_array_size = maccount;
8168 wifi_associated_dev3_t* temp = NULL;
8169 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8170 *associated_dev_array = temp;
8171 if(temp == NULL)
8172 {
8173 printf("Error Statement. Insufficient memory \n");
8174 return RETURN_ERR;
8175 }
8176 memset(buf,0,sizeof(buf));
8177 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8178 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008179 if (fp == NULL) {
8180 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8181 return RETURN_ERR;
8182 }
developer06a01d92022-09-07 16:32:39 +08008183 for(count = 0; count < maccount ; count++)
8184 {
8185 fgets(path,sizeof(path),fp);
8186 for(i = 0; path[i]!='\n';i++)
8187 str[i]=path[i];
8188 str[i]='\0';
8189 getIPAddress(str,ipaddr);
8190 memset(buf,0,sizeof(buf));
8191 if(strlen(ipaddr) > 0)
8192 {
8193 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8194 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8195 {
8196 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8197 {
8198 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8199 {
8200 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8201
8202 }
8203 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8204 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]);
8205 }
8206 temp[count].cli_AuthenticationState = 0; //TODO
8207 temp[count].cli_Active = 0; //TODO
8208 temp[count].cli_SignalStrength = 0;
8209 }
8210 else //Active wireless clients info
8211 {
8212 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8213 {
8214 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8215 {
8216 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8217
8218 }
8219 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8220 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]);
8221 }
8222 temp[count].cli_Active = 1;
8223 }
8224 }
8225 memset(ipaddr,0,sizeof(ipaddr));
8226 }
8227 pclose(fp);
8228 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8229 return RETURN_OK;
8230}
8231//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8232//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8233//To get Band Steering Capability
8234INT wifi_getBandSteeringCapability(BOOL *support)
8235{
8236 *support = FALSE;
8237 return RETURN_OK;
8238}
8239
8240
8241//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8242//To get Band Steering enable status
8243INT wifi_getBandSteeringEnable(BOOL *enable)
8244{
8245 *enable = FALSE;
8246 return RETURN_OK;
8247}
8248
8249//To turn on/off Band steering
8250INT wifi_setBandSteeringEnable(BOOL enable)
8251{
8252 return RETURN_OK;
8253}
8254
8255//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8256//To get Band Steering AP group
8257INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8258{
8259 if (NULL == output_ApGroup)
8260 return RETURN_ERR;
8261
8262 strcpy(output_ApGroup, "1,2");
8263 return RETURN_OK;
8264}
8265
8266//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8267//to set and read the band steering BandUtilizationThreshold parameters
8268INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8269{
8270 return RETURN_ERR;
8271}
8272
8273INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8274{
8275 return RETURN_ERR;
8276}
8277
8278//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8279//to set and read the band steering RSSIThreshold parameters
8280INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8281{
8282 return RETURN_ERR;
8283}
8284
8285INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8286{
8287 return RETURN_ERR;
8288}
8289
8290
8291//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8292//to set and read the band steering physical modulation rate threshold parameters
8293INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8294{
8295 //If chip is not support, return -1
8296 return RETURN_ERR;
8297}
8298
8299INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8300{
8301 //If chip is not support, return -1
8302 return RETURN_ERR;
8303}
8304
8305//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8306//to set and read the inactivity time (in seconds) for steering under overload condition
8307INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8308{
8309 return RETURN_ERR;
8310}
8311
8312INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8313{
8314 return RETURN_ERR;
8315}
8316
8317//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8318//to set and read the inactivity time (in seconds) for steering under Idle condition
8319INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8320{
8321 return RETURN_ERR;
8322}
8323
8324INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8325{
8326 return RETURN_ERR;
8327}
8328
8329//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8330//pClientMAC[64]
8331//pSourceSSIDIndex[64]
8332//pDestSSIDIndex[64]
8333//pSteeringReason[256]
8334INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8335{
8336 //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
8337 *pSteeringTime=time(NULL);
8338 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8339 return RETURN_OK;
8340}
8341
8342INT wifi_ifConfigDown(INT apIndex)
8343{
8344 INT status = RETURN_OK;
8345 char cmd[64];
8346
8347 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8348 printf("%s: %s\n", __func__, cmd);
8349 system(cmd);
8350
8351 return status;
8352}
8353
8354INT wifi_ifConfigUp(INT apIndex)
8355{
developerd946fd62022-12-08 18:03:28 +08008356 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008357 char cmd[128];
8358 char buf[1024];
8359
developerac6f1142022-12-20 19:26:35 +08008360 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008361 return RETURN_ERR;
8362 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008363 _syscmd(cmd, buf, sizeof(buf));
8364 return 0;
8365}
8366
8367//>> Deprecated. Replace with wifi_applyRadioSettings
8368INT wifi_pushBridgeInfo(INT apIndex)
8369{
developerd946fd62022-12-08 18:03:28 +08008370 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008371 char ip[32] = {0};
8372 char subnet[32] = {0};
8373 char bridge[32] = {0};
8374 int vlanId = 0;
8375 char cmd[128] = {0};
8376 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008377
8378 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8379 wifi_getApVlanID(apIndex,&vlanId);
8380
developerac6f1142022-12-20 19:26:35 +08008381 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008382 return RETURN_ERR;
8383 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008384 _syscmd(cmd,buf, sizeof(buf));
8385
8386 return 0;
8387}
8388
8389INT wifi_pushChannel(INT radioIndex, UINT channel)
8390{
developerd946fd62022-12-08 18:03:28 +08008391 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008392 char cmd[128];
8393 char buf[1024];
8394 int apIndex;
8395
8396 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008397 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008398 return RETURN_ERR;
8399 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008400 _syscmd(cmd,buf, sizeof(buf));
8401
8402 return 0;
8403}
8404
8405INT wifi_pushChannelMode(INT radioIndex)
8406{
8407 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8408 return RETURN_ERR;
8409}
8410
8411INT wifi_pushDefaultValues(INT radioIndex)
8412{
8413 //Apply Comcast specified default radio settings instantly
8414 //AMPDU=1
8415 //AMPDUFrames=32
8416 //AMPDULim=50000
8417 //txqueuelen=1000
8418
8419 return RETURN_ERR;
8420}
8421
8422INT wifi_pushTxChainMask(INT radioIndex)
8423{
8424 //Apply default TxChainMask instantly
8425 return RETURN_ERR;
8426}
8427
8428INT wifi_pushRxChainMask(INT radioIndex)
8429{
8430 //Apply default RxChainMask instantly
8431 return RETURN_ERR;
8432}
8433
8434INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8435{
8436 INT status;
8437
8438 status = wifi_setSSIDName(apIndex,ssid);
8439 wifi_setApEnable(apIndex,FALSE);
8440 wifi_setApEnable(apIndex,TRUE);
8441
8442 return status;
8443}
8444
8445INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8446{
8447 //Apply default Ssid Advertisement instantly
8448 return RETURN_ERR;
8449}
8450
8451INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8452{
8453 INT status = RETURN_ERR;
8454 *output = 0;
8455 return RETURN_ERR;
8456}
8457
8458INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8459{
8460 return RETURN_OK;
8461}
8462
8463INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8464{
8465 return RETURN_OK;
8466}
8467
8468//To-do
8469INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8470{
developereb199ae2022-09-13 14:04:27 +08008471 char output[16]={'\0'};
8472 char config_file[MAX_BUF_SIZE] = {0};
8473
8474 if (!output_string)
8475 return RETURN_ERR;
8476
8477 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8478 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8479
8480 if (strlen(output) == 0)
8481 snprintf(output_string, 64, "Disabled");
8482 else if (strncmp(output, "0", 1) == 0)
8483 snprintf(output_string, 64, "Disabled");
8484 else if (strncmp(output, "1", 1) == 0)
8485 snprintf(output_string, 64, "Optional");
8486 else if (strncmp(output, "2", 1) == 0)
8487 snprintf(output_string, 64, "Required");
8488 else {
8489 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8490 return RETURN_ERR;
8491 }
8492
8493 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008494 return RETURN_OK;
8495}
8496INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8497{
developereb199ae2022-09-13 14:04:27 +08008498 char str[MAX_BUF_SIZE]={'\0'};
8499 char cmd[MAX_CMD_SIZE]={'\0'};
8500 struct params params;
8501 char config_file[MAX_BUF_SIZE] = {0};
8502
8503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8504 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8505 return RETURN_ERR;
8506
8507 params.name = "ieee80211w";
8508 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8509 params.value = "0";
8510 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8511 params.value = "1";
8512 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8513 params.value = "2";
8514 else{
8515 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8516 return RETURN_ERR;
8517 }
8518 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8519 wifi_hostapdWrite(config_file, &params, 1);
8520 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008521 return RETURN_OK;
8522}
8523INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8524{
8525 char output[16]={'\0'};
8526 char config_file[MAX_BUF_SIZE] = {0};
8527
8528 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8529 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8530 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8531
8532 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8533 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8534
8535 return RETURN_OK;
8536}
8537
8538INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8539{
8540 return RETURN_OK;
8541}
8542
8543INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8544{
8545 return RETURN_OK;
8546}
8547
8548INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8549{
8550 return RETURN_OK;
8551}
8552
8553INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8554{
8555 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8556 char config_file[MAX_BUF_SIZE] = {0};
8557
8558 if (NULL == output)
8559 return RETURN_ERR;
8560 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8561 wifi_hostapdRead(config_file,"hw_mode",output,64);
8562
8563 if(strcmp(output,"b")==0)
8564 sprintf(output, "%s", "1,2,5.5,11");
8565 else if (strcmp(output,"a")==0)
8566 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8567 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8568 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8569
8570 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8571 return RETURN_OK;
8572}
8573
8574INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8575{
8576 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8577 char *temp;
8578 char temp_output[128];
8579 char temp_TransmitRates[128];
8580 char config_file[MAX_BUF_SIZE] = {0};
8581
8582 if (NULL == output)
8583 return RETURN_ERR;
8584
8585 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8586 wifi_hostapdRead(config_file,"supported_rates",output,64);
8587
developer5b398df2022-11-17 20:39:48 +08008588 if (strlen(output) == 0) {
8589 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8590 return RETURN_OK;
8591 }
developer06a01d92022-09-07 16:32:39 +08008592 strcpy(temp_TransmitRates,output);
8593 strcpy(temp_output,"");
8594 temp = strtok(temp_TransmitRates," ");
8595 while(temp!=NULL)
8596 {
8597 temp[strlen(temp)-1]=0;
8598 if((temp[0]=='5') && (temp[1]=='\0'))
8599 {
8600 temp="5.5";
8601 }
8602 strcat(temp_output,temp);
8603 temp = strtok(NULL," ");
8604 if(temp!=NULL)
8605 {
8606 strcat(temp_output,",");
8607 }
8608 }
8609 strcpy(output,temp_output);
8610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8611
8612 return RETURN_OK;
8613}
8614
8615INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8616{
8617 return RETURN_OK;
8618}
8619
8620
8621INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8622{
8623 int i=0;
8624 char *temp;
developeref938762022-10-19 17:21:01 +08008625 char temp1[128] = {0};
8626 char temp_output[128] = {0};
8627 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008628 struct params params={'\0'};
8629 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008630 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008631
8632 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8633 if(NULL == output)
8634 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008635 strcpy(temp_TransmitRates,output);
8636
8637 for(i=0;i<strlen(temp_TransmitRates);i++)
8638 {
developeref938762022-10-19 17:21:01 +08008639 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008640 {
8641 continue;
8642 }
8643 else
8644 {
8645 return RETURN_ERR;
8646 }
8647 }
8648 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008649 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008650 while(temp!=NULL)
8651 {
8652 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008653 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008654 {
developeref938762022-10-19 17:21:01 +08008655 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008656 {
8657 return RETURN_ERR;
8658 }
8659 }
8660
8661 if(strcmp(temp,"5.5")==0)
8662 {
8663 strcpy(temp1,"55");
8664 }
8665 else
8666 {
8667 strcat(temp1,"0");
8668 }
8669 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008670 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008671 if(temp!=NULL)
8672 {
8673 strcat(temp_output," ");
8674 }
8675 }
8676 strcpy(output,temp_output);
8677
developer06a01d92022-09-07 16:32:39 +08008678 params.name = "supported_rates";
8679 params.value = output;
8680
8681 wifi_dbg_printf("\n%s:",__func__);
8682 wifi_dbg_printf("params.value=%s\n",params.value);
8683 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8684 wifi_hostapdWrite(config_file,&params,1);
8685 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8686
8687 return RETURN_OK;
8688}
8689
8690
8691static char *sncopy(char *dst, int dst_sz, const char *src)
8692{
8693 if (src && dst && dst_sz > 0) {
8694 strncpy(dst, src, dst_sz);
8695 dst[dst_sz - 1] = '\0';
8696 }
8697 return dst;
8698}
8699
8700static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8701{
8702 if (0 == strcmp(ht_mode, "HT40") ||
8703 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008704 0 == strcmp(ht_mode, "HT160") ||
8705 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008706 switch (channel) {
developer9a520b12023-09-21 16:01:43 +08008707 case 0 ... 7:
developer06a01d92022-09-07 16:32:39 +08008708 case 36:
8709 case 44:
8710 case 52:
8711 case 60:
8712 case 100:
8713 case 108:
8714 case 116:
8715 case 124:
8716 case 132:
8717 case 140:
8718 case 149:
8719 case 157:
8720 return 1;
8721 case 8 ... 13:
8722 case 40:
8723 case 48:
8724 case 56:
8725 case 64:
8726 case 104:
8727 case 112:
8728 case 120:
8729 case 128:
8730 case 136:
8731 case 144:
8732 case 153:
8733 case 161:
8734 return -1;
8735 default:
8736 return -EINVAL;
8737 }
8738 }
8739
8740 return -EINVAL;
8741}
8742
developerb7593de2022-10-18 09:51:57 +08008743static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8744{
8745 int idx = channel%8;
8746 if (0 == strcmp(ht_mode, "HT40") ||
8747 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008748 0 == strcmp(ht_mode, "HT160") ||
8749 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008750 switch (idx) {
8751 case 1:
8752 return 1;
8753 case 5:
8754 return -1;
8755 default:
8756 return -EINVAL;
8757 }
8758 }
8759
8760 return -EINVAL;
8761}
developer06a01d92022-09-07 16:32:39 +08008762static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8763{
8764 if (NULL == hw_mode) return;
8765
8766 if (0 == strcmp(hw_mode, "ac"))
8767 sncopy(bw_mode, bw_mode_len, "ht vht");
8768
8769 if (0 == strcmp(hw_mode, "n"))
8770 sncopy(bw_mode, bw_mode_len, "ht");
8771
8772 return;
8773}
8774
8775static int util_chan_to_freq(int chan)
8776{
8777 if (chan == 14)
8778 return 2484;
8779 else if (chan < 14)
8780 return 2407 + chan * 5;
8781 else if (chan >= 182 && chan <= 196)
8782 return 4000 + chan * 5;
8783 else
8784 return 5000 + chan * 5;
8785 return 0;
8786}
8787
developerb7593de2022-10-18 09:51:57 +08008788static int util_6G_chan_to_freq(int chan)
8789{
8790 if (chan)
8791 return 5950 + chan * 5;
8792 else
8793 return 0;
8794
8795}
developer06a01d92022-09-07 16:32:39 +08008796const int *util_unii_5g_chan2list(int chan, int width)
8797{
8798 static const int lists[] = {
8799 // <width>, <chan1>, <chan2>..., 0,
8800 20, 36, 0,
8801 20, 40, 0,
8802 20, 44, 0,
8803 20, 48, 0,
8804 20, 52, 0,
8805 20, 56, 0,
8806 20, 60, 0,
8807 20, 64, 0,
8808 20, 100, 0,
8809 20, 104, 0,
8810 20, 108, 0,
8811 20, 112, 0,
8812 20, 116, 0,
8813 20, 120, 0,
8814 20, 124, 0,
8815 20, 128, 0,
8816 20, 132, 0,
8817 20, 136, 0,
8818 20, 140, 0,
8819 20, 144, 0,
8820 20, 149, 0,
8821 20, 153, 0,
8822 20, 157, 0,
8823 20, 161, 0,
8824 20, 165, 0,
8825 40, 36, 40, 0,
8826 40, 44, 48, 0,
8827 40, 52, 56, 0,
8828 40, 60, 64, 0,
8829 40, 100, 104, 0,
8830 40, 108, 112, 0,
8831 40, 116, 120, 0,
8832 40, 124, 128, 0,
8833 40, 132, 136, 0,
8834 40, 140, 144, 0,
8835 40, 149, 153, 0,
8836 40, 157, 161, 0,
8837 80, 36, 40, 44, 48, 0,
8838 80, 52, 56, 60, 64, 0,
8839 80, 100, 104, 108, 112, 0,
8840 80, 116, 120, 124, 128, 0,
8841 80, 132, 136, 140, 144, 0,
8842 80, 149, 153, 157, 161, 0,
8843 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8844 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8845 -1 // final delimiter
8846 };
8847 const int *start;
8848 const int *p;
8849
8850 for (p = lists; *p != -1; p++) {
8851 if (*p == width) {
8852 for (start = ++p; *p != 0; p++) {
8853 if (*p == chan)
8854 return start;
8855 }
8856 }
8857 // move to the end of channel list of given width
8858 while (*p != 0) {
8859 p++;
8860 }
8861 }
8862
8863 return NULL;
8864}
8865
8866static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8867{
8868 if (NULL == ht_mode)
8869 return 0;
8870
8871 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8872 const int *chans = util_unii_5g_chan2list(channel, width);
8873 int sum = 0;
8874 int cnt = 0;
8875
8876 if (NULL == chans)
8877 return 0;
8878
8879 while (*chans) {
8880 sum += *chans;
8881 cnt++;
8882 chans++;
8883 }
developer30423732022-12-01 16:17:49 +08008884 if (cnt == 0)
8885 return 0;
developer06a01d92022-09-07 16:32:39 +08008886 return sum / cnt;
8887}
8888
developerb7593de2022-10-18 09:51:57 +08008889static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8890{
8891 if (NULL == ht_mode)
8892 return 0;
8893
8894 int width = strtol((ht_mode + 2), NULL, 10);
8895
8896 int idx = 0 ;
8897 int centerchan = 0;
8898 int chan_ofs = 1;
8899
8900 if (width == 40){
8901 idx = ((channel/4) + chan_ofs)%2;
8902 switch (idx) {
8903 case 0:
8904 centerchan = (channel - 2);
8905 break;
8906 case 1:
8907 centerchan = (channel + 2);
8908 break;
8909 default:
8910 return -EINVAL;
8911 }
8912 }else if (width == 80){
8913 idx = ((channel/4) + chan_ofs)%4;
8914 switch (idx) {
8915 case 0:
8916 centerchan = (channel - 6);
8917 break;
8918 case 1:
8919 centerchan = (channel + 6);
8920 break;
8921 case 2:
8922 centerchan = (channel + 2);
8923 break;
8924 case 3:
8925 centerchan = (channel - 2);
8926 break;
8927 default:
8928 return -EINVAL;
8929 }
8930 }else if (width == 160){
8931 switch (channel) {
8932 case 1 ... 29:
8933 centerchan = 15;
8934 break;
8935 case 33 ... 61:
8936 centerchan = 47;
8937 break;
8938 case 65 ... 93:
8939 centerchan = 79;
8940 break;
8941 case 97 ... 125:
8942 centerchan = 111;
8943 break;
8944 case 129 ... 157:
8945 centerchan = 143;
8946 break;
8947 case 161 ... 189:
8948 centerchan = 175;
8949 break;
8950 case 193 ... 221:
8951 centerchan = 207;
8952 break;
8953 default:
8954 return -EINVAL;
8955 }
developer7c4cd202023-03-01 10:56:29 +08008956 }else if (width == 320){
8957 switch (channel) {
8958 case 1 ... 29:
8959 centerchan = 31;
8960 break;
8961 case 33 ... 93:
8962 centerchan = 63;
8963 break;
8964 case 97 ... 157:
8965 centerchan = 127;
8966 break;
8967 case 161 ... 221:
8968 centerchan = 191;
8969 break;
8970 default:
8971 return -EINVAL;
8972 }
developerb7593de2022-10-18 09:51:57 +08008973 }
8974 return centerchan;
8975}
developer06a01d92022-09-07 16:32:39 +08008976static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8977{
8978 BOOL onlyG, onlyN, onlyA;
8979 CHAR tmp[64];
8980 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8981 if (ret == RETURN_OK) {
8982 sncopy(hw_mode, hw_mode_size, tmp);
8983 }
8984 return ret;
8985}
8986
8987INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8988{
8989 // Sample commands:
8990 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8991 // hostapd_cli -i wifi0 chan_switch 30 2437
8992 char cmd[MAX_CMD_SIZE] = {0};
8993 char buf[MAX_BUF_SIZE] = {0};
8994 int freq = 0, ret = 0;
8995 char center_freq1_str[32] = ""; // center_freq1=%d
8996 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8997 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8998 char hw_mode[16] = ""; // n|ac
8999 char bw_mode[16] = ""; // ht|ht vht
9000 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08009001 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009002 int sec_chan_offset;
9003 int width;
developer4fb0b922022-09-30 14:29:09 +08009004 char config_file[64] = {0};
9005 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08009006 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08009007 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08009008 wifi_band band = band_invalid;
9009 int center_chan = 0;
9010 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08009011
developer4fb0b922022-09-30 14:29:09 +08009012 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08009013
developerac6f1142022-12-20 19:26:35 +08009014 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009015 return RETURN_ERR;
9016
developer06a01d92022-09-07 16:32:39 +08009017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9018
developerb7593de2022-10-18 09:51:57 +08009019 band = wifi_index_to_band(radioIndex);
9020
developer5884e982022-10-06 10:52:50 +08009021 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08009022
9023 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08009024 if (channel){
developerb7593de2022-10-18 09:51:57 +08009025 if (band == band_6){
9026 freq = util_6G_chan_to_freq(channel);
9027 }else{
9028 freq = util_chan_to_freq(channel);
9029 }
developer7c4cd202023-03-01 10:56:29 +08009030 if (width == 320) {
9031 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
9032 setEHT320 = TRUE;
9033 }
developer5884e982022-10-06 10:52:50 +08009034 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08009035
developer5884e982022-10-06 10:52:50 +08009036 // Provide bandwith if specified
9037 if (channel_width_MHz > 20) {
9038 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9039 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9040 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08009041
developer5884e982022-10-06 10:52:50 +08009042 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9043 }else if (channel_width_MHz == 20){
9044 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9045 }
developer06a01d92022-09-07 16:32:39 +08009046
developerb7593de2022-10-18 09:51:57 +08009047
developer5884e982022-10-06 10:52:50 +08009048 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08009049 if (band == band_6){
9050 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9051 if(center_chan){
9052 center_freq1 = util_6G_chan_to_freq(center_chan);
9053 }
9054 }else{
9055 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9056 if(center_chan){
9057 center_freq1 = util_chan_to_freq(center_chan);
9058 }
developer5884e982022-10-06 10:52:50 +08009059 }
developerb7593de2022-10-18 09:51:57 +08009060
9061 if (center_freq1)
9062 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9063
9064 }
9065
9066 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9067 if (band == band_6){
9068 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9069 }else{
9070 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08009071 }
developerb7593de2022-10-18 09:51:57 +08009072 if (sec_chan_offset != -EINVAL)
9073 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08009074
developer5884e982022-10-06 10:52:50 +08009075 // Only the first AP, other are hanging on the same radio
9076 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08009077 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9078 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08009079 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9080 wifi_dbg_printf("execute: '%s'\n", cmd);
9081 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08009082 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08009083
developer5884e982022-10-06 10:52:50 +08009084 ret = wifi_setRadioChannel(radioIndex, channel);
9085 if (ret != RETURN_OK) {
9086 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9087 return RETURN_ERR;
9088 }
9089
9090 if (sec_chan_offset == 1) ext_str = "Above";
9091 else if (sec_chan_offset == -1) ext_str = "Below";
9092
9093 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08009094
developer5884e982022-10-06 10:52:50 +08009095 } else {
9096 if (channel_width_MHz > 20)
9097 ext_str = "Above";
9098 }
developer4fb0b922022-09-30 14:29:09 +08009099
developer06a01d92022-09-07 16:32:39 +08009100 char mhz_str[16];
9101 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009102 if (setEHT320 == TRUE)
9103 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9104 else
9105 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009106
developer57fa24a2023-03-15 17:25:07 +08009107 writeBandWidth(radioIndex, mhz_str);
9108 if (band == band_2_4 || band == band_5) {
9109 if (width == 20)
9110 wifi_RemoveRadioExtChannel(radioIndex, ext_str);
9111 else
9112 wifi_setRadioExtChannel(radioIndex, ext_str);
9113 }
developer06a01d92022-09-07 16:32:39 +08009114 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9115
9116 return RETURN_OK;
9117}
9118
9119INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9120{
developer615510b2022-09-27 10:14:35 +08009121 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009122 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009123 char cmd[256]={0};
9124 char buf[128]={0};
9125 char file_name[32] = {0};
9126 char filter_SSID[32] = {0};
9127 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009128 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009129 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009130 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009131 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009132 size_t len=0;
9133 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009134 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009135 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009136 bool filter_enable = false;
9137 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009138 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009139
developer615510b2022-09-27 10:14:35 +08009140 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009141
developer615510b2022-09-27 10:14:35 +08009142 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9143 f = fopen(file_name, "r");
9144 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009145 fgets(buf, sizeof(file_name), f);
9146 if ((strncmp(buf, "0", 1)) != 0) {
9147 fgets(filter_SSID, sizeof(file_name), f);
9148 if (strlen(filter_SSID) != 0)
9149 filter_enable = true;
9150 }
developer615510b2022-09-27 10:14:35 +08009151 fclose(f);
9152 }
9153
developerac6f1142022-12-20 19:26:35 +08009154 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009155 return RETURN_ERR;
9156
developer033b37b2022-10-18 11:27:46 +08009157 phyId = radio_index_to_phy(radio_index);
9158
9159 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009160 _syscmd(cmd, buf, sizeof(buf));
9161 channels_num = strtol(buf, NULL, 10);
9162
developerd946fd62022-12-08 18:03:28 +08009163 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9164 // 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 +08009165 fprintf(stderr, "cmd: %s\n", cmd);
9166 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009167 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9168 return RETURN_ERR;
9169 }
developer5550e242022-09-30 09:59:32 +08009170
9171 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9172 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9173
developer615510b2022-09-27 10:14:35 +08009174 ret = fgets(line, sizeof(line), f);
9175 while (ret != NULL) {
9176 if(strstr(line, "BSS") != NULL) { // new neighbor info
9177 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9178 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9179 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9180
9181 if (!filter_BSS) {
9182 index++;
9183 wifi_neighbor_ap2_t *tmp;
9184 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9185 if (tmp == NULL) { // no more memory to use
9186 index--;
9187 wifi_dbg_printf("%s: realloc failed\n", __func__);
9188 break;
9189 }
9190 scan_array = tmp;
9191 }
9192 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009193
developer615510b2022-09-27 10:14:35 +08009194 filter_BSS = false;
9195 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9196 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9197 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9198 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9199 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009200 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009201 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009202
developer615510b2022-09-27 10:14:35 +08009203 if (freq >= 2412 && freq <= 2484) {
9204 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9205 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9206 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9207 }
9208 else if (freq >= 5160 && freq <= 5805) {
9209 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9210 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9211 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9212 }
developer06a01d92022-09-07 16:32:39 +08009213
developer615510b2022-09-27 10:14:35 +08009214 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009215 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009216 for (int i = 0; i < channels_num; i++) {
9217 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9218 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9219 break;
9220 }
9221 }
developer06a01d92022-09-07 16:32:39 +08009222 }
developer615510b2022-09-27 10:14:35 +08009223 } else if (strstr(line, "beacon interval") != NULL) {
9224 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9225 } else if (strstr(line, "signal") != NULL) {
9226 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9227 } else if (strstr(line,"SSID") != NULL) {
9228 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9229 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9230 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009231 }
developer615510b2022-09-27 10:14:35 +08009232 } else if (strstr(line, "Supported rates") != NULL) {
9233 char SRate[80] = {0}, *tmp = NULL;
9234 memset(buf, 0, sizeof(buf));
9235 strcpy(SRate, line);
9236 tmp = strtok(SRate, ":");
9237 tmp = strtok(NULL, ":");
9238 strcpy(buf, tmp);
9239 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009240
developer615510b2022-09-27 10:14:35 +08009241 tmp = strtok(buf, " \n");
9242 while (tmp != NULL) {
9243 strcat(SRate, tmp);
9244 if (SRate[strlen(SRate) - 1] == '*') {
9245 SRate[strlen(SRate) - 1] = '\0';
9246 }
9247 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009248
developer615510b2022-09-27 10:14:35 +08009249 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009250 }
developer615510b2022-09-27 10:14:35 +08009251 SRate[strlen(SRate) - 1] = '\0';
9252 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9253 } else if (strstr(line, "DTIM") != NULL) {
9254 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9255 } else if (strstr(line, "VHT capabilities") != NULL) {
9256 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9257 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9258 } else if (strstr(line, "HT capabilities") != NULL) {
9259 strcat(scan_array[index].ap_SupportedStandards, ",n");
9260 strcpy(scan_array[index].ap_OperatingStandards, "n");
9261 } else if (strstr(line, "VHT operation") != NULL) {
9262 ret = fgets(line, sizeof(line), f);
9263 sscanf(line," * channel width: %d", &vht_channel_width);
9264 if(vht_channel_width == 1) {
9265 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9266 } else {
9267 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9268 }
9269 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9270 continue;
9271 } else if (strstr(line, "HT operation") != NULL) {
9272 ret = fgets(line, sizeof(line), f);
9273 sscanf(line," * secondary channel offset: %s", &buf);
9274 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009275 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009276 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 +08009277 }
developer615510b2022-09-27 10:14:35 +08009278 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009279 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009280 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9281 } else {
9282 //20Mhz
9283 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 +08009284 }
developer615510b2022-09-27 10:14:35 +08009285 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009286 continue;
developer615510b2022-09-27 10:14:35 +08009287 } else if (strstr(line, "HE capabilities") != NULL) {
9288 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9289 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9290 ret = fgets(line, sizeof(line), f);
9291 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9292 if (strstr(line, "HE40/2.4GHz") != NULL)
9293 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9294 else
9295 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9296 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9297 if (strstr(line, "HE80/5GHz") != NULL) {
9298 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9299 ret = fgets(line, sizeof(line), f);
9300 } else
9301 continue;
9302 if (strstr(line, "HE160/5GHz") != NULL)
9303 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009304 }
developer615510b2022-09-27 10:14:35 +08009305 continue;
9306 } else if (strstr(line, "WPA") != NULL) {
9307 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9308 } else if (strstr(line, "RSN") != NULL) {
9309 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9310 } else if (strstr(line, "Group cipher") != NULL) {
9311 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9312 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9313 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009314 }
developer06a01d92022-09-07 16:32:39 +08009315 }
developer615510b2022-09-27 10:14:35 +08009316 ret = fgets(line, sizeof(line), f);
9317 }
9318
9319 if (!filter_BSS) {
9320 *output_array_size = index + 1;
9321 } else {
9322 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9323 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009324 }
developer06a01d92022-09-07 16:32:39 +08009325 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009326 pclose(f);
developer5550e242022-09-30 09:59:32 +08009327 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009328 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009329 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009330}
developer615510b2022-09-27 10:14:35 +08009331
developer06a01d92022-09-07 16:32:39 +08009332INT wifi_getApAssociatedDeviceStats(
9333 INT apIndex,
9334 mac_address_t *clientMacAddress,
9335 wifi_associated_dev_stats_t *associated_dev_stats,
9336 u64 *handle)
9337{
9338 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9339 char interface_name[50] = {0};
9340 char cmd[1024] = {0};
9341 char mac_str[18] = {0};
9342 char *key = NULL;
9343 char *val = NULL;
9344 FILE *f = NULL;
9345 char *line = NULL;
9346 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009347
9348 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9349 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9350 return RETURN_ERR;
9351 }
9352
9353 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9354 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9355 if((f = popen(cmd, "r")) == NULL) {
9356 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9357 return RETURN_ERR;
9358 }
9359
developer30423732022-12-01 16:17:49 +08009360 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009361 key = strtok(line,":");
9362 val = strtok(NULL,":");
9363
9364 if(!strncmp(key,"rx bytes",8))
9365 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9366 if(!strncmp(key,"tx bytes",8))
9367 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9368 if(!strncmp(key,"rx packets",10))
9369 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9370 if(!strncmp(key,"tx packets",10))
9371 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9372 if(!strncmp(key,"tx retries",10))
9373 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9374 if(!strncmp(key,"tx failed",9))
9375 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9376 if(!strncmp(key,"rx drop misc",13))
9377 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9378 if(!strncmp(key,"rx bitrate",10)) {
9379 val = strtok(val, " ");
9380 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9381 }
9382 if(!strncmp(key,"tx bitrate",10)) {
9383 val = strtok(val, " ");
9384 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9385 }
9386 }
9387 free(line);
9388 pclose(f);
9389 return RETURN_OK;
9390}
9391
9392INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9393{
developerd946fd62022-12-08 18:03:28 +08009394 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009395 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9396
9397 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9398 if (NULL == output_string)
9399 return RETURN_ERR;
9400
developerac6f1142022-12-20 19:26:35 +08009401 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009402 return RETURN_ERR;
9403 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 +08009404 _syscmd(cmd, buf, sizeof(buf));
9405
9406 //size of SSID name restricted to value less than 32 bytes
9407 snprintf(output_string, 32, "%s", buf);
9408 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9409
9410 return RETURN_OK;
9411}
9412
9413INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9414{
9415 //char cmd[MAX_CMD_SIZE] = {0};
9416 char config_file[MAX_BUF_SIZE] = {0};
9417 char buf[32] = {0};
9418
9419 if (!output_filterMode)
9420 return RETURN_ERR;
9421
9422 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9423 //_syscmd(cmd, buf, sizeof(buf));
9424 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9425 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009426 if(strlen(buf) == 0) {
9427 *output_filterMode = 0;
9428 }
9429 else {
9430 int macaddr_acl_mode = strtol(buf, NULL, 10);
9431 if (macaddr_acl_mode == 1) {
9432 *output_filterMode = 1;
9433 } else if (macaddr_acl_mode == 0) {
9434 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9435 if (strlen(buf) == 0) {
9436 *output_filterMode = 0;
9437 } else {
9438 *output_filterMode = 2;
9439 }
9440 } else {
9441 return RETURN_ERR;
9442 }
9443 }
developer06a01d92022-09-07 16:32:39 +08009444
9445 return RETURN_OK;
9446}
9447
9448INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9449{
9450 FILE *fp = NULL;
9451 char str[MAX_BUF_SIZE] = {0};
9452 int wificlientindex = 0 ;
9453 int count = 0;
9454 int signalstrength = 0;
9455 int arr[MACADDRESS_SIZE] = {0};
9456 unsigned char mac[MACADDRESS_SIZE] = {0};
9457 UINT wifi_count = 0;
9458 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9459 char pipeCmd[MAX_CMD_SIZE] = {0};
9460
9461 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9462 *output_array_size = 0;
9463 *associated_dev_array = NULL;
9464 char interface_name[50] = {0};
9465
9466 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9467 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9468 return RETURN_ERR;
9469 }
9470
9471 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9472 fp = popen(pipeCmd, "r");
9473 if (fp == NULL)
9474 {
9475 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9476 return RETURN_ERR;
9477 }
9478
9479 /* Read the output a line at a time - output it. */
9480 fgets(str, sizeof(str)-1, fp);
9481 wifi_count = (unsigned int) atoi ( str );
9482 *output_array_size = wifi_count;
9483 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9484 pclose(fp);
9485
9486 if(wifi_count == 0)
9487 {
9488 return RETURN_OK;
9489 }
9490 else
9491 {
9492 wifi_associated_dev2_t* temp = NULL;
9493 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9494 *associated_dev_array = temp;
9495 if(temp == NULL)
9496 {
9497 printf("Error Statement. Insufficient memory \n");
9498 return RETURN_ERR;
9499 }
9500
9501 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9502 system(pipeCmd);
9503
9504 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9505 if(fp == NULL)
9506 {
9507 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9508 return RETURN_ERR;
9509 }
9510 fclose(fp);
9511
developer30423732022-12-01 16:17:49 +08009512 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009513 fp = popen(pipeCmd, "r");
9514 if(fp)
9515 {
9516 for(count =0 ; count < wifi_count; count++)
9517 {
9518 fgets(str, MAX_BUF_SIZE, fp);
9519 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9520 {
9521 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9522 {
9523 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9524
9525 }
9526 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9527 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]);
9528 }
9529 temp[count].cli_AuthenticationState = 1; //TODO
9530 temp[count].cli_Active = 1; //TODO
9531 }
9532 pclose(fp);
9533 }
9534
9535 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009536 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 +08009537 fp = popen(pipeCmd, "r");
9538 if(fp)
9539 {
9540 pclose(fp);
9541 }
9542 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9543 if(fp)
9544 {
9545 for(count =0 ; count < wifi_count ;count++)
9546 {
9547 fgets(str, MAX_BUF_SIZE, fp);
9548 signalstrength = atoi(str);
9549 temp[count].cli_RSSI = signalstrength;
9550 }
9551 pclose(fp);
9552 }
9553
9554
9555 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009556 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 +08009557 fp = popen(pipeCmd, "r");
9558 if (fp)
9559 {
9560 pclose(fp);
9561 }
9562 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9563 if (fp)
9564 {
9565 for (count = 0; count < wifi_count; count++)
9566 {
9567 fgets(str, MAX_BUF_SIZE, fp);
9568 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9569 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9570 }
9571 pclose(fp);
9572 }
9573
9574 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009575 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 +08009576 fp = popen(pipeCmd, "r");
9577 if (fp)
9578 {
9579 pclose(fp);
9580 }
9581 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9582 if (fp)
9583 {
9584 for (count = 0; count < wifi_count; count++)
9585 {
9586 fgets(str, MAX_BUF_SIZE, fp);
9587 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9588 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9589 }
9590 pclose(fp);
9591 }
9592 }
9593 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9594 return RETURN_OK;
9595
9596}
9597
9598INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9599{
9600#if 0
9601 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009602 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009603 _syscmd(cmd, buf, sizeof(buf));*/
9604
9605 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9606 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9607 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9608 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9609
9610 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.
9611 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].
9612 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].
9613 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].
9614 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9615 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9616
9617 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9618 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9619 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9620 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.
9621 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.
9622 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.
9623 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.
9624 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.
9625 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.
9626 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.
9627 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9628#endif
9629
9630 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009631 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009632 char pipeCmd[128] = {0};
9633 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009634 wifi_ssidTrafficStats2_t *out = output_struct;
9635
developerce736392022-09-13 15:24:34 +08009636 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009637 if (!output_struct)
9638 return RETURN_ERR;
9639
developerce736392022-09-13 15:24:34 +08009640 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009641 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009642 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009643 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009644
developer06a01d92022-09-07 16:32:39 +08009645 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009646 if (fp == NULL) {
9647 fprintf(stderr, "%s: popen failed\n", __func__);
9648 return RETURN_ERR;
9649 }
9650 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009651 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009652
developerce736392022-09-13 15:24:34 +08009653 if (strlen(str) == 0) // interface not exist
9654 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009655
developerce736392022-09-13 15:24:34 +08009656 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9657 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009658
developerce736392022-09-13 15:24:34 +08009659 memset(str, 0, sizeof(str));
9660 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009661 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009662 if (fp == NULL) {
9663 fprintf(stderr, "%s: popen failed\n", __func__);
9664 return RETURN_ERR;
9665 }
9666 fgets(str, sizeof(str), fp);
9667
9668 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9669 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009670 pclose(fp);
developerce736392022-09-13 15:24:34 +08009671
9672 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9673 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9674
9675 // Not supported
9676 output_struct->ssid_RetransCount = 0;
9677 output_struct->ssid_FailedRetransCount = 0;
9678 output_struct->ssid_RetryCount = 0;
9679 output_struct->ssid_MultipleRetryCount = 0;
9680 output_struct->ssid_ACKFailureCount = 0;
9681 output_struct->ssid_AggregatedPacketCount = 0;
9682
developer06a01d92022-09-07 16:32:39 +08009683 return RETURN_OK;
9684}
9685
9686//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).
9687INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9688{
9689 char output_val[16]={'\0'};
9690 char config_file[MAX_BUF_SIZE] = {0};
9691
9692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9693 if (!output)
9694 return RETURN_ERR;
9695 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9696 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9697
9698 if( strcmp(output_val,"1") == 0 )
9699 *output = TRUE;
9700 else
9701 *output = FALSE;
9702 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9703
9704 return RETURN_OK;
9705}
9706
9707INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9708{
9709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9710 char str[MAX_BUF_SIZE]={'\0'};
9711 char string[MAX_BUF_SIZE]={'\0'};
9712 char cmd[MAX_CMD_SIZE]={'\0'};
9713 char *ch;
9714 char config_file[MAX_BUF_SIZE] = {0};
9715 struct params params;
9716
9717 if(enable == TRUE)
9718 strcpy(string,"1");
9719 else
9720 strcpy(string,"0");
9721
9722 params.name = "ap_isolate";
9723 params.value = string;
9724
9725 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9726 wifi_hostapdWrite(config_file,&params,1);
9727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9728
9729 return RETURN_OK;
9730}
9731
9732INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9733{
9734 if (NULL == output_dBm)
9735 return RETURN_ERR;
9736
9737 *output_dBm = 0;
9738 return RETURN_OK;
9739}
9740
9741INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9742{
9743 return RETURN_OK;
9744}
9745INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9746{
9747 return RETURN_OK;
9748}
9749INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9750{
9751 return RETURN_OK;
9752}
9753INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9754{
9755 return RETURN_OK;
9756}
9757INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9758{
9759 return RETURN_OK;
9760}
9761INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9762{
9763 char config_file[MAX_BUF_SIZE] = {0};
9764 struct params list;
9765
9766 list.name = "bss_transition";
9767 list.value = activate?"1":"0";
9768 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9769 wifi_hostapdWrite(config_file, &list, 1);
9770
9771 return RETURN_OK;
9772}
9773wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9774
9775void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9776{
9777 return;
9778}
9779
9780INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9781{
9782 // TODO Implement me!
9783 return RETURN_OK;
9784}
9785
9786INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9787{
developera3c68b92022-09-13 15:27:29 +08009788 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009789 FILE *f = NULL;
9790
developer72ec5572023-01-05 16:27:13 +08009791 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009792
developer72ec5572023-01-05 16:27:13 +08009793 if (essid == NULL)
9794 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009795
developer72ec5572023-01-05 16:27:13 +08009796 if (strlen(essid) == 0 || apIndex == -1) {
9797 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9798 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009799 }
9800
developer72ec5572023-01-05 16:27:13 +08009801 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9802 f = fopen(file_name, "w");
9803 if (f == NULL)
9804 return RETURN_ERR;
9805
9806 // For mode == 0 is to disable filter, just don't write ssid to the file.
9807 fprintf(f, "%d\n%s", mode, mode?essid:"");
9808 fclose(f);
9809 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009810 return RETURN_OK;
9811}
9812
9813INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9814{
9815 // TODO Implement me!
9816 //Apply wifi_pushRadioChannel() instantly
9817 return RETURN_ERR;
9818}
9819
9820INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9821{
9822 // TODO Implement me!
9823 return RETURN_OK;
9824}
9825
9826#ifdef HAL_NETLINK_IMPL
9827static int tidStats_callback(struct nl_msg *msg, void *arg) {
9828 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9829 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9830 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9831 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9832 int rem , tid_index = 0;
9833
9834 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9835 wifi_associated_dev_tid_entry_t *stats_entry;
9836
9837 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9838 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9839 };
9840 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9841 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9842 };
9843
9844 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9845 genlmsg_attrlen(gnlh, 0), NULL);
9846
9847
9848 if (!tb[NL80211_ATTR_STA_INFO]) {
9849 fprintf(stderr, "station stats missing!\n");
9850 return NL_SKIP;
9851 }
9852
9853 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9854 tb[NL80211_ATTR_STA_INFO],
9855 stats_policy)) {
9856 fprintf(stderr, "failed to parse nested attributes!\n");
9857 return NL_SKIP;
9858 }
9859
9860 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9861 {
9862 stats_entry = &out->tid_array[tid_index];
9863
9864 stats_entry->tid = tid_index;
9865 stats_entry->ac = _tid_ac_index_get[tid_index];
9866
9867 if(sinfo[NL80211_STA_INFO_TID_STATS])
9868 {
9869 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9870 printf("failed to parse nested stats attributes!");
9871 return NL_SKIP;
9872 }
9873 }
9874 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9875 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9876
9877 if(tid_index < (PS_MAX_TID - 1))
9878 tid_index++;
9879 }
9880 //ToDo: sum_time_ms, ewma_time_ms
9881 return NL_SKIP;
9882}
9883#endif
9884
9885INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9886{
9887#ifdef HAL_NETLINK_IMPL
9888 Netlink nl;
9889 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009890 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009891
developerac6f1142022-12-20 19:26:35 +08009892 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009893 return RETURN_ERR;
9894
9895 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009896
9897 nl.id = initSock80211(&nl);
9898
9899 if (nl.id < 0) {
9900 fprintf(stderr, "Error initializing netlink \n");
9901 return -1;
9902 }
9903
9904 struct nl_msg* msg = nlmsg_alloc();
9905
9906 if (!msg) {
9907 fprintf(stderr, "Failed to allocate netlink message.\n");
9908 nlfree(&nl);
9909 return -2;
9910 }
9911
9912 genlmsg_put(msg,
9913 NL_AUTO_PORT,
9914 NL_AUTO_SEQ,
9915 nl.id,
9916 0,
9917 0,
9918 NL80211_CMD_GET_STATION,
9919 0);
9920
9921 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9922 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9923 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9924 nl_send_auto(nl.socket, msg);
9925 nl_recvmsgs(nl.socket, nl.cb);
9926 nlmsg_free(msg);
9927 nlfree(&nl);
9928 return RETURN_OK;
9929#else
9930//iw implementation
9931#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9932#define TOTAL_MAX_LINES 50
9933
9934 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009935 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009936 FILE *fp=NULL;
9937 char pipeCmd[1024]= {'\0'};
9938 int lines,tid_index=0;
9939 char mac_addr[20] = {'\0'};
9940
developerac6f1142022-12-20 19:26:35 +08009941 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009942 return RETURN_ERR;
9943
developer06a01d92022-09-07 16:32:39 +08009944 wifi_associated_dev_tid_entry_t *stats_entry;
9945
developer06a01d92022-09-07 16:32:39 +08009946 strcpy(mac_addr,clientMacAddress);
9947
9948 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9949 fp= popen(pipeCmd,"r");
9950 if(fp == NULL)
9951 {
9952 perror("popen for station dump failed\n");
9953 return RETURN_ERR;
9954 }
9955 pclose(fp);
9956
9957 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9958 fp=popen(pipeCmd,"r");
9959 if(fp == NULL)
9960 {
9961 perror("popen for grep station failed\n");
9962 return RETURN_ERR;
9963 }
9964 else if(fgets(buf,sizeof(buf),fp) != NULL)
9965 lines=atoi(buf);
9966 else
9967 {
9968 pclose(fp);
9969 fprintf(stderr,"No devices are connected \n");
9970 return RETURN_ERR;
9971 }
9972 pclose(fp);
9973
9974 if(lines == 1)
9975 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9976
9977 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9978 {
9979 stats_entry = &tid_stats->tid_array[tid_index];
9980 stats_entry->tid = tid_index;
9981
9982 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);
9983
9984 fp=popen(pipeCmd,"r");
9985 if(fp ==NULL)
9986 {
9987 perror("Failed to read from tid file \n");
9988 return RETURN_ERR;
9989 }
9990 else if(fgets(buf,sizeof(buf),fp) != NULL)
9991 stats_entry->num_msdus = atol(buf);
9992
9993 pclose(fp);
9994 stats_entry->ac = _tid_ac_index_get[tid_index];
9995// TODO:
9996// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9997// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9998 }
9999 return RETURN_OK;
10000#endif
10001}
10002
10003
10004INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
10005{
developerd946fd62022-12-08 18:03:28 +080010006 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +080010007 char cmd[128]={0};
10008 char buf[128]={0};
10009 int freq = 0;
10010
10011 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10012
10013 // full mode is used to scan all channels.
10014 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10015 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
10016 ieee80211_channel_to_frequency(chan_list[0], &freq);
10017
developerac6f1142022-12-20 19:26:35 +080010018 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010019 return RETURN_ERR;
10020
developer615510b2022-09-27 10:14:35 +080010021 if (freq)
developerd946fd62022-12-08 18:03:28 +080010022 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +080010023 else
developerd946fd62022-12-08 18:03:28 +080010024 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +080010025
10026 _syscmd(cmd, buf, sizeof(buf));
10027 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10028
developer06a01d92022-09-07 16:32:39 +080010029 return RETURN_OK;
10030}
10031
10032
10033INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10034{
10035 // TODO Implement me!
10036 return RETURN_ERR;
10037}
10038
10039INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10040{
10041 // TODO Implement me!
10042 return RETURN_ERR;
10043}
10044
10045INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10046{
10047 // TODO Implement me!
10048 return RETURN_ERR;
10049}
10050
10051INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10052{
10053 // TODO Implement me!
10054 return RETURN_ERR;
10055}
10056
10057INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10058{
10059 // TODO Implement me!
10060 return RETURN_ERR;
10061}
10062
10063INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10064{
10065 // TODO Implement me!
10066 return RETURN_ERR;
10067}
10068
10069INT wifi_steering_eventUnregister(void)
10070{
10071 // TODO Implement me!
10072 return RETURN_ERR;
10073}
10074
10075INT wifi_delApAclDevices(INT apIndex)
10076{
10077#if 0
10078 char cmd[MAX_BUF_SIZE] = {0};
10079 char buf[MAX_BUF_SIZE] = {0};
10080
10081 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +080010082 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +080010083 if(_syscmd(cmd,buf,sizeof(buf)))
10084 return RETURN_ERR;
10085#endif
developer9988c232023-03-06 14:57:08 +080010086 char cmd[256]={0};
10087 char buf[64]={0};
developer06a01d92022-09-07 16:32:39 +080010088
developere6aafda2022-09-13 14:59:28 +080010089 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer9988c232023-03-06 14:57:08 +080010090 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 +080010091 if(_syscmd(cmd, buf, sizeof(buf)))
10092 return RETURN_ERR;
10093 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010094
10095 return RETURN_OK;
10096}
10097
10098#ifdef HAL_NETLINK_IMPL
10099static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10100 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10101 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10102 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10103 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10104 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10105 char mac_addr[20],dev[20];
10106
10107 nla_parse(tb,
10108 NL80211_ATTR_MAX,
10109 genlmsg_attrdata(gnlh, 0),
10110 genlmsg_attrlen(gnlh, 0),
10111 NULL);
10112
10113 if(!tb[NL80211_ATTR_STA_INFO]) {
10114 fprintf(stderr, "sta stats missing!\n");
10115 return NL_SKIP;
10116 }
10117
10118 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10119 fprintf(stderr, "failed to parse nested attributes!\n");
10120 return NL_SKIP;
10121 }
10122 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10123
10124 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10125
10126 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10127 fprintf(stderr, "failed to parse nested rate attributes!");
10128 return NL_SKIP;
10129 }
10130
10131 if(sinfo[NL80211_STA_INFO_TID_STATS])
10132 {
10133 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10134 printf("failed to parse nested stats attributes!");
10135 return NL_SKIP;
10136 }
10137 }
10138
10139 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10140 {
10141 printf("Type is VHT\n");
10142 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10143 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10144
10145 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10146 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10147 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10148 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10149 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10150 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10151 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10152 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10153 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10154 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10155 }
10156 else
10157 {
10158 printf(" OFDM or CCK \n");
10159 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10160 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10161 }
10162
10163 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10164 if(rinfo[NL80211_RATE_INFO_MCS])
10165 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10166 }
10167 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10168 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10169 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10170 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10171
10172 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10173 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10174
10175 if (sinfo[NL80211_STA_INFO_SIGNAL])
10176 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10177 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10178 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10179 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10180 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10181 //rssi_array need to be filled
10182 return NL_SKIP;
10183}
10184#endif
10185
10186INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10187{
10188#ifdef HAL_NETLINK_IMPL
10189 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010190 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010191 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010192 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010193
10194 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10195
10196 if (*output_array_size <= 0)
10197 return RETURN_OK;
10198
developer06a01d92022-09-07 16:32:39 +080010199 nl.id = initSock80211(&nl);
10200
10201 if (nl.id < 0) {
10202 fprintf(stderr, "Error initializing netlink \n");
10203 return 0;
10204 }
10205
10206 struct nl_msg* msg = nlmsg_alloc();
10207
10208 if (!msg) {
10209 fprintf(stderr, "Failed to allocate netlink message.\n");
10210 nlfree(&nl);
10211 return 0;
10212 }
10213
10214 genlmsg_put(msg,
10215 NL_AUTO_PORT,
10216 NL_AUTO_SEQ,
10217 nl.id,
10218 0,
10219 0,
10220 NL80211_CMD_GET_STATION,
10221 0);
10222
10223 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10224 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10225 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10226 nl_send_auto(nl.socket, msg);
10227 nl_recvmsgs(nl.socket, nl.cb);
10228 nlmsg_free(msg);
10229 nlfree(&nl);
10230 return RETURN_OK;
10231#else
10232 //TODO Implement me
10233 return RETURN_OK;
10234#endif
10235}
10236
10237#ifdef HAL_NETLINK_IMPL
10238static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10239 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10240 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10241 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10242 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10243 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10244 char mac_addr[20],dev[20];
10245
10246 nla_parse(tb,
10247 NL80211_ATTR_MAX,
10248 genlmsg_attrdata(gnlh, 0),
10249 genlmsg_attrlen(gnlh, 0),
10250 NULL);
10251
10252 if(!tb[NL80211_ATTR_STA_INFO]) {
10253 fprintf(stderr, "sta stats missing!\n");
10254 return NL_SKIP;
10255 }
10256
10257 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10258 fprintf(stderr, "failed to parse nested attributes!\n");
10259 return NL_SKIP;
10260 }
10261
10262 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10263
10264 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10265
10266 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10267 fprintf(stderr, "failed to parse nested rate attributes!");
10268 return NL_SKIP;
10269 }
10270
10271 if(sinfo[NL80211_STA_INFO_TID_STATS])
10272 {
10273 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10274 printf("failed to parse nested stats attributes!");
10275 return NL_SKIP;
10276 }
10277 }
10278 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10279 {
10280 printf("Type is VHT\n");
10281 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10282 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10283
10284 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10285 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10286 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10287 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10288 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10289 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10290 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10291 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10292 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10293 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10294 }
10295 else
10296 {
10297 printf(" OFDM or CCK \n");
10298 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10299 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10300 }
10301
10302 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10303 if(rinfo[NL80211_RATE_INFO_MCS])
10304 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10305 }
10306
10307 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10308 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10309 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10310 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10311
10312 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10313 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10314 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10315
10316 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10317 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10318
10319 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10320 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10321
10322 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10323 ((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]);
10324
10325 return NL_SKIP;
10326}
10327#endif
10328
10329INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10330{
10331#ifdef HAL_NETLINK_IMPL
10332 Netlink nl;
10333 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010334 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010335 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010336 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010337
10338 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10339
10340 if (*output_array_size <= 0)
10341 return RETURN_OK;
10342
developerd946fd62022-12-08 18:03:28 +080010343 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010344
10345 nl.id = initSock80211(&nl);
10346
10347 if(nl.id < 0) {
10348 fprintf(stderr, "Error initializing netlink \n");
10349 return 0;
10350 }
10351
10352 struct nl_msg* msg = nlmsg_alloc();
10353
10354 if(!msg) {
10355 fprintf(stderr, "Failed to allocate netlink message.\n");
10356 nlfree(&nl);
10357 return 0;
10358 }
10359
10360 genlmsg_put(msg,
10361 NL_AUTO_PORT,
10362 NL_AUTO_SEQ,
10363 nl.id,
10364 0,
10365 0,
10366 NL80211_CMD_GET_STATION,
10367 0);
10368
10369 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10370 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10371 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10372 nl_send_auto(nl.socket, msg);
10373 nl_recvmsgs(nl.socket, nl.cb);
10374 nlmsg_free(msg);
10375 nlfree(&nl);
10376 return RETURN_OK;
10377#else
10378 //TODO Implement me
10379 return RETURN_OK;
10380#endif
10381}
10382
10383INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10384{
10385 // TODO Implement me!
10386 char buf[MAX_BUF_SIZE] = {0};
10387 char config_file[MAX_BUF_SIZE] = {0};
10388
10389 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10390 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10391 *activate = (strncmp("1",buf,1) == 0);
10392
10393 return RETURN_OK;
10394}
10395
10396INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10397{
10398 char config_file[MAX_BUF_SIZE] = {0};
10399 struct params list;
10400
10401 list.name = "rrm_neighbor_report";
10402 list.value = activate?"1":"0";
10403 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10404 wifi_hostapdWrite(config_file, &list, 1);
10405
10406 return RETURN_OK;
10407}
10408
10409INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10410{
10411 char buf[32] = {0};
10412 char config_file[MAX_BUF_SIZE] = {0};
10413
10414 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10415 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10416 *activate = (strncmp("1",buf,1) == 0);
10417
10418 return RETURN_OK;
10419}
10420#undef HAL_NETLINK_IMPL
10421#ifdef HAL_NETLINK_IMPL
10422static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10423 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10424 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10425 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10426 char dev[20];
10427 int freq =0 ;
10428 static int i=0;
10429
10430 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10431
10432 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10433 };
10434
10435 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10436
10437 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10438
10439 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10440 fprintf(stderr, "survey data missing!\n");
10441 return NL_SKIP;
10442 }
10443
10444 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10445 {
10446 fprintf(stderr, "failed to parse nested attributes!\n");
10447 return NL_SKIP;
10448 }
10449
10450
10451 if(out[0].array_size == 1 )
10452 {
10453 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10454 {
10455 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10456 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10457 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10458
10459 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10460 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10461 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10462 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10463 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10464 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10465 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10466 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10467 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10468 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10469 if (sinfo[NL80211_SURVEY_INFO_TIME])
10470 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10471 return NL_STOP;
10472 }
10473 }
10474 else
10475 {
10476 if ( i <= out[0].array_size )
10477 {
10478 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10479 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10480 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10481
10482 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10483 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10484 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10485 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10486 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10487 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10488 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10489 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10490 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10491 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10492 if (sinfo[NL80211_SURVEY_INFO_TIME])
10493 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10494 }
10495 }
10496
10497 i++;
10498 return NL_SKIP;
10499}
10500#endif
10501
10502static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10503{
10504 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10505 FILE *fp;
10506
10507 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10508 {
10509 printf("Creating Frequency-Channel Map\n");
10510 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10511 }
10512 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10513 if((fp = popen(command, "r")))
10514 {
10515 fgets(output, sizeof(output), fp);
10516 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010517 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010518 }
10519
10520 return 0;
10521}
10522
10523static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10524{
10525 int freqMHz = -1;
10526 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010527 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010528
10529 ieee80211_channel_to_frequency(channel, &freqMHz);
10530 if (freqMHz == -1) {
10531 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10532 return -1;
10533 }
10534
developer7930d352022-12-21 17:55:42 +080010535 wifi_GetInterfaceName(radioIndex, interface_name);
10536 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010537 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10538 radioIndex, freqMHz);
10539 return -1;
10540 }
10541
10542 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10543 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10544 return -1;
10545 }
10546
10547 return 0;
10548}
10549
10550static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10551{
10552 const char *ptr = buf;
10553 char *key = NULL;
10554 char *val = NULL;
10555 char line[256] = { '\0' };
10556
10557 while (ptr = get_line_from_str_buf(ptr, line)) {
10558 if (strstr(line, "Frequency")) continue;
10559
10560 key = strtok(line, ":");
10561 val = strtok(NULL, " ");
10562 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10563
10564 if (!strcmp(key, "noise")) {
10565 sscanf(val, "%d", &stats->ch_noise);
10566 if (stats->ch_noise == 0) {
10567 // Workaround for missing noise information.
10568 // Assume -95 for 2.4G and -103 for 5G
10569 if (radioIndex == 0) stats->ch_noise = -95;
10570 if (radioIndex == 1) stats->ch_noise = -103;
10571 }
10572 }
10573 else if (!strcmp(key, "channel active time")) {
10574 sscanf(val, "%llu", &stats->ch_utilization_total);
10575 }
10576 else if (!strcmp(key, "channel busy time")) {
10577 sscanf(val, "%llu", &stats->ch_utilization_busy);
10578 }
10579 else if (!strcmp(key, "channel receive time")) {
10580 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10581 }
10582 else if (!strcmp(key, "channel transmit time")) {
10583 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10584 }
10585 };
10586
10587 return 0;
10588}
10589
10590INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10591{
10592 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10593#ifdef HAL_NETLINK_IMPL
10594 Netlink nl;
10595 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010596 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010597
10598 local[0].array_size = array_size;
10599
developerac6f1142022-12-20 19:26:35 +080010600 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010601 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010602
10603 nl.id = initSock80211(&nl);
10604
10605 if (nl.id < 0) {
10606 fprintf(stderr, "Error initializing netlink \n");
10607 return -1;
10608 }
10609
10610 struct nl_msg* msg = nlmsg_alloc();
10611
10612 if (!msg) {
10613 fprintf(stderr, "Failed to allocate netlink message.\n");
10614 nlfree(&nl);
10615 return -2;
10616 }
10617
10618 genlmsg_put(msg,
10619 NL_AUTO_PORT,
10620 NL_AUTO_SEQ,
10621 nl.id,
10622 0,
10623 NLM_F_DUMP,
10624 NL80211_CMD_GET_SURVEY,
10625 0);
10626
10627 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10628 nl_send_auto(nl.socket, msg);
10629 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10630 nl_recvmsgs(nl.socket, nl.cb);
10631 nlmsg_free(msg);
10632 nlfree(&nl);
10633 //Copying the Values
10634 for(int i=0;i<array_size;i++)
10635 {
10636 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10637 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10638 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10639 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10640 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10641 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10642 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10643 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10644 }
10645#else
10646 ULONG channel = 0;
10647 int i;
10648 int number_of_channels = array_size;
10649 char buf[512];
10650 INT ret;
10651 wifi_channelStats_t tmp_stats;
10652
10653 if (number_of_channels == 0) {
10654 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10655 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10656 return RETURN_ERR;
10657 }
10658 number_of_channels = 1;
10659 input_output_channelStats_array[0].ch_number = channel;
10660 }
10661
10662 for (i = 0; i < number_of_channels; i++) {
10663
10664 input_output_channelStats_array[i].ch_noise = 0;
10665 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10666 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10667 input_output_channelStats_array[i].ch_utilization_busy = 0;
10668 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10669 input_output_channelStats_array[i].ch_utilization_total = 0;
10670
10671 memset(buf, 0, sizeof(buf));
10672 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10673 return RETURN_ERR;
10674 }
10675 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10676 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10677 return RETURN_ERR;
10678 }
10679
10680 // XXX: fake missing 'self' counter which is not available in iw survey output
10681 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10682 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10683
10684 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10685 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10686 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10687 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10688 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10689
10690 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",
10691 __func__,
10692 input_output_channelStats_array[i].ch_number,
10693 input_output_channelStats_array[i].ch_noise,
10694 input_output_channelStats_array[i].ch_utilization_total,
10695 input_output_channelStats_array[i].ch_utilization_busy,
10696 input_output_channelStats_array[i].ch_utilization_busy_rx,
10697 input_output_channelStats_array[i].ch_utilization_busy_tx,
10698 input_output_channelStats_array[i].ch_utilization_busy_self,
10699 input_output_channelStats_array[i].ch_utilization_busy_ext);
10700 }
10701#endif
10702 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10703 return RETURN_OK;
10704}
10705#define HAL_NETLINK_IMPL
10706
10707/* Hostapd events */
10708
10709#ifndef container_of
10710#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10711#define container_of(ptr, type, member) \
10712 ((type *)((char *)ptr - offset_of(type, member)))
10713#endif /* container_of */
10714
10715struct ctrl {
10716 char sockpath[128];
10717 char sockdir[128];
10718 char bss[IFNAMSIZ];
10719 char reply[4096];
10720 int ssid_index;
10721 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10722 void (*overrun)(struct ctrl *ctrl);
10723 struct wpa_ctrl *wpa;
10724 unsigned int ovfl;
10725 size_t reply_len;
10726 int initialized;
10727 ev_timer retry;
10728 ev_timer watchdog;
10729 ev_stat stat;
10730 ev_io io;
10731};
10732static wifi_newApAssociatedDevice_callback clients_connect_cb;
10733static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10734static struct ctrl wpa_ctrl[MAX_APS];
10735static int initialized;
10736
10737static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10738{
10739 char cbuf[256] = {};
10740 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10741 struct cmsghdr *cmsg;
10742 unsigned int ovfl = ctrl->ovfl;
10743 unsigned int drop;
10744
10745 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10746 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10747 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10748 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10749
10750 drop = ovfl - ctrl->ovfl;
10751 ctrl->ovfl = ovfl;
10752
10753 return drop;
10754}
10755
10756static void ctrl_close(struct ctrl *ctrl)
10757{
10758 if (ctrl->io.cb)
10759 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10760 if (ctrl->retry.cb)
10761 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10762 if (!ctrl->wpa)
10763 return;
10764
10765 wpa_ctrl_detach(ctrl->wpa);
10766 wpa_ctrl_close(ctrl->wpa);
10767 ctrl->wpa = NULL;
10768 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10769}
10770
10771static void ctrl_process(struct ctrl *ctrl)
10772{
10773 const char *str;
10774 int drops;
10775 int level;
10776 int err;
10777
10778 /* Example events:
10779 *
10780 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10781 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10782 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10783 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10784 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10785 */
10786 if (!(str = index(ctrl->reply, '>')))
10787 return;
10788 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10789 return;
10790
10791 str++;
10792
10793 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10794 if (!(str = index(ctrl->reply, ' ')))
10795 return;
10796 wifi_associated_dev_t sta;
10797 memset(&sta, 0, sizeof(sta));
10798
10799 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10800 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10801 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10802
10803 sta.cli_Active=true;
10804
10805 (clients_connect_cb)(ctrl->ssid_index, &sta);
10806 goto handled;
10807 }
10808
10809 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10810 if (!(str = index(ctrl->reply, ' ')))
10811 return;
10812
10813 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10814 goto handled;
10815 }
10816
10817 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10818 printf("CTRL_WPA: handle TERMINATING event\n");
10819 goto retry;
10820 }
10821
10822 if (strncmp("AP-DISABLED", str, 11) == 0) {
10823 printf("CTRL_WPA: handle AP-DISABLED\n");
10824 goto retry;
10825 }
10826
10827 printf("Event not supported!!\n");
10828
10829handled:
10830
10831 if ((drops = ctrl_get_drops(ctrl))) {
10832 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10833 if (ctrl->overrun)
10834 ctrl->overrun(ctrl);
10835 }
10836
10837 return;
10838
10839retry:
10840 printf("WPA_CTRL: closing\n");
10841 ctrl_close(ctrl);
10842 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10843 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10844}
10845
10846static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10847{
10848 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10849 int err;
10850
10851 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10852 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10853 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10854 ctrl->reply[ctrl->reply_len] = 0;
10855 if (err < 0) {
10856 if (errno == EAGAIN || errno == EWOULDBLOCK)
10857 return;
10858 ctrl_close(ctrl);
10859 ev_timer_again(EV_A_ &ctrl->retry);
10860 return;
10861 }
10862
10863 ctrl_process(ctrl);
10864}
10865
10866static int ctrl_open(struct ctrl *ctrl)
10867{
10868 int fd;
10869
10870 if (ctrl->wpa)
10871 return 0;
10872
10873 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10874 if (!ctrl->wpa)
10875 goto err;
10876
10877 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10878 goto err_close;
10879
10880 fd = wpa_ctrl_get_fd(ctrl->wpa);
10881 if (fd < 0)
10882 goto err_detach;
10883
10884 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10885 goto err_detach;
10886
10887 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10888 ev_io_start(EV_DEFAULT_ &ctrl->io);
10889
10890 return 0;
10891
10892err_detach:
10893 wpa_ctrl_detach(ctrl->wpa);
10894err_close:
10895 wpa_ctrl_close(ctrl->wpa);
10896err:
10897 ctrl->wpa = NULL;
10898 return -1;
10899}
10900
10901static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10902{
10903 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10904
10905 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10906 ctrl_open(ctrl);
10907}
10908
10909static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10910{
10911 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10912
10913 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10914 if (ctrl_open(ctrl) == 0) {
10915 printf("WPA_CTRL: retry successful\n");
10916 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10917 }
10918}
10919
10920int ctrl_enable(struct ctrl *ctrl)
10921{
10922 if (ctrl->wpa)
10923 return 0;
10924
10925 if (!ctrl->stat.cb) {
10926 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10927 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10928 }
10929
10930 if (!ctrl->retry.cb) {
10931 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10932 }
10933
10934 return ctrl_open(ctrl);
10935}
10936
10937static void
10938ctrl_msg_cb(char *buf, size_t len)
10939{
10940 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10941
10942 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10943 ctrl_process(ctrl);
10944}
10945
10946static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10947{
10948 int err;
10949
10950 if (!ctrl->wpa)
10951 return -1;
10952 if (*reply_len < 2)
10953 return -1;
10954
10955 (*reply_len)--;
10956 ctrl->reply_len = sizeof(ctrl->reply);
10957 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10958 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10959 if (err < 0)
10960 return err;
10961
10962 if (ctrl->reply_len > *reply_len)
10963 ctrl->reply_len = *reply_len;
10964
10965 *reply_len = ctrl->reply_len;
10966 memcpy(reply, ctrl->reply, *reply_len);
10967 reply[*reply_len - 1] = 0;
10968 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10969 return 0;
10970}
10971
10972static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10973{
10974 const char *pong = "PONG";
10975 const char *ping = "PING";
10976 char reply[1024];
10977 size_t len = sizeof(reply);
10978 int err;
10979 ULONG s, snum;
10980 INT ret;
10981 BOOL status;
10982
10983 printf("WPA_CTRL: watchdog cb\n");
10984
10985 ret = wifi_getSSIDNumberOfEntries(&snum);
10986 if (ret != RETURN_OK) {
10987 printf("%s: failed to get SSID count", __func__);
10988 return;
10989 }
10990
10991 if (snum > MAX_APS) {
10992 printf("more ssid than supported! %lu\n", snum);
10993 return;
10994 }
10995
10996 for (s = 0; s < snum; s++) {
10997 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010998 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010999 continue;
11000 }
11001 if (status == false) continue;
11002
11003 memset(reply, 0, sizeof(reply));
11004 len = sizeof(reply);
11005 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
11006 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
11007 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11008 continue;
11009
11010 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11011 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080011012 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080011013 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11014 }
11015}
11016
11017static int init_wpa()
11018{
11019 int ret = 0, i = 0;
11020 ULONG s, snum;
11021
11022 ret = wifi_getSSIDNumberOfEntries(&snum);
11023 if (ret != RETURN_OK) {
11024 printf("%s: failed to get SSID count", __func__);
11025 return RETURN_ERR;
11026 }
11027
11028 if (snum > MAX_APS) {
11029 printf("more ssid than supported! %lu\n", snum);
11030 return RETURN_ERR;
11031 }
11032
11033 for (s = 0; s < snum; s++) {
11034 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11035 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11036 wpa_ctrl[s].ssid_index = s;
11037 ctrl_enable(&wpa_ctrl[s]);
11038 }
11039
11040 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11041 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11042
11043 initialized = 1;
11044 printf("WPA_CTRL: initialized\n");
11045
11046 return RETURN_OK;
11047}
11048
11049void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11050{
11051 clients_connect_cb = callback_proc;
11052 if (!initialized)
11053 init_wpa();
11054}
11055
11056void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11057{
11058 clients_disconnect_cb = callback_proc;
11059 if (!initialized)
11060 init_wpa();
11061}
11062
11063INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11064{
11065 // TODO Implement me!
11066 return RETURN_ERR;
11067}
11068
11069INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11070{
11071 // TODO Implement me!
11072 return RETURN_ERR;
11073}
11074
11075INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11076{
11077 int i;
developer4b102122023-02-15 10:53:03 +080011078 int phyId = -1;
11079 char cmd[256] = {0};
11080 char channel_numbers_buf[256] = {0};
11081 char dfs_state_buf[256] = {0};
11082 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080011083 const char *ptr;
developer4b102122023-02-15 10:53:03 +080011084 BOOL dfs_enable = false;
developer06a01d92022-09-07 16:32:39 +080011085
developer4b102122023-02-15 10:53:03 +080011086 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080011087
developer4b102122023-02-15 10:53:03 +080011088 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11089 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011090
developer4b102122023-02-15 10:53:03 +080011091 snprintf(cmd, sizeof (cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v '%sno IR\\|5340\\|5480' | awk '{print $4}' | tr -d '[]'", phyId, dfs_enable?"":"radar\\|");
developer06a01d92022-09-07 16:32:39 +080011092
developer4b102122023-02-15 10:53:03 +080011093 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11094 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11095 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011096 }
11097
developer4b102122023-02-15 10:53:03 +080011098 ptr = channel_numbers_buf;
11099 i = 0;
11100 while (ptr = get_line_from_str_buf(ptr, line)) {
11101 if (i >= outputMapSize) {
11102 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11103 return RETURN_ERR;
11104 }
11105 sscanf(line, "%d", &outputMap[i].ch_number);
11106
11107 memset(cmd, 0, sizeof(cmd));
11108 // Below command should fetch string for DFS state (usable, available or unavailable)
11109 // Example line: "DFS state: usable (for 78930 sec)"
11110 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) {
11111 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011112 return RETURN_ERR;
11113 }
11114
developer4b102122023-02-15 10:53:03 +080011115 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11116 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011117 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11118 return RETURN_ERR;
11119 }
11120
developer4b102122023-02-15 10:53:03 +080011121 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011122
developer4b102122023-02-15 10:53:03 +080011123 if (!strcmp(dfs_state_buf, "usable")) {
11124 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11125 } else if (!strcmp(dfs_state_buf, "available")) {
11126 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11127 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11128 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11129 } else {
11130 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011131 }
developer4b102122023-02-15 10:53:03 +080011132 i++;
developer06a01d92022-09-07 16:32:39 +080011133 }
11134
developer4b102122023-02-15 10:53:03 +080011135 return RETURN_OK;
11136
developer06a01d92022-09-07 16:32:39 +080011137 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11138 return RETURN_ERR;
11139}
11140
11141INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11142{
11143 // TODO Implement me!
11144 return RETURN_ERR;
11145}
11146
11147INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11148{
11149 return RETURN_OK;
11150}
11151
11152INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11153{
11154 // TODO Implement me!
11155 return RETURN_ERR;
11156}
11157
11158INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11159{
11160 // TODO API refrence Implementaion is present on RPI hal
11161 return RETURN_ERR;
11162}
11163
developerfeab1d12023-09-27 11:29:38 +080011164
developer06a01d92022-09-07 16:32:39 +080011165INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11166{
developera5005b62022-09-13 15:43:35 +080011167 char cmd[128]={'\0'};
11168 char buf[128]={'\0'};
developerfeab1d12023-09-27 11:29:38 +080011169 int radioIndex = -1;
11170 int phyIndex = -1;
11171 bool enabled = false;
11172 int cur_tx_dbm = 0;
developera5005b62022-09-13 15:43:35 +080011173
11174 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerfeab1d12023-09-27 11:29:38 +080011175
developera5005b62022-09-13 15:43:35 +080011176 if(txpwr_pcntg == NULL)
11177 return RETURN_ERR;
11178
developerfeab1d12023-09-27 11:29:38 +080011179 // The API name as getRadioXXX, I think the input index should be radioIndex,
11180 // but current we not change the name, but use it as radioIndex
11181 radioIndex = apIndex;
11182 phyIndex = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +080011183
developera5005b62022-09-13 15:43:35 +080011184 // Get the maximum tx power of the device
developerfeab1d12023-09-27 11:29:38 +080011185 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11186 "grep 'Percentage Control:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011187 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011188 if (strcmp(buf, "enable") == 0)
11189 enabled = true;
developera5005b62022-09-13 15:43:35 +080011190
developerfeab1d12023-09-27 11:29:38 +080011191 if (!enabled) {
11192 *txpwr_pcntg = 100;
11193 return RETURN_OK;
11194 }
11195
developera5005b62022-09-13 15:43:35 +080011196 memset(cmd, 0, sizeof(cmd));
11197 memset(buf, 0, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011198 snprintf(cmd, sizeof(cmd), "cat /sys/kernel/debug/ieee80211/phy%d/mt76/txpower_info | "
11199 "grep 'Power Drop:' | awk '{print $3}' | tr -d '\\n'", phyIndex);
developera5005b62022-09-13 15:43:35 +080011200 _syscmd(cmd, buf, sizeof(buf));
developerfeab1d12023-09-27 11:29:38 +080011201 cur_tx_dbm = strtol(buf, NULL, 10);
developera5005b62022-09-13 15:43:35 +080011202
developerfeab1d12023-09-27 11:29:38 +080011203 switch (cur_tx_dbm) {
11204 case 0:
11205 *txpwr_pcntg = 100; // range 91-100
developera5005b62022-09-13 15:43:35 +080011206 break;
developerfeab1d12023-09-27 11:29:38 +080011207 case 1:
11208 *txpwr_pcntg = 75; // range 61-90
11209 break;
11210 case 3:
11211 *txpwr_pcntg = 50; // range 31-60
11212 break;
11213 case 6:
11214 *txpwr_pcntg = 25; // range 16-30
11215 break;
11216 case 9:
11217 *txpwr_pcntg = 12; // range 10-15
11218 break;
11219 case 12:
11220 *txpwr_pcntg = 6; // range 1-9
11221 break;
11222 default:
11223 *txpwr_pcntg = 100; // 0
developera5005b62022-09-13 15:43:35 +080011224 }
developerfeab1d12023-09-27 11:29:38 +080011225
developer06a01d92022-09-07 16:32:39 +080011226 return RETURN_OK;
11227}
11228
11229INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11230{
developer58599c22022-09-13 16:40:34 +080011231 // TODO precac feature.
11232 struct params params = {0};
11233 char config_file[128] = {0};
11234
11235 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11236
11237 params.name = "enable_background_radar";
11238 params.value = enable?"1":"0";
11239 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11240 wifi_hostapdWrite(config_file, &params, 1);
11241 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11242
11243 /* TODO precac feature */
11244
11245 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11246 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011247}
11248
11249INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11250{
developer58599c22022-09-13 16:40:34 +080011251 char config_file[128] = {0};
11252 char buf[64] = {0};
11253
11254 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11255 if (NULL == enable || NULL == precac)
11256 return RETURN_ERR;
11257
11258 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11259 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
developerf7e92b62023-05-04 17:06:52 +080011260 if (strncmp(buf, "1", 1) == 0) {
developer58599c22022-09-13 16:40:34 +080011261 *enable = true;
developerf7e92b62023-05-04 17:06:52 +080011262 *precac = true;
11263 } else {
developer58599c22022-09-13 16:40:34 +080011264 *enable = false;
developerf7e92b62023-05-04 17:06:52 +080011265 *precac = false;
11266 }
developer58599c22022-09-13 16:40:34 +080011267
11268 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11269 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011270}
11271
11272INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11273{
developer58599c22022-09-13 16:40:34 +080011274 *supported = TRUE;
11275 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011276}
11277
developera7149722023-01-11 11:36:21 +080011278bool check_is_hemu_vendor_new_patch() {
11279 char cmd[128] = {0};
11280 char buf[128] = {0};
11281
11282 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11283 _syscmd(cmd, buf, sizeof(buf));
11284
11285 if (strlen(buf) > 0)
11286 return FALSE;
11287 else
11288 return TRUE;
11289}
11290
developer3e6b1692022-09-30 18:04:05 +080011291INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11292{
11293 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11294 struct params params = {0};
11295 char config_file[64] = {0};
11296 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011297 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011298 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011299 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011300 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11301
developera7149722023-01-11 11:36:21 +080011302 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011303
11304 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11305 set_mu_type &= ~0x05; // unset bit 0, 2
11306 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11307 set_mu_type |= 0x01;
11308 set_mu_type &= ~0x04;
11309 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11310 set_mu_type &= ~0x01;
11311 set_mu_type |= 0x04;
11312 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11313 set_mu_type |= 0x05; // set bit 0, 2
11314 }
11315
developera7149722023-01-11 11:36:21 +080011316 new_vendor_patch = check_is_hemu_vendor_new_patch();
11317 if (new_vendor_patch)
11318 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11319 else
11320 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11321
11322 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011323 sprintf(buf, "%u", set_mu_type);
11324 params.value = buf;
11325 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11326 wifi_hostapdWrite(config_file, &params, 1);
11327 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011328 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011329
11330 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11331 return RETURN_OK;
11332}
11333
11334INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11335{
11336 struct params params={0};
11337 char config_file[64] = {0};
11338 char buf[64] = {0};
11339 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011340 bool new_vendor_patch = FALSE;
11341 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011342
11343 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11344
11345 if (mu_type == NULL)
11346 return RETURN_ERR;
11347
developera7149722023-01-11 11:36:21 +080011348 new_vendor_patch = check_is_hemu_vendor_new_patch();
11349
11350 if (new_vendor_patch)
11351 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11352 else
11353 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11354
developer3e6b1692022-09-30 18:04:05 +080011355 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011356 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011357 get_mu_type = strtol(buf, NULL, 10);
11358
11359 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11360 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11361 else if (get_mu_type & 0x04)
11362 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11363 else if (get_mu_type & 0x01)
11364 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11365 else
11366 *mu_type = WIFI_DL_MU_TYPE_NONE;
11367
11368 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11369 return RETURN_OK;
11370}
11371
11372INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11373{
11374 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11375 struct params params={0};
11376 char config_file[64] = {0};
11377 char buf[64] = {0};
11378 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011379 bool new_vendor_patch = FALSE;
11380 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11382
developera7149722023-01-11 11:36:21 +080011383 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011384
11385 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11386 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11387 set_mu_type &= ~0x0a;
11388 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11389 set_mu_type |= 0x02;
11390 set_mu_type &= ~0x08;
11391 }
11392
developera7149722023-01-11 11:36:21 +080011393 new_vendor_patch = check_is_hemu_vendor_new_patch();
11394
11395 if (new_vendor_patch)
11396 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11397 else
11398 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11399
11400 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011401 sprintf(buf, "%u", set_mu_type);
11402 params.value = buf;
11403 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11404 wifi_hostapdWrite(config_file, &params, 1);
11405 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011406 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011407
11408 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11409 return RETURN_OK;
11410}
11411
11412INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11413{
11414 struct params params={0};
11415 char config_file[64] = {0};
11416 char buf[64] = {0};
11417 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011418 bool new_vendor_patch = FALSE;
11419 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011420
11421 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11422
developera7149722023-01-11 11:36:21 +080011423 new_vendor_patch = check_is_hemu_vendor_new_patch();
11424
11425 if (new_vendor_patch)
11426 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11427 else
11428 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11429
developer3e6b1692022-09-30 18:04:05 +080011430 if (mu_type == NULL)
11431 return RETURN_ERR;
11432
11433 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011434 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011435
11436 get_mu_type = strtol(buf, NULL, 10);
11437 if (get_mu_type & 0x02)
11438 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11439 else
11440 *mu_type = WIFI_DL_MU_TYPE_NONE;
11441
11442 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11443 return RETURN_OK;
11444}
11445
11446
developer454b9462022-09-13 15:29:16 +080011447INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11448{
11449 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011450 char buf[256] = {0};
11451 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011452 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011453 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011454 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011455 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011456
11457 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11458
developer254882b2022-09-30 17:12:31 +080011459 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011460 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11461 return RETURN_ERR;
11462 }
developer454b9462022-09-13 15:29:16 +080011463
developer254882b2022-09-30 17:12:31 +080011464 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011465 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011466
developer254882b2022-09-30 17:12:31 +080011467 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11468 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011469 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011470 _syscmd(cmd, buf, sizeof(buf));
11471 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11472 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11473 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011474 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 +080011475 _syscmd(cmd, buf, sizeof(buf));
11476 }
11477 if (band == band_5) {
11478 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11479 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011480 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 +080011481 _syscmd(cmd, buf, sizeof(buf));
11482 }
11483 }
11484 }
11485 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011486
developer254882b2022-09-30 17:12:31 +080011487 if (guard_interval == wifi_guard_interval_400)
11488 strcpy(GI, "0.4");
11489 else if (guard_interval == wifi_guard_interval_800)
11490 strcpy(GI, "0.8");
11491 else if (guard_interval == wifi_guard_interval_1600)
11492 strcpy(GI, "1.6");
11493 else if (guard_interval == wifi_guard_interval_3200)
11494 strcpy(GI, "3.2");
11495 else if (guard_interval == wifi_guard_interval_auto)
11496 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011497 // Record GI for get GI function
11498 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11499 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011500 if (f == NULL)
11501 return RETURN_ERR;
11502 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011503 fclose(f);
11504 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11505 return RETURN_OK;
11506}
11507
11508INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11509{
11510 char buf[32] = {0};
11511 char cmd[64] = {0};
11512
11513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11514
11515 if (guard_interval == NULL)
11516 return RETURN_ERR;
11517
developer7c4cd202023-03-01 10:56:29 +080011518 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011519 _syscmd(cmd, buf, sizeof(buf));
11520
11521 if (strncmp(buf, "0.4", 3) == 0)
11522 *guard_interval = wifi_guard_interval_400;
11523 else if (strncmp(buf, "0.8", 3) == 0)
11524 *guard_interval = wifi_guard_interval_800;
11525 else if (strncmp(buf, "1.6", 3) == 0)
11526 *guard_interval = wifi_guard_interval_1600;
11527 else if (strncmp(buf, "3.2", 3) == 0)
11528 *guard_interval = wifi_guard_interval_3200;
11529 else
11530 *guard_interval = wifi_guard_interval_auto;
11531
11532 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11533 return RETURN_OK;
11534}
11535
developer3cc61d12022-09-13 16:36:05 +080011536INT wifi_setBSSColor(INT radio_index, UCHAR color)
11537{
11538 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11539 struct params params = {0};
11540 char config_file[128] = {0};
11541 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011542 UCHAR *color_list;
11543 int color_num = 0;
11544 int maxNumberColors = 64;
11545 BOOL color_is_aval = FALSE;
11546
developerbf0b9dc2023-07-06 14:30:54 +080011547 if (color > 63 || color == 0)
developer2acb9632023-03-14 14:58:31 +080011548 return RETURN_ERR;
11549
developer517f3be2023-05-08 10:02:39 +080011550 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11551 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK) {
11552 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011553 return RETURN_ERR;
developer517f3be2023-05-08 10:02:39 +080011554 }
developer2acb9632023-03-14 14:58:31 +080011555
11556 for (int i = 0; i < color_num; i++) {
11557 if (color_list[i] == color) {
11558 color_is_aval = TRUE;
11559 break;
11560 }
11561 }
11562 if (color_is_aval == FALSE) {
developer517f3be2023-05-08 10:02:39 +080011563 free(color_list);
developer2acb9632023-03-14 14:58:31 +080011564 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11565 return RETURN_ERR;
11566 }
developer3cc61d12022-09-13 16:36:05 +080011567
11568 params.name = "he_bss_color";
11569 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11570 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011571 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011572 wifi_hostapdWrite(config_file, &params, 1);
11573 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011574 wifi_reloadAp(radio_index);
11575
developer517f3be2023-05-08 10:02:39 +080011576 free(color_list);
developer3cc61d12022-09-13 16:36:05 +080011577 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11578 return RETURN_OK;
11579}
11580
11581INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11582{
developer3cc61d12022-09-13 16:36:05 +080011583 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011584 char cmd[128] = {0};
11585 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011586
developer3cc61d12022-09-13 16:36:05 +080011587 if (NULL == color)
11588 return RETURN_ERR;
11589
developer2acb9632023-03-14 14:58:31 +080011590 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11591 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011592
developer2acb9632023-03-14 14:58:31 +080011593 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11594 _syscmd(cmd, buf, sizeof(buf));
11595 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011596
developer2acb9632023-03-14 14:58:31 +080011597 return RETURN_OK;
11598}
11599
11600INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11601{
11602 char buf[64] = {0};
11603 char cmd[128] = {0};
11604 char interface_name[16] = {0};
11605 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011606
developer2acb9632023-03-14 14:58:31 +080011607 if (NULL == colorList || NULL == numColorReturned)
11608 return RETURN_ERR;
11609
11610 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11611 return RETURN_ERR;
11612
11613 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11614 _syscmd(cmd, buf, sizeof(buf));
11615 color_bitmap = strtoull(buf, NULL, 16);
11616
11617 *numColorReturned = 0;
11618 for (int i = 0; i < maxNumberColors; i++) {
11619 if (color_bitmap & 1) {
11620 colorList[*numColorReturned] = i;
11621 (*numColorReturned) += 1;
11622 }
11623 color_bitmap >>= 1;
11624 }
developer3cc61d12022-09-13 16:36:05 +080011625 return RETURN_OK;
11626}
11627
developer06a01d92022-09-07 16:32:39 +080011628/* multi-psk support */
11629INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11630{
11631 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011632 char interface_name[16] = {0};
11633
developerac6f1142022-12-20 19:26:35 +080011634 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011635 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011636
developerd946fd62022-12-08 18:03:28 +080011637 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11638 interface_name,
developer06a01d92022-09-07 16:32:39 +080011639 mac[0],
11640 mac[1],
11641 mac[2],
11642 mac[3],
11643 mac[4],
11644 mac[5]
11645 );
11646 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11647 _syscmd(cmd, key->wifi_keyId, 64);
11648
11649
11650 return RETURN_OK;
11651}
11652
11653INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11654{
developerd946fd62022-12-08 18:03:28 +080011655 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011656 FILE *fd = NULL;
11657 char fname[100];
11658 char cmd[128] = {0};
11659 char out[64] = {0};
11660 wifi_key_multi_psk_t * key = NULL;
11661 if(keysNumber < 0)
11662 return RETURN_ERR;
11663
developer431128d2022-12-16 15:30:41 +080011664 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011665 fd = fopen(fname, "w");
11666 if (!fd) {
11667 return RETURN_ERR;
11668 }
11669 key= (wifi_key_multi_psk_t *) keys;
11670 for(int i=0; i<keysNumber; ++i, key++) {
11671 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11672 }
11673 fclose(fd);
11674
11675 //reload file
developerac6f1142022-12-20 19:26:35 +080011676 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011677 return RETURN_ERR;
11678 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011679 _syscmd(cmd, out, 64);
11680 return RETURN_OK;
11681}
11682
11683INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11684{
11685 FILE *fd = NULL;
11686 char fname[100];
11687 char * line = NULL;
11688 char * pos = NULL;
11689 size_t len = 0;
11690 ssize_t read = 0;
11691 INT ret = RETURN_OK;
11692 wifi_key_multi_psk_t *keys_it = NULL;
11693
11694 if (keysNumber < 1) {
11695 return RETURN_ERR;
11696 }
11697
developer431128d2022-12-16 15:30:41 +080011698 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011699 fd = fopen(fname, "r");
11700 if (!fd) {
11701 return RETURN_ERR;
11702 }
11703
11704 if (keys == NULL) {
11705 ret = RETURN_ERR;
11706 goto close;
11707 }
11708
11709 keys_it = keys;
11710 while ((read = getline(&line, &len, fd)) != -1) {
11711 //Strip trailing new line if present
11712 if (read > 0 && line[read-1] == '\n') {
11713 line[read-1] = '\0';
11714 }
11715
11716 if(strcmp(line,"keyid=")) {
11717 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11718 if (!(pos = index(line, ' '))) {
11719 ret = RETURN_ERR;
11720 goto close;
11721 }
11722 pos++;
11723 //Here should be 00:00:00:00:00:00
11724 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11725 printf("Not supported MAC: %s\n", pos);
11726 }
11727 if (!(pos = index(pos, ' '))) {
11728 ret = RETURN_ERR;
11729 goto close;
11730 }
11731 pos++;
11732
11733 //The rest is PSK
11734 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11735 keys_it++;
11736
11737 if(--keysNumber <= 0)
11738 break;
11739 }
11740 }
11741
11742close:
11743 free(line);
11744 fclose(fd);
11745 return ret;
11746}
11747/* end of multi-psk support */
11748
11749INT wifi_setNeighborReports(UINT apIndex,
11750 UINT numNeighborReports,
11751 wifi_NeighborReport_t *neighborReports)
11752{
11753 char cmd[256] = { 0 };
11754 char hex_bssid[13] = { 0 };
11755 char bssid[18] = { 0 };
11756 char nr[256] = { 0 };
11757 char ssid[256];
11758 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011759 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011760 INT ret;
11761
11762 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011763 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011764 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011765 return RETURN_ERR;
11766 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 +080011767 system(cmd);
11768
11769 for(unsigned int i = 0; i < numNeighborReports; i++)
11770 {
11771 memset(ssid, 0, sizeof(ssid));
11772 ret = wifi_getSSIDName(apIndex, ssid);
11773 if (ret != RETURN_OK)
11774 return RETURN_ERR;
11775
11776 memset(hex_ssid, 0, sizeof(hex_ssid));
11777 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11778 sprintf(hex_ssid + k,"%02x", ssid[j]);
11779
11780 snprintf(hex_bssid, sizeof(hex_bssid),
11781 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11782 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11783 snprintf(bssid, sizeof(bssid),
11784 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11785 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11786
11787 snprintf(nr, sizeof(nr),
11788 "%s" // bssid
11789 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11790 "%02hhx" // operclass
11791 "%02hhx" // channel
11792 "%02hhx", // phy_mode
11793 hex_bssid,
11794 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11795 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11796 neighborReports[i].opClass,
11797 neighborReports[i].channel,
11798 neighborReports[i].phyTable);
11799
11800 snprintf(cmd, sizeof(cmd),
11801 "hostapd_cli set_neighbor "
11802 "%s " // bssid
11803 "ssid=%s " // ssid
11804 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011805 "-i %s",
11806 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011807
11808 if (WEXITSTATUS(system(cmd)) != 0)
11809 {
11810 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11811 }
11812 }
11813
11814 return RETURN_OK;
11815}
11816
11817INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11818{
11819 return RETURN_OK;
11820}
11821
11822#ifdef _WIFI_HAL_TEST_
11823int main(int argc,char **argv)
11824{
11825 int index;
11826 INT ret=0;
11827 char buf[1024]="";
11828
11829 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11830 if(argc<3)
11831 {
11832 if(argc==2)
11833 {
11834 if(!strcmp(argv[1], "init"))
11835 return wifi_init();
11836 if(!strcmp(argv[1], "reset"))
11837 return wifi_reset();
11838 if(!strcmp(argv[1], "wifi_getHalVersion"))
11839 {
11840 char buffer[64];
11841 if(wifi_getHalVersion(buffer)==RETURN_OK)
11842 printf("Version: %s\n", buffer);
11843 else
11844 printf("Error in wifi_getHalVersion\n");
11845 return RETURN_OK;
11846 }
11847 }
11848 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11849 exit(-1);
11850 }
11851
11852 index = atoi(argv[2]);
11853 if(strstr(argv[1], "wifi_getApName")!=NULL)
11854 {
11855 wifi_getApName(index,buf);
11856 printf("Ap name is %s \n",buf);
11857 return 0;
11858 }
11859 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11860 {
11861 BOOL b = FALSE;
11862 BOOL *output_bool = &b;
11863 wifi_getRadioAutoChannelEnable(index,output_bool);
11864 printf("Channel enabled = %d \n",b);
11865 return 0;
11866 }
11867 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11868 {
11869 wifi_getApWpaEncryptionMode(index,buf);
11870 printf("encryption enabled = %s\n",buf);
11871 return 0;
11872 }
11873 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11874 {
11875 BOOL b = FALSE;
11876 BOOL *output_bool = &b;
11877 wifi_getApSsidAdvertisementEnable(index,output_bool);
11878 printf("advertisment enabled = %d\n",b);
11879 return 0;
11880 }
11881 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11882 {
11883 if(argc <= 3 )
11884 {
11885 printf("Insufficient arguments \n");
11886 exit(-1);
11887 }
11888
11889 char sta[20] = {'\0'};
11890 ULLONG handle= 0;
11891 strcpy(sta,argv[3]);
11892 mac_address_t st;
11893 mac_addr_aton(st,sta);
11894
11895 wifi_associated_dev_tid_stats_t tid_stats;
11896 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11897 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11898 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);
11899 }
11900
11901 if(strstr(argv[1], "getApEnable")!=NULL) {
11902 BOOL enable;
11903 ret=wifi_getApEnable(index, &enable);
11904 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11905 }
11906 else if(strstr(argv[1], "setApEnable")!=NULL) {
11907 BOOL enable = atoi(argv[3]);
11908 ret=wifi_setApEnable(index, enable);
11909 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11910 }
11911 else if(strstr(argv[1], "getApStatus")!=NULL) {
11912 char status[64];
11913 ret=wifi_getApStatus(index, status);
11914 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11915 }
11916 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11917 {
11918 wifi_getSSIDNameStatus(index,buf);
11919 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11920 return 0;
11921 }
11922 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11923 wifi_ssidTrafficStats2_t stats={0};
11924 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11925 printf("%s %d: returns %d\n", argv[1], index, ret);
11926 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11927 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11928 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11929 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11930 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11931 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11932 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11933 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11934 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11935 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11936 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11937 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11938 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11939 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11940 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11941 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11942 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11943 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11944 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11945 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11946 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11947 }
11948 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11949 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11950 UINT array_size=0;
11951 UINT i=0;
11952 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11953 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11954 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11955 printf(" neighbor %d:\n", i);
11956 printf(" ap_SSID =%s\n", pt->ap_SSID);
11957 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11958 printf(" ap_Mode =%s\n", pt->ap_Mode);
11959 printf(" ap_Channel =%d\n", pt->ap_Channel);
11960 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11961 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11962 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11963 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11964 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11965 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11966 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11967 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11968 printf(" ap_Noise =%d\n", pt->ap_Noise);
11969 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11970 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11971 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11972 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11973 }
11974 if(neighbor_ap_array)
11975 free(neighbor_ap_array); //make sure to free the list
11976 }
11977 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11978 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11979 UINT array_size=0;
11980 UINT i=0;
11981 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11982 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11983 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11984 printf(" associated_dev %d:\n", i);
11985 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11986 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11987 printf(" cli_SNR =%d\n", pt->cli_SNR);
11988 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11989 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11990 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11991 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11992 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11993 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11994 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11995 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11996 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11997 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11998 }
11999 if(associated_dev_array)
12000 free(associated_dev_array); //make sure to free the list
12001 }
12002
12003 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
12004 {
12005#define MAX_ARRAY_SIZE 64
12006 int i, array_size;
12007 char *p, *ch_str;
12008 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
12009
12010 if(argc != 5)
12011 {
12012 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
12013 exit(-1);
12014 }
12015 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
12016
12017 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
12018 {
12019 strtok_r(ch_str, ",", &p);
12020 input_output_channelStats_array[i].ch_number = atoi(ch_str);
12021 }
12022 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
12023 if(!array_size)
12024 array_size=1;//Need to print current channel statistics
12025 for(i=0; i<array_size; i++)
12026 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12027 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12028 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12029 input_output_channelStats_array[i].ch_number,\
12030 input_output_channelStats_array[i].ch_noise,\
12031 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12032 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12033 input_output_channelStats_array[i].ch_utilization_busy,\
12034 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12035 input_output_channelStats_array[i].ch_utilization_total);
12036 }
12037
12038 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12039 {
12040 if(argc <= 3 )
12041 {
12042 printf("Insufficient arguments \n");
12043 exit(-1);
12044 }
12045 char mac_addr[20] = {'\0'};
12046 wifi_device_t output_struct;
12047 int dev_index = atoi(argv[3]);
12048
12049 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12050 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12051 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);
12052 }
12053
12054 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12055 {
12056 if (argc <= 3)
12057 {
12058 printf("Insufficient arguments\n");
12059 exit(-1);
12060 }
12061 char args[256];
12062 wifi_NeighborReport_t *neighborReports;
12063
12064 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12065 if (!neighborReports)
12066 {
12067 printf("Failed to allocate memory");
12068 exit(-1);
12069 }
12070
12071 for (int i = 3; i < argc; ++i)
12072 {
12073 char *val;
12074 int j = 0;
12075 memset(args, 0, sizeof(args));
12076 strncpy(args, argv[i], sizeof(args));
12077 val = strtok(args, ";");
12078 while (val != NULL)
12079 {
12080 if (j == 0)
12081 {
12082 mac_addr_aton(neighborReports[i - 3].bssid, val);
12083 } else if (j == 1)
12084 {
12085 neighborReports[i - 3].info = strtol(val, NULL, 16);
12086 } else if (j == 2)
12087 {
12088 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12089 } else if (j == 3)
12090 {
12091 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12092 } else if (j == 4)
12093 {
12094 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12095 } else {
12096 printf("Insufficient arguments]n\n");
12097 exit(-1);
12098 }
12099 val = strtok(NULL, ";");
12100 j++;
12101 }
12102 }
12103
12104 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12105 if (ret != RETURN_OK)
12106 {
12107 printf("wifi_setNeighborReports ret = %d", ret);
12108 exit(-1);
12109 }
12110 }
12111 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12112 {
12113 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12114 printf("%s.\n", buf);
12115 else
12116 printf("Error returned\n");
12117 }
12118 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12119 {
12120 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12121 printf("%s.\n", buf);
12122 else
12123 printf("Error returned\n");
12124 }
12125 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12126 {
12127 if (argc <= 2)
12128 {
12129 printf("Insufficient arguments\n");
12130 exit(-1);
12131 }
12132 char buf[64]= {'\0'};
12133 wifi_getRadioOperatingChannelBandwidth(index,buf);
12134 printf("Current bandwidth is %s \n",buf);
12135 return 0;
12136 }
12137 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12138 {
12139 if (argc <= 5)
12140 {
12141 printf("Insufficient arguments\n");
12142 exit(-1);
12143 }
12144 UINT channel = atoi(argv[3]);
12145 UINT width = atoi(argv[4]);
12146 UINT beacon = atoi(argv[5]);
12147 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12148 printf("Result = %d", ret);
12149 }
12150
12151 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12152 return 0;
12153}
12154
12155#endif
12156
12157#ifdef WIFI_HAL_VERSION_3
12158
developer1e5aa162022-09-13 16:06:24 +080012159INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12160{
12161 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12162 if (bitMap & WIFI_BITRATE_1MBPS)
12163 strcat(BasicRate, "1,");
12164 if (bitMap & WIFI_BITRATE_2MBPS)
12165 strcat(BasicRate, "2,");
12166 if (bitMap & WIFI_BITRATE_5_5MBPS)
12167 strcat(BasicRate, "5.5,");
12168 if (bitMap & WIFI_BITRATE_6MBPS)
12169 strcat(BasicRate, "6,");
12170 if (bitMap & WIFI_BITRATE_9MBPS)
12171 strcat(BasicRate, "9,");
12172 if (bitMap & WIFI_BITRATE_11MBPS)
12173 strcat(BasicRate, "11,");
12174 if (bitMap & WIFI_BITRATE_12MBPS)
12175 strcat(BasicRate, "12,");
12176 if (bitMap & WIFI_BITRATE_18MBPS)
12177 strcat(BasicRate, "18,");
12178 if (bitMap & WIFI_BITRATE_24MBPS)
12179 strcat(BasicRate, "24,");
12180 if (bitMap & WIFI_BITRATE_36MBPS)
12181 strcat(BasicRate, "36,");
12182 if (bitMap & WIFI_BITRATE_48MBPS)
12183 strcat(BasicRate, "48,");
12184 if (bitMap & WIFI_BITRATE_54MBPS)
12185 strcat(BasicRate, "54,");
12186 if (strlen(BasicRate) != 0) // remove last comma
12187 BasicRate[strlen(BasicRate) - 1] = '\0';
12188 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12189 return RETURN_OK;
12190}
12191
12192INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12193{
12194 UINT BitMap = 0;
12195 char *rate;
12196
12197 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12198 rate = strtok(BasicRatesList, ",");
12199 while(rate != NULL)
12200 {
12201 if (strcmp(rate, "1") == 0)
12202 BitMap |= WIFI_BITRATE_1MBPS;
12203 else if (strcmp(rate, "2") == 0)
12204 BitMap |= WIFI_BITRATE_2MBPS;
12205 else if (strcmp(rate, "5.5") == 0)
12206 BitMap |= WIFI_BITRATE_5_5MBPS;
12207 else if (strcmp(rate, "6") == 0)
12208 BitMap |= WIFI_BITRATE_6MBPS;
12209 else if (strcmp(rate, "9") == 0)
12210 BitMap |= WIFI_BITRATE_9MBPS;
12211 else if (strcmp(rate, "11") == 0)
12212 BitMap |= WIFI_BITRATE_11MBPS;
12213 else if (strcmp(rate, "12") == 0)
12214 BitMap |= WIFI_BITRATE_12MBPS;
12215 else if (strcmp(rate, "18") == 0)
12216 BitMap |= WIFI_BITRATE_18MBPS;
12217 else if (strcmp(rate, "24") == 0)
12218 BitMap |= WIFI_BITRATE_24MBPS;
12219 else if (strcmp(rate, "36") == 0)
12220 BitMap |= WIFI_BITRATE_36MBPS;
12221 else if (strcmp(rate, "48") == 0)
12222 BitMap |= WIFI_BITRATE_48MBPS;
12223 else if (strcmp(rate, "54") == 0)
12224 BitMap |= WIFI_BITRATE_54MBPS;
12225 rate = strtok(NULL, ",");
12226 }
12227 *basicRateBitMap = BitMap;
12228 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12229 return RETURN_OK;
12230}
12231
developer7c4cd202023-03-01 10:56:29 +080012232INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12233{
12234 int center_channel = 0;
12235 char central_channel_str[16] = {0};
12236 char config_file[32] = {0};
12237 struct params param = {0};
12238
12239 center_channel = util_unii_6g_centerfreq("HT320", channel);
12240 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12241 if (channel >= 193)
12242 return RETURN_ERR;
12243 if (channel >= 33) {
12244 if (channel > center_channel)
12245 center_channel += 32;
12246 else
12247 center_channel -= 32;
12248 }
12249 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12250 if (channel <= 29)
12251 return RETURN_ERR;
12252 }
12253 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12254 param.name = "eht_oper_centr_freq_seg0_idx";
12255 param.value = central_channel_str;
12256 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12257 wifi_hostapdWrite(config_file, &param, 1);
12258
12259 return RETURN_OK;
12260}
12261
12262INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12263{
12264 int op_class = 0;
12265 char config_file[32] = {0};
12266 char op_class_str[8] = {0};
12267 struct params param = {0};
12268
12269 if (bandwidth == 20)
12270 op_class = 131;
12271 else if (bandwidth == 40)
12272 op_class = 132;
12273 else if (bandwidth == 80)
12274 op_class = 133;
12275 else if (bandwidth == 160)
12276 op_class = 134;
12277 else if (bandwidth == 320)
12278 op_class = 137;
12279 else
12280 return RETURN_ERR;
12281 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12282 param.name = "op_class";
12283 param.value = op_class_str;
12284 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12285 wifi_hostapdWrite(config_file, &param, 1);
12286 return RETURN_OK;
12287}
12288
12289INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12290{
12291 char config_file[32] = {0};
12292 char buf [16] = {0};
12293
12294 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12295 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12296 return RETURN_ERR; // 6g band should set op_class
12297 *class = (UINT)strtoul(buf, NULL, 10);
12298
12299 return RETURN_OK;
12300}
12301
developer1e5aa162022-09-13 16:06:24 +080012302// 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 +080012303INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12304{
developer1e5aa162022-09-13 16:06:24 +080012305 char buf[128] = {0};
12306 char cmd[128] = {0};
12307 char config_file[64] = {0};
12308 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012309 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012310 wifi_radio_operationParam_t current_param;
12311
12312 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12313
12314 multiple_set = TRUE;
12315 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12316 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12317 return RETURN_ERR;
12318 }
12319 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12320 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12321 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12322 return RETURN_ERR;
12323 }
12324 }
developer5884e982022-10-06 10:52:50 +080012325
12326 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12327 bandwidth = 20;
12328 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12329 bandwidth = 40;
12330 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12331 bandwidth = 80;
12332 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12333 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012334 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12335 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012336 if (operationParam->autoChannelEnabled){
12337 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12338 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12339 return RETURN_ERR;
12340 }
12341 }else{
developer1e5aa162022-09-13 16:06:24 +080012342 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12343 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12344 return RETURN_ERR;
12345 }
12346 }
developer5884e982022-10-06 10:52:50 +080012347
developer7c4cd202023-03-01 10:56:29 +080012348 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12349 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12350 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12351 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12352 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12353 return RETURN_ERR;
12354 }
12355 }
12356
12357 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12358 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12359 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12360 return RETURN_ERR;
12361 }
12362 }
12363
developer1e5aa162022-09-13 16:06:24 +080012364 if (current_param.variant != operationParam->variant) {
12365 // Two different definition bit map, so need to check every bit.
12366 if (operationParam->variant & WIFI_80211_VARIANT_A)
12367 set_mode |= WIFI_MODE_A;
12368 if (operationParam->variant & WIFI_80211_VARIANT_B)
12369 set_mode |= WIFI_MODE_B;
12370 if (operationParam->variant & WIFI_80211_VARIANT_G)
12371 set_mode |= WIFI_MODE_G;
12372 if (operationParam->variant & WIFI_80211_VARIANT_N)
12373 set_mode |= WIFI_MODE_N;
12374 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12375 set_mode |= WIFI_MODE_AC;
12376 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12377 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012378 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12379 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012380 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12381 memset(buf, 0, sizeof(buf));
12382 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12383 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12384 return RETURN_ERR;
12385 }
12386 }
12387 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12388 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12389 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12390 return RETURN_ERR;
12391 }
12392 }
12393 if (current_param.beaconInterval != operationParam->beaconInterval) {
12394 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12395 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12396 return RETURN_ERR;
12397 }
12398 }
12399 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12400 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12401 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12402 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12403 return RETURN_ERR;
12404 }
12405 }
12406 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12407 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12408 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12409 return RETURN_ERR;
12410 }
12411 }
12412 if (current_param.guardInterval != operationParam->guardInterval) {
12413 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12414 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12415 return RETURN_ERR;
12416 }
12417 }
12418 if (current_param.transmitPower != operationParam->transmitPower) {
12419 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12420 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12421 return RETURN_ERR;
12422 }
12423 }
12424 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12425 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12426 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12427 return RETURN_ERR;
12428 }
12429 }
12430 if (current_param.obssCoex != operationParam->obssCoex) {
12431 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12432 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12433 return RETURN_ERR;
12434 }
12435 }
12436 if (current_param.stbcEnable != operationParam->stbcEnable) {
12437 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12438 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12439 return RETURN_ERR;
12440 }
12441 }
developer5735d092023-09-19 20:12:26 +080012442 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12443 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12444 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12445 return RETURN_ERR;
12446 }
12447 }
developer1e5aa162022-09-13 16:06:24 +080012448
12449 // if enable is true, then restart the radio
12450 wifi_setRadioEnable(index, FALSE);
12451 if (operationParam->enable == TRUE)
12452 wifi_setRadioEnable(index, TRUE);
12453 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12454
developer06a01d92022-09-07 16:32:39 +080012455 return RETURN_OK;
12456}
12457
12458INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12459{
developer1e5aa162022-09-13 16:06:24 +080012460 char band[64] = {0};
12461 char buf[256] = {0};
12462 char config_file[64] = {0};
12463 char cmd[128] = {0};
12464 int ret = RETURN_ERR;
12465 int mode = 0;
12466 ULONG channel = 0;
12467 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012468
12469 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12470 printf("Entering %s index = %d\n", __func__, (int)index);
12471
developer1e5aa162022-09-13 16:06:24 +080012472 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12473 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12474 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012475 {
developer1e5aa162022-09-13 16:06:24 +080012476 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012477 return RETURN_ERR;
12478 }
12479 operationParam->enable = enabled;
12480
12481 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012482 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012483 {
developer1e5aa162022-09-13 16:06:24 +080012484 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012485 return RETURN_ERR;
12486 }
12487
12488 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012489 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012490 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012491 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012492 else if (!strcmp(band, "6GHz"))
12493 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012494 else
12495 {
developer1e5aa162022-09-13 16:06:24 +080012496 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012497 band);
12498 }
12499
developer1e5aa162022-09-13 16:06:24 +080012500 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12501 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12502 operationParam->channel = 0;
12503 operationParam->autoChannelEnabled = TRUE;
12504 } else {
12505 operationParam->channel = strtol(buf, NULL, 10);
12506 operationParam->autoChannelEnabled = FALSE;
12507 }
12508
developer06a01d92022-09-07 16:32:39 +080012509 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012510 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12511 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12512 return RETURN_ERR;
12513 }
developer06a01d92022-09-07 16:32:39 +080012514 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12515 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12516 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012517 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012518 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12519 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012520 else
12521 {
developer1e5aa162022-09-13 16:06:24 +080012522 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12523 return false;
developer06a01d92022-09-07 16:32:39 +080012524 }
12525
developer7c4cd202023-03-01 10:56:29 +080012526 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12527 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12528 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12529 return RETURN_ERR;
12530 }
12531 }
12532
developer1e5aa162022-09-13 16:06:24 +080012533 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12534 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12535 return RETURN_ERR;
12536 }
12537 // Two different definition bit map, so need to check every bit.
12538 if (mode & WIFI_MODE_A)
12539 operationParam->variant |= WIFI_80211_VARIANT_A;
12540 if (mode & WIFI_MODE_B)
12541 operationParam->variant |= WIFI_80211_VARIANT_B;
12542 if (mode & WIFI_MODE_G)
12543 operationParam->variant |= WIFI_80211_VARIANT_G;
12544 if (mode & WIFI_MODE_N)
12545 operationParam->variant |= WIFI_80211_VARIANT_N;
12546 if (mode & WIFI_MODE_AC)
12547 operationParam->variant |= WIFI_80211_VARIANT_AC;
12548 if (mode & WIFI_MODE_AX)
12549 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012550 if (mode & WIFI_MODE_BE)
12551 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012552 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12553 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12554 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012555 }
developer1e5aa162022-09-13 16:06:24 +080012556 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12557 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12558 return RETURN_ERR;
12559 }
12560 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12561 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12562 return RETURN_ERR;
12563 }
developer06a01d92022-09-07 16:32:39 +080012564
developer1e5aa162022-09-13 16:06:24 +080012565 memset(buf, 0, sizeof(buf));
12566 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12567 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12568 return RETURN_ERR;
12569 }
12570 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12571
12572 memset(buf, 0, sizeof(buf));
12573 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12574 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12575 return RETURN_ERR;
12576 }
12577 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12578
12579 memset(buf, 0, sizeof(buf));
12580 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12581 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12582
12583 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12584 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12585 return RETURN_ERR;
12586 }
12587 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12588 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12589 return RETURN_ERR;
12590 }
12591
12592 memset(buf, 0, sizeof(buf));
12593 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12594 if (strcmp(buf, "-1") == 0) {
12595 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12596 operationParam->ctsProtection = FALSE;
12597 } else {
12598 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12599 operationParam->ctsProtection = TRUE;
12600 }
12601
12602 memset(buf, 0, sizeof(buf));
12603 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12604 if (strcmp(buf, "0") == 0)
12605 operationParam->obssCoex = FALSE;
12606 else
12607 operationParam->obssCoex = TRUE;
12608
12609 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12610 _syscmd(cmd, buf, sizeof(buf));
12611 if (strlen(buf) != 0)
12612 operationParam->stbcEnable = TRUE;
12613 else
12614 operationParam->stbcEnable = FALSE;
12615
developer5735d092023-09-19 20:12:26 +080012616 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12617 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12618 return RETURN_ERR;
12619 }
developer1e5aa162022-09-13 16:06:24 +080012620
12621 // Below value is hardcoded
12622
12623 operationParam->numSecondaryChannels = 0;
12624 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12625 operationParam->channelSecondary[i] = 0;
12626 }
12627 operationParam->csa_beacon_count = 15;
12628 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012629
12630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12631 return RETURN_OK;
12632}
12633
12634static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12635{
developerc086fb72022-10-04 10:18:22 +080012636 int max_radio_num = 0;
12637
12638 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012639 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012640 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12641 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012642 }
12643
developerc086fb72022-10-04 10:18:22 +080012644 return (arrayIndex * max_radio_num) + radioIndex;
12645}
developer06a01d92022-09-07 16:32:39 +080012646
developerc086fb72022-10-04 10:18:22 +080012647wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12648 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12649 return WIFI_BITRATE_1MBPS;
12650 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12651 return WIFI_BITRATE_2MBPS;
12652 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12653 return WIFI_BITRATE_5_5MBPS;
12654 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12655 return WIFI_BITRATE_6MBPS;
12656 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12657 return WIFI_BITRATE_9MBPS;
12658 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12659 return WIFI_BITRATE_11MBPS;
12660 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12661 return WIFI_BITRATE_12MBPS;
12662 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12663 return WIFI_BITRATE_18MBPS;
12664 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12665 return WIFI_BITRATE_24MBPS;
12666 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12667 return WIFI_BITRATE_36MBPS;
12668 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12669 return WIFI_BITRATE_48MBPS;
12670 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12671 return WIFI_BITRATE_54MBPS;
12672 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012673}
12674
developer1d57d002022-10-12 18:03:15 +080012675INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12676{
12677 if (beacon == WIFI_BITRATE_1MBPS)
12678 strcpy(beacon_str, "1Mbps");
12679 else if (beacon == WIFI_BITRATE_2MBPS)
12680 strcpy(beacon_str, "2Mbps");
12681 else if (beacon == WIFI_BITRATE_5_5MBPS)
12682 strcpy(beacon_str, "5.5Mbps");
12683 else if (beacon == WIFI_BITRATE_6MBPS)
12684 strcpy(beacon_str, "6Mbps");
12685 else if (beacon == WIFI_BITRATE_9MBPS)
12686 strcpy(beacon_str, "9Mbps");
12687 else if (beacon == WIFI_BITRATE_11MBPS)
12688 strcpy(beacon_str, "11Mbps");
12689 else if (beacon == WIFI_BITRATE_12MBPS)
12690 strcpy(beacon_str, "12Mbps");
12691 else if (beacon == WIFI_BITRATE_18MBPS)
12692 strcpy(beacon_str, "18Mbps");
12693 else if (beacon == WIFI_BITRATE_24MBPS)
12694 strcpy(beacon_str, "24Mbps");
12695 else if (beacon == WIFI_BITRATE_36MBPS)
12696 strcpy(beacon_str, "36Mbps");
12697 else if (beacon == WIFI_BITRATE_48MBPS)
12698 strcpy(beacon_str, "48Mbps");
12699 else if (beacon == WIFI_BITRATE_54MBPS)
12700 strcpy(beacon_str, "54Mbps");
12701 return RETURN_OK;
12702}
12703
developer74ed4192023-09-21 17:15:17 +080012704void checkVapStatus(int apIndex, bool *enable)
12705{
12706 char if_name[16] = {0};
12707 char cmd[128] = {0};
12708 char buf[128] = {0};
12709
12710 *enable = FALSE;
12711 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12712 return;
12713
12714 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12715 _syscmd(cmd, buf, sizeof(buf));
12716 if (strlen(buf) > 0)
12717 *enable = TRUE;
12718 return;
12719}
12720
developer06a01d92022-09-07 16:32:39 +080012721INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12722{
developerc086fb72022-10-04 10:18:22 +080012723 INT mode = 0;
12724 INT ret = -1;
12725 INT output = 0;
12726 int i = 0;
12727 int vap_index = 0;
12728 BOOL enabled = FALSE;
12729 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012730 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012731
developer06a01d92022-09-07 16:32:39 +080012732
12733 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12734 printf("Entering %s index = %d\n", __func__, (int)index);
12735
developera77d84b2023-02-22 16:10:50 +080012736 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012737 {
developerc086fb72022-10-04 10:18:22 +080012738 map->vap_array[i].radio_index = index;
12739
developer06a01d92022-09-07 16:32:39 +080012740 vap_index = array_index_to_vap_index(index, i);
12741 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012742 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012743
developerc086fb72022-10-04 10:18:22 +080012744 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012745
12746 map->vap_array[i].vap_index = vap_index;
12747
12748 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012749 ret = wifi_getApName(vap_index, buf);
12750 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012751 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12752
developerc086fb72022-10-04 10:18:22 +080012753 return RETURN_ERR;
12754 }
12755 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12756
12757 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012758 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012759 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012760 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012761 return RETURN_ERR;
12762 }
12763 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 +080012764
developer74ed4192023-09-21 17:15:17 +080012765 checkVapStatus(vap_index, &enabled);
developer06a01d92022-09-07 16:32:39 +080012766 map->vap_array[i].u.bss_info.enabled = enabled;
12767
developerc086fb72022-10-04 10:18:22 +080012768 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12769 if (ret != RETURN_OK) {
12770 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12771 return RETURN_ERR;
12772 }
developer06a01d92022-09-07 16:32:39 +080012773 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012774
12775 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12776 if (ret != RETURN_OK) {
12777 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12778 return RETURN_ERR;
12779 }
12780 map->vap_array[i].u.bss_info.isolation = enabled;
12781
12782 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12783 if (ret != RETURN_OK) {
12784 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12785 return RETURN_ERR;
12786 }
12787 map->vap_array[i].u.bss_info.bssMaxSta = output;
12788
12789 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12790 if (ret != RETURN_OK) {
12791 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12792 return RETURN_ERR;
12793 }
12794 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012795
developerc086fb72022-10-04 10:18:22 +080012796 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12797 if (ret != RETURN_OK) {
12798 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12799 return RETURN_ERR;
12800 }
12801 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012802
developerc086fb72022-10-04 10:18:22 +080012803 ret = wifi_getApSecurity(vap_index, &security);
12804 if (ret != RETURN_OK) {
12805 printf("%s: wifi_getApSecurity return error\n", __func__);
12806 return RETURN_ERR;
12807 }
12808 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012809
developerc086fb72022-10-04 10:18:22 +080012810 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12811 if (ret != RETURN_OK) {
12812 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12813 return RETURN_ERR;
12814 }
12815 if (mode == 0)
12816 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12817 else
12818 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12819 if (mode == 1)
12820 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12821 else if (mode == 2)
12822 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012823
developerc086fb72022-10-04 10:18:22 +080012824 ret = wifi_getApWmmEnable(vap_index, &enabled);
12825 if (ret != RETURN_OK) {
12826 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12827 return RETURN_ERR;
12828 }
12829 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012830
developerc086fb72022-10-04 10:18:22 +080012831 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12832 if (ret != RETURN_OK) {
12833 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012834 return RETURN_ERR;
12835 }
developerc086fb72022-10-04 10:18:22 +080012836 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012837
12838 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012839 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012840 if (ret != RETURN_OK) {
12841 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12842 return RETURN_ERR;
12843 }
12844 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012845
developerc086fb72022-10-04 10:18:22 +080012846 memset(buf, 0, sizeof(buf));
12847 ret = wifi_getBaseBSSID(vap_index, buf);
12848 if (ret != RETURN_OK) {
12849 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12850 return RETURN_ERR;
12851 }
12852 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12853 &map->vap_array[i].u.bss_info.bssid[0],
12854 &map->vap_array[i].u.bss_info.bssid[1],
12855 &map->vap_array[i].u.bss_info.bssid[2],
12856 &map->vap_array[i].u.bss_info.bssid[3],
12857 &map->vap_array[i].u.bss_info.bssid[4],
12858 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012859 // 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]);
12860
12861 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12862 if (ret != RETURN_OK) {
12863 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12864 return RETURN_ERR;
12865 }
12866 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer613892e2023-09-21 16:33:35 +080012867
12868 ret = wifi_getApWpsEnable(vap_index, &enabled);
12869 if (ret != RETURN_OK) {
12870 fprintf(stderr, "%s: wifi_getApWpsEnable\n", __func__);
12871 return RETURN_ERR;
12872 }
12873
12874 map->vap_array[i].u.bss_info.wps.enable = enabled;
12875
developera77d84b2023-02-22 16:10:50 +080012876 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080012877 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012878 }
12879 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12880 return RETURN_OK;
12881}
12882
developer431128d2022-12-16 15:30:41 +080012883
developerd946fd62022-12-08 18:03:28 +080012884static int prepareInterface(UINT apIndex, char *new_interface)
12885{
12886 char cur_interface[16] = {0};
12887 char config_file[128] = {0};
12888 char cmd[128] = {0};
12889 char buf[16] = {0};
12890 int max_radio_num = 0;
12891 int radioIndex = -1;
12892 int phyIndex = -1;
12893
12894 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12895 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12896
12897 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12898 wifi_getMaxRadioNumber(&max_radio_num);
12899 radioIndex = apIndex % max_radio_num;
12900 phyIndex = radio_index_to_phy(radioIndex);
12901 // disable and del old interface, then add new interface
12902 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080012903 if (!(apIndex/max_radio_num)) {
12904 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
12905 _syscmd(cmd, buf, sizeof(buf));
12906 }
developerd946fd62022-12-08 18:03:28 +080012907 }
developer431128d2022-12-16 15:30:41 +080012908 // update the vap status file
12909 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12910 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012911 return RETURN_OK;
12912}
12913
developer06a01d92022-09-07 16:32:39 +080012914INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12915{
developerd946fd62022-12-08 18:03:28 +080012916 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012917 unsigned int i;
12918 wifi_vap_info_t *vap_info = NULL;
12919 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012920 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012921 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012922 char buf[256] = {0};
12923 char cmd[128] = {0};
12924 char config_file[64] = {0};
12925 char bssid[32] = {0};
12926 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012927 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012928
12929 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12930 printf("Entering %s index = %d\n", __func__, (int)index);
12931 for (i = 0; i < map->num_vaps; i++)
12932 {
developer1d57d002022-10-12 18:03:15 +080012933 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012934 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012935
12936 // Check vap status file to enable multiple ap if the system boot.
12937 checkVapStatus(vap_info->vap_index, &enable);
12938 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012939 continue;
developer06a01d92022-09-07 16:32:39 +080012940
developer1d57d002022-10-12 18:03:15 +080012941 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12942
developer431128d2022-12-16 15:30:41 +080012943 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12944 enable = FALSE;
12945
12946 // multi-ap first up need to copy current radio config
12947 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012948 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12949 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012950 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12951 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12952 } else {
12953 // Check whether the interface name is valid or this ap change it.
12954 int apIndex = -1;
12955 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12956 if (apIndex != -1 && apIndex != vap_info->vap_index)
12957 continue;
12958 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012959 }
developer06a01d92022-09-07 16:32:39 +080012960
developer1d57d002022-10-12 18:03:15 +080012961 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012962 params[0].name = "interface";
12963 params[0].value = vap_info->vap_name;
12964 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12965 params[1].name = "bssid";
12966 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012967 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012968 params[2].name = "wpa_psk_file";
12969 params[2].value = psk_file;
12970
12971 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12972 wifi_hostapdWrite(config_file, params, 3);
12973
12974 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12975 _syscmd(cmd, buf, sizeof(buf));
12976
12977 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12978 if (ret != RETURN_OK) {
12979 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12980 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012981 }
developer1d57d002022-10-12 18:03:15 +080012982
12983 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12984 if (ret != RETURN_OK) {
12985 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12986 return RETURN_ERR;
12987 }
12988
12989 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12990 if (ret != RETURN_OK) {
12991 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12992 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012993 }
12994
developer1d57d002022-10-12 18:03:15 +080012995 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12996 if (ret != RETURN_OK) {
12997 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12998 return RETURN_ERR;
12999 }
developer06a01d92022-09-07 16:32:39 +080013000
developer1d57d002022-10-12 18:03:15 +080013001 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
13002 if (ret != RETURN_OK) {
13003 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
13004 return RETURN_ERR;
13005 }
developer06a01d92022-09-07 16:32:39 +080013006
developer1d57d002022-10-12 18:03:15 +080013007 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
13008 if (ret != RETURN_OK) {
13009 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
13010 return RETURN_ERR;
13011 }
13012
developer804c64f2022-10-19 13:54:40 +080013013 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080013014 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080013015 }else {
13016 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080013017 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080013018 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13019 _syscmd(cmd, buf, sizeof(buf));
13020 }else{
developer1d57d002022-10-12 18:03:15 +080013021 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080013022 }
developer1d57d002022-10-12 18:03:15 +080013023 }
13024
13025 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13026 if (ret != RETURN_OK) {
13027 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13028 return RETURN_ERR;
13029 }
13030
13031 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13032 if (ret != RETURN_OK) {
13033 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13034 return RETURN_ERR;
13035 }
13036
13037 memset(buf, 0, sizeof(buf));
13038 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
13039 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
13040 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13041 if (ret != RETURN_OK) {
13042 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13043 return RETURN_ERR;
13044 }
13045
developer1d57d002022-10-12 18:03:15 +080013046 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13047 if (ret != RETURN_OK) {
13048 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13049 return RETURN_ERR;
13050 }
13051
13052 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13053 if (ret != RETURN_OK) {
13054 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13055 return RETURN_ERR;
13056 }
developer06a01d92022-09-07 16:32:39 +080013057
developer894affa2023-05-10 18:13:19 +080013058 ret = wifi_setApWpsEnable(vap_info->vap_index, vap_info->u.bss_info.wps.enable);
13059 if (ret != RETURN_OK) {
13060 fprintf(stderr, "%s: wifi_setApWpsEnable return error\n", __func__);
13061 return RETURN_ERR;
13062 }
13063
developer2f995fb2023-02-24 10:40:44 +080013064 wifi_setApEnable(vap_info->vap_index, FALSE);
developer74ed4192023-09-21 17:15:17 +080013065 if (vap_info->u.bss_info.enabled == TRUE)
13066 wifi_setApEnable(vap_info->vap_index, TRUE);
13067
developer2f995fb2023-02-24 10:40:44 +080013068 multiple_set = FALSE;
13069
13070 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer900e2b72023-05-23 10:23:48 +080013071 if (vap_info->u.bss_info.wps.enable && vap_info->u.bss_info.wps.methods && WIFI_ONBOARDINGMETHODS_PUSHBUTTON) {
developer894affa2023-05-10 18:13:19 +080013072 // The set wps methods function should check whether wps is configured.
13073 ret = wifi_setApWpsButtonPush(vap_info->vap_index);
13074 if (ret != RETURN_OK) {
13075 fprintf(stderr, "%s: wifi_setApWpsButtonPush return error\n", __func__);
13076 return RETURN_ERR;
13077 }
13078 // wifi_setApWpsConfigMethodsEnabled only write to config.
13079 ret = wifi_setApWpsConfigMethodsEnabled(vap_info->vap_index, "PushButton");
13080 if (ret != RETURN_OK) {
13081 fprintf(stderr, "%s: wifi_setApWpsConfigMethodsEnabled return error\n", __func__);
13082 return RETURN_ERR;
13083 }
13084 }
developer2f995fb2023-02-24 10:40:44 +080013085
developer894affa2023-05-10 18:13:19 +080013086 // TODO mgmtPowerControl, interworking
developer06a01d92022-09-07 16:32:39 +080013087 }
developerfb09ba62023-06-09 17:03:21 +080013088
13089 // IGMP Snooping enable should be placed after all hostapd_reload.
13090 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13091 if (ret != RETURN_OK) {
13092 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable return error\n", __func__);
13093 return RETURN_ERR;
13094 }
13095
developer06a01d92022-09-07 16:32:39 +080013096 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13097 return RETURN_OK;
13098}
13099
13100int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13101{
13102 char *token, *next;
13103 const char s[2] = ",";
13104 int count =0;
13105
13106 /* get the first token */
13107 token = strtok_r(pchannels, s, &next);
13108
13109 /* walk through other tokens */
13110 while( token != NULL && count < MAX_CHANNELS) {
13111 chlistptr->channels_list[count++] = atoi(token);
13112 token = strtok_r(NULL, s, &next);
13113 }
13114
13115 return count;
13116}
13117
13118static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13119{
13120 INT status;
13121 wifi_channels_list_t *chlistp;
13122 CHAR output_string[64];
13123 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013124 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013125 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013126
13127 if(rcap == NULL)
13128 {
13129 return RETURN_ERR;
13130 }
13131
13132 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013133 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013134
developer1e5aa162022-09-13 16:06:24 +080013135 if (band == band_2_4)
13136 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13137 else if (band == band_5)
13138 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13139 else if (band == band_6)
13140 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013141
13142 chlistp = &(rcap->channel_list[0]);
13143 memset(pchannels, 0, sizeof(pchannels));
13144
13145 /* possible number of radio channels */
13146 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13147 {
13148 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13149 }
13150 /* Number of channels and list*/
13151 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13152
13153 /* autoChannelSupported */
13154 /* always ON with wifi_getRadioAutoChannelSupported */
13155 rcap->autoChannelSupported = TRUE;
13156
13157 /* DCSSupported */
13158 /* always ON with wifi_getRadioDCSSupported */
13159 rcap->DCSSupported = TRUE;
13160
13161 /* zeroDFSSupported - TBD */
13162 rcap->zeroDFSSupported = FALSE;
13163
13164 /* Supported Country List*/
13165 memset(output_string, 0, sizeof(output_string));
13166 status = wifi_getRadioCountryCode(radioIndex, output_string);
13167 if( status != 0 ) {
13168 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13169 return RETURN_ERR;
13170 } else {
13171 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13172 }
13173 if(!strcmp(output_string,"US")){
13174 rcap->countrySupported[0] = wifi_countrycode_US;
13175 rcap->countrySupported[1] = wifi_countrycode_CA;
13176 } else if (!strcmp(output_string,"CA")) {
13177 rcap->countrySupported[0] = wifi_countrycode_CA;
13178 rcap->countrySupported[1] = wifi_countrycode_US;
13179 } else {
13180 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13181 }
13182
13183 rcap->numcountrySupported = 2;
13184
13185 /* csi */
13186 rcap->csi.maxDevices = 8;
13187 rcap->csi.soudingFrameSupported = TRUE;
13188
developer7930d352022-12-21 17:55:42 +080013189 wifi_GetInterfaceName(radioIndex, interface_name);
13190 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013191
13192 /* channelWidth - all supported bandwidths */
13193 int i=0;
13194 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013195
13196 /* mode - all supported variants */
13197 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13198 wifi_getRadioSupportedStandards(radioIndex, output_string);
13199
developer06a01d92022-09-07 16:32:39 +080013200 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13201 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13202 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013203 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013204
developer7c4cd202023-03-01 10:56:29 +080013205 if (strstr(output_string, "n") != NULL)
13206 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13207 if (strstr(output_string, "ax") != NULL)
13208 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13209 if (strstr(output_string, "be") != NULL)
13210 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13211 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013212 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13213 WIFI_CHANNELBANDWIDTH_40MHZ |
13214 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013215 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013216
developer7c4cd202023-03-01 10:56:29 +080013217 if (strstr(output_string, "n") != NULL)
13218 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13219 if (strstr(output_string, "ac") != NULL)
13220 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13221 if (strstr(output_string, "ax") != NULL)
13222 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13223 if (strstr(output_string, "be") != NULL)
13224 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13225 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13226 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13227 WIFI_CHANNELBANDWIDTH_40MHZ |
13228 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013229 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013230
13231 if (strstr(output_string, "be") != NULL) {
13232 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13233 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13234 }
developer06a01d92022-09-07 16:32:39 +080013235 }
developer7c4cd202023-03-01 10:56:29 +080013236
developer06a01d92022-09-07 16:32:39 +080013237 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13238 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13239
13240 /* supportedBitRate - all supported bitrates */
13241 rcap->supportedBitRate[i] = 0;
13242 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13243 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13244 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13245 }
developer1e5aa162022-09-13 16:06:24 +080013246 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013247 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13248 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13249 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13250 }
13251
13252
13253 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13254 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13255 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13256 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13257 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13258 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13259 rcap->cipherSupported = 0;
13260 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13261 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13262
13263 return RETURN_OK;
13264}
13265
13266INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13267{
developer30423732022-12-01 16:17:49 +080013268 INT status = 0, radioIndex = 0;
13269 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013270 int iter = 0;
developer30423732022-12-01 16:17:49 +080013271 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013272 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013273 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013274
13275 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13276
13277 memset(cap, 0, sizeof(wifi_hal_capability_t));
13278
13279 /* version */
13280 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13281 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13282
13283 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013284 wifi_getMaxRadioNumber(&max_num_radios);
13285 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013286
13287 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13288 {
13289 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13290 if (status != 0) {
13291 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13292 return RETURN_ERR;
13293 }
13294
13295 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13296 {
developer804c64f2022-10-19 13:54:40 +080013297 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013298 {
13299 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13300 return RETURN_ERR;
13301 }
13302 iface_info = &cap->wifi_prop.interface_map[iter];
13303 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13304 iface_info->rdk_radio_index = radioIndex;
13305 memset(output, 0, sizeof(output));
13306 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13307 {
13308 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13309 }
13310 // TODO: bridge name
13311 // TODO: vlan id
13312 // TODO: primary
13313 iface_info->index = array_index_to_vap_index(radioIndex, j);
13314 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013315 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013316 {
13317 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13318 }
13319 iter++;
13320 }
13321 }
13322
13323 cap->BandSteeringSupported = FALSE;
13324 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13325 return RETURN_OK;
13326}
13327
developer9df4e652022-10-11 11:27:38 +080013328INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13329{
13330 struct params h_config={0};
13331 char config_file[64] = {0};
13332
13333 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13334
13335 h_config.name = "okc";
13336 h_config.value = okc_enable?"1":"0";
13337
13338 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13339 wifi_hostapdWrite(config_file, &h_config, 1);
13340 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13341
13342 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13343 return RETURN_OK;
13344}
13345
13346INT wifi_setSAEMFP(int ap_index, BOOL enable)
13347{
13348 struct params h_config={0};
13349 char config_file[64] = {0};
13350 char buf[128] = {0};
13351
13352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13353
13354 h_config.name = "sae_require_mfp";
13355 h_config.value = enable?"1":"0";
13356
13357 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13358 wifi_hostapdWrite(config_file, &h_config, 1);
13359 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13360
13361 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13362 return RETURN_OK;
13363}
13364
13365INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13366{
13367 struct params h_config={0};
13368 char config_file[64] = {0};
13369 char buf[128] = {0};
13370
13371 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13372
13373 h_config.name = "sae_pwe";
13374 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13375 h_config.value = buf;
13376
13377 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13378 wifi_hostapdWrite(config_file, &h_config, 1);
13379 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13380
13381 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13382 return RETURN_OK;
13383}
13384
13385INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13386{
13387 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13388 struct params h_config={0};
13389 char config_file[64] = {0};
13390
13391 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13392
13393 h_config.name = "wpa_disable_eapol_key_retries";
13394 h_config.value = disable_EAPOL_retries?"1":"0";
13395
13396 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13397 wifi_hostapdWrite(config_file, &h_config, 1);
13398 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13399
13400 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13401 return RETURN_OK;
13402}
13403
developer06a01d92022-09-07 16:32:39 +080013404INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13405{
developer587c1b62022-09-27 15:58:59 +080013406 char buf[128] = {0};
13407 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013408 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013409 char password[64] = {0};
13410 char mfp[32] = {0};
13411 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013412 BOOL okc_enable = FALSE;
13413 BOOL sae_MFP = FALSE;
13414 BOOL disable_EAPOL_retries = TRUE;
13415 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013416 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013417 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013418
13419 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13420
13421 multiple_set = TRUE;
13422 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13423 if (security->mode == wifi_security_mode_none) {
13424 strcpy(wpa_mode, "None");
13425 } else if (security->mode == wifi_security_mode_wpa_personal)
13426 strcpy(wpa_mode, "WPA-Personal");
13427 else if (security->mode == wifi_security_mode_wpa2_personal)
13428 strcpy(wpa_mode, "WPA2-Personal");
13429 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13430 strcpy(wpa_mode, "WPA-WPA2-Personal");
13431 else if (security->mode == wifi_security_mode_wpa_enterprise)
13432 strcpy(wpa_mode, "WPA-Enterprise");
13433 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13434 strcpy(wpa_mode, "WPA2-Enterprise");
13435 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13436 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013437 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013438 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013439 okc_enable = TRUE;
13440 sae_MFP = TRUE;
13441 sae_pwe = 2;
13442 disable_EAPOL_retries = FALSE;
13443 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013444 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013445 okc_enable = TRUE;
13446 sae_MFP = TRUE;
13447 sae_pwe = 2;
13448 disable_EAPOL_retries = FALSE;
13449 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013450 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013451 sae_MFP = TRUE;
13452 sae_pwe = 2;
13453 disable_EAPOL_retries = FALSE;
developerae432c62023-04-24 11:07:20 +080013454 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer5c9fee82023-01-13 14:44:16 +080013455 strcpy(wpa_mode, "OWE");
13456 sae_MFP = TRUE;
13457 sae_pwe = 2;
13458 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013459 }
13460
13461 band = wifi_index_to_band(ap_index);
13462 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13463 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13464 return RETURN_ERR;
13465 }
developer587c1b62022-09-27 15:58:59 +080013466
13467 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013468 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013469 wifi_setSAEMFP(ap_index, sae_MFP);
13470 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013471 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013472
developerae432c62023-04-24 11:07:20 +080013473 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer4b102122023-02-15 10:53:03 +080013474 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) {
13475 int key_len = strlen(security->u.key.key);
13476 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13477 if (key_len == 64) { // set wpa_psk
13478 strncpy(password, security->u.key.key, 64); // 64 characters
13479 password[64] = '\0';
13480 wifi_setApSecurityPreSharedKey(ap_index, password);
13481 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13482 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13483 strncpy(password, security->u.key.key, 63);
13484 password[63] = '\0';
13485 wifi_setApSecurityKeyPassphrase(ap_index, password);
13486 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13487 } else
13488 return RETURN_ERR;
13489 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013490 }
13491 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13492 params.name = "sae_password";
13493 params.value = security->u.key.key;
13494 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013495 } else { // remove sae_password
13496 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13497 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013498 }
13499 }
developer587c1b62022-09-27 15:58:59 +080013500
13501 if (security->mode != wifi_security_mode_none) {
13502 memset(&params, 0, sizeof(params));
13503 params.name = "wpa_pairwise";
13504 if (security->encr == wifi_encryption_tkip)
13505 params.value = "TKIP";
13506 else if (security->encr == wifi_encryption_aes)
13507 params.value = "CCMP";
13508 else if (security->encr == wifi_encryption_aes_tkip)
13509 params.value = "TKIP CCMP";
13510 wifi_hostapdWrite(config_file, &params, 1);
13511 }
13512
13513 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013514 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013515 else if (security->mfp == wifi_mfp_cfg_optional)
13516 strcpy(mfp, "Optional");
13517 else if (security->mfp == wifi_mfp_cfg_required)
13518 strcpy(mfp, "Required");
13519 wifi_setApSecurityMFPConfig(ap_index, mfp);
13520
13521 memset(&params, 0, sizeof(params));
13522 params.name = "transition_disable";
13523 if (security->wpa3_transition_disable == TRUE)
13524 params.value = "0x01";
13525 else
13526 params.value = "0x00";
13527 wifi_hostapdWrite(config_file, &params, 1);
13528
13529 memset(&params, 0, sizeof(params));
13530 params.name = "wpa_group_rekey";
13531 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13532 params.value = buf;
13533 wifi_hostapdWrite(config_file, &params, 1);
13534
13535 memset(&params, 0, sizeof(params));
13536 params.name = "wpa_strict_rekey";
13537 params.value = security->strict_rekey?"1":"0";
13538 wifi_hostapdWrite(config_file, &params, 1);
13539
13540 memset(&params, 0, sizeof(params));
13541 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013542 if (security->eapol_key_retries == 0)
13543 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013544 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13545 params.value = buf;
13546 wifi_hostapdWrite(config_file, &params, 1);
13547
13548 memset(&params, 0, sizeof(params));
13549 params.name = "disable_pmksa_caching";
13550 params.value = security->disable_pmksa_caching?"1":"0";
13551 wifi_hostapdWrite(config_file, &params, 1);
13552
developer23e71282023-01-18 10:25:19 +080013553 if (multiple_set == FALSE) {
13554 wifi_setApEnable(ap_index, FALSE);
13555 wifi_setApEnable(ap_index, TRUE);
13556 }
developer587c1b62022-09-27 15:58:59 +080013557
13558 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13559
developer06a01d92022-09-07 16:32:39 +080013560 return RETURN_OK;
13561}
13562
13563INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13564{
developer9df4e652022-10-11 11:27:38 +080013565 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013566 char config_file[128] = {0};
13567 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013568 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013569
13570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13571 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13572 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13573 security->mode = wifi_security_mode_none;
13574 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013575 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013576 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013577 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013578 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013579 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013580 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013581 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013582 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013583 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013584 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013585 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013586 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013587 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013588 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013589 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013590 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013591 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013592 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013593 else if (!strcmp(buf, "OWE"))
developerae432c62023-04-24 11:07:20 +080013594 security->mode = wifi_security_mode_enhanced_open;
developer587c1b62022-09-27 15:58:59 +080013595 }
13596
13597 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13598 if (security->mode == wifi_security_mode_none)
13599 security->encr = wifi_encryption_none;
13600 else {
13601 if (strcmp(buf, "TKIP") == 0)
13602 security->encr = wifi_encryption_tkip;
13603 else if (strcmp(buf, "CCMP") == 0)
13604 security->encr = wifi_encryption_aes;
13605 else
13606 security->encr = wifi_encryption_aes_tkip;
13607 }
13608
developer9df4e652022-10-11 11:27:38 +080013609 if (security->mode != wifi_encryption_none) {
13610 memset(buf, 0, sizeof(buf));
13611 // wpa3 can use one or both configs as password, so we check sae_password first.
13612 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013613 if (strlen(buf) != 0) {
13614 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13615 security->u.key.type = wifi_security_key_type_sae;
13616 set_sae = TRUE;
13617 strncpy(security->u.key.key, buf, sizeof(buf));
13618 }
13619 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13620 if (strlen(buf) != 0){
13621 if (set_sae == TRUE)
13622 security->u.key.type = wifi_security_key_type_psk_sae;
13623 else if (strlen(buf) == 64)
13624 security->u.key.type = wifi_security_key_type_psk;
13625 else
13626 security->u.key.type = wifi_security_key_type_pass;
13627 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013628 }
developer9df4e652022-10-11 11:27:38 +080013629 security->u.key.key[255] = '\0';
13630 }
13631
developer587c1b62022-09-27 15:58:59 +080013632 memset(buf, 0, sizeof(buf));
13633 wifi_getApSecurityMFPConfig(ap_index, buf);
13634 if (strcmp(buf, "Disabled") == 0)
13635 security->mfp = wifi_mfp_cfg_disabled;
13636 else if (strcmp(buf, "Optional") == 0)
13637 security->mfp = wifi_mfp_cfg_optional;
13638 else if (strcmp(buf, "Required") == 0)
13639 security->mfp = wifi_mfp_cfg_required;
13640
13641 memset(buf, 0, sizeof(buf));
13642 security->wpa3_transition_disable = FALSE;
13643 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13644 disable = strtol(buf, NULL, 16);
13645 if (disable != 0)
13646 security->wpa3_transition_disable = TRUE;
13647
13648 memset(buf, 0, sizeof(buf));
13649 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13650 if (strlen(buf) == 0)
13651 security->rekey_interval = 86400;
13652 else
13653 security->rekey_interval = strtol(buf, NULL, 10);
13654
13655 memset(buf, 0, sizeof(buf));
13656 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13657 if (strlen(buf) == 0)
developer894d8222023-06-15 13:40:44 +080013658 security->strict_rekey = 0;
developer587c1b62022-09-27 15:58:59 +080013659 else
13660 security->strict_rekey = strtol(buf, NULL, 10);
13661
13662 memset(buf, 0, sizeof(buf));
13663 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13664 if (strlen(buf) == 0)
13665 security->eapol_key_retries = 4;
13666 else
13667 security->eapol_key_retries = strtol(buf, NULL, 10);
13668
13669 memset(buf, 0, sizeof(buf));
13670 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13671 if (strlen(buf) == 0)
13672 security->disable_pmksa_caching = FALSE;
13673 else
13674 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13675
13676 /* TODO
13677 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13678 */
13679 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13680 security->eap_identity_req_timeout = 0;
13681 security->eap_identity_req_retries = 0;
13682 security->eap_req_timeout = 0;
13683 security->eap_req_retries = 0;
13684 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013685 return RETURN_OK;
13686}
13687
13688#endif /* WIFI_HAL_VERSION_3 */
13689
13690#ifdef WIFI_HAL_VERSION_3_PHASE2
13691INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13692{
developerd946fd62022-12-08 18:03:28 +080013693 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013694 char cmd[128] = {0};
13695 char buf[128] = {0};
13696 char *mac_addr = NULL;
13697 BOOL status = FALSE;
13698 size_t len = 0;
13699
13700 if(ap_index > MAX_APS)
13701 return RETURN_ERR;
13702
13703 *output_numDevices = 0;
13704 wifi_getApEnable(ap_index, &status);
13705 if (status == FALSE)
13706 return RETURN_OK;
13707
developerac6f1142022-12-20 19:26:35 +080013708 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013709 return RETURN_ERR;
13710 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013711 _syscmd(cmd, buf, sizeof(buf));
13712
13713 mac_addr = strtok(buf, "\n");
13714 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13715 *output_numDevices = i + 1;
13716 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13717 addr_ptr = output_deviceMacAddressArray[i];
13718 mac_addr_aton(addr_ptr, mac_addr);
13719 mac_addr = strtok(NULL, "\n");
13720 }
13721
13722 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013723}
13724#else
13725INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13726{
developerd946fd62022-12-08 18:03:28 +080013727 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013728 char cmd[128];
13729 BOOL status = false;
13730
13731 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13732 return RETURN_ERR;
13733
13734 output_buf[0] = '\0';
13735
13736 wifi_getApEnable(ap_index,&status);
13737 if (!status)
13738 return RETURN_OK;
13739
developerac6f1142022-12-20 19:26:35 +080013740 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013741 return RETURN_ERR;
13742 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013743 _syscmd(cmd, output_buf, output_buf_size);
13744
13745 return RETURN_OK;
13746}
13747#endif
developer2f513ab2022-09-13 14:26:06 +080013748
13749INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13750{
13751 char output[16]={'\0'};
13752 char config_file[MAX_BUF_SIZE] = {0};
13753
13754 if (!enable)
13755 return RETURN_ERR;
13756
13757 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13758 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13759
13760 if (strlen(output) == 0)
13761 *enable = FALSE;
13762 else if (strncmp(output, "1", 1) == 0)
13763 *enable = TRUE;
13764 else
13765 *enable = FALSE;
13766
13767 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13768 return RETURN_OK;
13769}
developer2d9c30f2022-09-13 15:06:14 +080013770
13771INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13772{
developer804c64f2022-10-19 13:54:40 +080013773 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013774 return RETURN_ERR;
13775 *output_enable=TRUE;
13776 return RETURN_OK;
13777}
developerfd7d2892022-09-13 16:44:53 +080013778
13779INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13780{
13781 char cmd[128] = {0};
13782 char buf[128] = {0};
13783 char line[128] = {0};
13784 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013785 FILE *f = NULL;
13786 int index = 0;
13787 int exp = 0;
13788 int mantissa = 0;
13789 int duration = 0;
13790 int radio_index = 0;
13791 int max_radio_num = 0;
13792 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013793 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013794 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13795
13796 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013797
developerfd7d2892022-09-13 16:44:53 +080013798 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013799
13800 phyId = radio_index_to_phy(radio_index);
13801 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013802 _syscmd(cmd, buf, sizeof(buf));
13803 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13804 if (*numSessionReturned > maxNumberSessions)
13805 *numSessionReturned = maxNumberSessions;
13806 else if (*numSessionReturned < 1) {
13807 *numSessionReturned = 0;
13808 return RETURN_OK;
13809 }
13810
developer033b37b2022-10-18 11:27:46 +080013811 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
developerfd7d2892022-09-13 16:44:53 +080013812 if ((f = popen(cmd, "r")) == NULL) {
13813 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13814 return RETURN_ERR;
13815 }
13816
13817 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013818 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013819 char *tmp = NULL;
13820 strcpy(buf, line);
13821 tmp = strtok(buf, " ");
13822 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13823 tmp = strtok(NULL, " ");
13824 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13825 tmp = strtok(NULL, " ");
13826 if (strstr(tmp, "t")) {
13827 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13828 }
13829 if (strstr(tmp, "a")) {
13830 twtSessions[index].twtParameters.operation.announced = TRUE;
13831 }
13832 tmp = strtok(NULL, " ");
13833 exp = strtol(tmp, NULL, 10);
13834 tmp = strtok(NULL, " ");
13835 mantissa = strtol(tmp, NULL, 10);
13836 tmp = strtok(NULL, " ");
13837 duration = strtol(tmp, NULL, 10);
13838
13839 // only implicit supported
13840 twtSessions[index].twtParameters.operation.implicit = TRUE;
13841 // only individual agreement supported
13842 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13843
13844 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13845 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013846 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013847 // Overflow handling
13848 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13849 } else {
13850 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13851 }
13852 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13853 index++;
13854 }
13855
13856 pclose(f);
13857 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13858 return RETURN_OK;
13859}