blob: f407a0ca6f1dc3fda7c07547520ca4af4e2fdbce [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 {
1332 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1333 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
developerd946fd62022-12-08 18:03:28 +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);
2916 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
2917 }
2918 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);
developerfa41b1f2023-01-06 10:25:51 +08002986 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
developer06a01d92022-09-07 16:32:39 +08002987 }
2988
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;
3140 snprintf(output_list, 64,"0,25,50,75,100");
3141 return RETURN_OK;
3142}
3143
developera5005b62022-09-13 15:43:35 +08003144//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08003145//The transmite power level is in units of full power for this radio.
3146INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3147{
developerd946fd62022-12-08 18:03:28 +08003148 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003149 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003150 char buf[16]={0};
3151 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003152
developera5005b62022-09-13 15:43:35 +08003153 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08003154 return RETURN_ERR;
3155
developerac6f1142022-12-20 19:26:35 +08003156 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003157 return RETURN_ERR;
3158 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08003159 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003160
developera5005b62022-09-13 15:43:35 +08003161 *output_ulong = strtol(buf, NULL, 10);
3162
3163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003164 return RETURN_OK;
3165}
3166
3167//Set Transmit Power
3168//The transmite power level is in units of full power for this radio.
3169INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3170{
developerd946fd62022-12-08 18:03:28 +08003171 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003172 char *support;
developer06a01d92022-09-07 16:32:39 +08003173 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003174 char buf[128]={0};
3175 char txpower_str[64] = {0};
3176 int txpower = 0;
3177 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08003178 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003179
3180 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003181
developerac6f1142022-12-20 19:26:35 +08003182 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003183 return RETURN_ERR;
3184 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08003185 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08003186 maximum_tx = strtol(buf, NULL, 10);
3187
3188 // Get the Tx power supported list and check that is the input in the list
3189 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3190 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3191 support = strtok(buf, ",");
3192 while(true)
3193 {
3194 if(support == NULL) { // input not in the list
3195 wifi_dbg_printf("Input value is invalid.\n");
3196 return RETURN_ERR;
3197 }
3198 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3199 break;
3200 }
3201 support = strtok(NULL, ",");
3202 }
3203 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003204 phyId = radio_index_to_phy(radioIndex);
3205 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003206 _syscmd(cmd, buf, sizeof(buf));
3207 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003208
3209 return RETURN_OK;
3210}
3211
3212//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3213INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3214{
3215 if (NULL == Supported)
3216 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003217 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003218
3219 return RETURN_OK;
3220}
3221
3222//Get 80211h feature enable
3223INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3224{
developer3885fec2022-09-13 15:13:47 +08003225 char buf[64]={'\0'};
3226 char config_file[64] = {'\0'};
3227
3228 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3229 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003230 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003231
3232 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3233 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003234
developer3885fec2022-09-13 15:13:47 +08003235 if (strncmp(buf, "1", 1) == 0)
3236 *enable = TRUE;
3237 else
3238 *enable = FALSE;
3239
3240 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003241 return RETURN_OK;
3242}
3243
3244//Set 80211h feature enable
3245INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3246{
developer3885fec2022-09-13 15:13:47 +08003247 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3248 struct params params={'\0'};
3249 char config_file[MAX_BUF_SIZE] = {0};
3250
3251 params.name = "ieee80211h";
3252
3253 if (enable) {
3254 params.value = "1";
3255 } else {
3256 params.value = "0";
3257 }
3258
3259 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3260 wifi_hostapdWrite(config_file, &params, 1);
3261
3262 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3263 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3264 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003265}
3266
3267//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.
3268INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3269{
3270 if (NULL == output)
3271 return RETURN_ERR;
3272 *output=100;
3273
3274 return RETURN_OK;
3275}
3276
3277//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.
3278INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3279{
3280 if (NULL == output)
3281 return RETURN_ERR;
3282 *output = -99;
3283
3284 return RETURN_OK;
3285}
3286
3287INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3288{
3289 return RETURN_ERR;
3290}
3291
3292
3293//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3294INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3295{
developerd946fd62022-12-08 18:03:28 +08003296 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003297 char cmd[MAX_BUF_SIZE]={'\0'};
3298 char buf[MAX_CMD_SIZE]={'\0'};
3299
3300 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3301 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003302 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003303
developerac6f1142022-12-20 19:26:35 +08003304 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003305 return RETURN_ERR;
3306 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 +08003307 _syscmd(cmd, buf, sizeof(buf));
3308 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003309
developer5f222492022-09-13 15:21:52 +08003310 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003311 return RETURN_OK;
3312}
3313
3314INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3315{
developer5f222492022-09-13 15:21:52 +08003316 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3317 struct params params={'\0'};
3318 char buf[MAX_BUF_SIZE] = {'\0'};
3319 char config_file[MAX_BUF_SIZE] = {'\0'};
3320
developer5b398df2022-11-17 20:39:48 +08003321 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3322 return RETURN_ERR;
3323
developer5f222492022-09-13 15:21:52 +08003324 params.name = "beacon_int";
3325 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3326 params.value = buf;
3327
3328 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3329 wifi_hostapdWrite(config_file, &params, 1);
3330
3331 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3332 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3333 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003334}
3335
3336//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.
3337INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3338{
developer06a01d92022-09-07 16:32:39 +08003339 //TODO: need to revisit below implementation
3340 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003341 char temp_output[128] = {0};
3342 char temp_TransmitRates[64] = {0};
3343 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003344
3345 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3346 if (NULL == output)
3347 return RETURN_ERR;
3348 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003349 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3350
3351 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3352 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3353 } else {
3354 temp = strtok(temp_TransmitRates," ");
3355 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003356 {
developere9d0abd2022-09-13 15:40:57 +08003357 // Convert 100 kbps to Mbps
3358 temp[strlen(temp)-1]=0;
3359 if((temp[0]=='5') && (temp[1]=='\0'))
3360 {
3361 temp="5.5";
3362 }
3363 strcat(temp_output,temp);
3364 temp = strtok(NULL," ");
3365 if(temp!=NULL)
3366 {
3367 strcat(temp_output,",");
3368 }
developer06a01d92022-09-07 16:32:39 +08003369 }
developere9d0abd2022-09-13 15:40:57 +08003370 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003371 }
developer06a01d92022-09-07 16:32:39 +08003372 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003373 return RETURN_OK;
3374}
3375
3376INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3377{
3378 char *temp;
3379 char temp1[128];
3380 char temp_output[128];
3381 char temp_TransmitRates[128];
3382 char set[128];
3383 char sub_set[128];
3384 int set_count=0,subset_count=0;
3385 int set_index=0,subset_index=0;
3386 char *token;
3387 int flag=0, i=0;
3388 struct params params={'\0'};
3389 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003390 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003391
3392 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3393 if(NULL == TransmitRates)
3394 return RETURN_ERR;
3395 strcpy(sub_set,TransmitRates);
3396
3397 //Allow only supported Data transmit rate to be set
3398 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3399 token = strtok(sub_set,",");
3400 while( token != NULL ) /* split the basic rate to be set, by comma */
3401 {
3402 sub_set[subset_count]=atoi(token);
3403 subset_count++;
3404 token=strtok(NULL,",");
3405 }
3406 token=strtok(set,",");
3407 while(token!=NULL) /* split the supported rate by comma */
3408 {
3409 set[set_count]=atoi(token);
3410 set_count++;
3411 token=strtok(NULL,",");
3412 }
3413 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3414 {
3415 for(set_index=0;set_index < set_count;set_index++)
3416 {
3417 flag=0;
3418 if(sub_set[subset_index]==set[set_index])
3419 break;
3420 else
3421 flag=1; /* No match found */
3422 }
3423 if(flag==1)
3424 return RETURN_ERR; //If value not found return Error
3425 }
3426 strcpy(temp_TransmitRates,TransmitRates);
3427
3428 for(i=0;i<strlen(temp_TransmitRates);i++)
3429 {
3430 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003431 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003432 {
3433 continue;
3434 }
3435 else
3436 {
3437 return RETURN_ERR;
3438 }
3439 }
3440 strcpy(temp_output,"");
3441 temp = strtok(temp_TransmitRates,",");
3442 while(temp!=NULL)
3443 {
3444 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003445 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003446 {
developeref938762022-10-19 17:21:01 +08003447 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003448 {
3449 return RETURN_ERR;
3450 }
3451 }
3452
3453 if(strcmp(temp,"5.5")==0)
3454 {
3455 strcpy(temp1,"55");
3456 }
3457 else
3458 {
3459 strcat(temp1,"0");
3460 }
3461 strcat(temp_output,temp1);
3462 temp = strtok(NULL,",");
3463 if(temp!=NULL)
3464 {
3465 strcat(temp_output," ");
3466 }
3467 }
3468 strcpy(TransmitRates,temp_output);
3469
3470 params.name= "basic_rates";
3471 params.value =TransmitRates;
3472
3473 wifi_dbg_printf("\n%s:",__func__);
3474 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3475 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3476 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3477 wifi_hostapdWrite(config_file,&params,1);
3478 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3479 return RETURN_OK;
3480}
3481
3482//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
developerac6f1142022-12-20 19:26:35 +08003483INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
developer06a01d92022-09-07 16:32:39 +08003484{
3485 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3486 FILE *fp = NULL;
3487 char path[256] = {0}, output_string[256] = {0};
3488 int count = 0;
3489 char *interface = NULL;
3490
3491 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3492 if (fp == NULL)
3493 {
3494 printf("Failed to run command in Function %s\n", __FUNCTION__);
3495 return RETURN_ERR;
3496 }
3497 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3498 {
3499 interface = strchr(path, '=');
3500
3501 if (interface != NULL)
3502 {
3503 strcpy(output_string, interface + 1);
developer72ec5572023-01-05 16:27:13 +08003504 for (count = 0; output_string[count] != '\n' && output_string[count] != '\0'; count++)
developer06a01d92022-09-07 16:32:39 +08003505 interface_name[count] = output_string[count];
3506
3507 interface_name[count] = '\0';
3508 }
3509 }
3510 pclose(fp);
3511 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3512 return RETURN_OK;
3513}
3514
3515INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3516{
3517 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3518 output_struct->radio_BytesSent = 0;
3519 output_struct->radio_BytesReceived = 0;
3520 output_struct->radio_PacketsSent = 0;
3521 output_struct->radio_PacketsReceived = 0;
3522 output_struct->radio_ErrorsSent = 0;
3523 output_struct->radio_ErrorsReceived = 0;
3524 output_struct->radio_DiscardPacketsSent = 0;
3525 output_struct->radio_DiscardPacketsReceived = 0;
3526 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3527 return RETURN_OK;
3528}
3529
3530
3531INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3532{
3533 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3534 CHAR buf[MAX_CMD_SIZE] = {0};
3535 CHAR Value[MAX_BUF_SIZE] = {0};
3536 FILE *fp = NULL;
3537
3538 if (ifname == NULL || strlen(ifname) <= 1)
3539 return RETURN_OK;
3540
3541 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3542 system(buf);
3543
3544 fp = fopen("/tmp/Radio_Stats.txt", "r");
3545 if(fp == NULL)
3546 {
3547 printf("/tmp/Radio_Stats.txt not exists \n");
3548 return RETURN_ERR;
3549 }
3550 fclose(fp);
3551
3552 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3553 File_Reading(buf, Value);
3554 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3555
3556 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3557 File_Reading(buf, Value);
3558 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3559
3560 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3561 File_Reading(buf, Value);
3562 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3563
3564 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3565 File_Reading(buf, Value);
3566 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3567
3568 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3569 File_Reading(buf, Value);
3570 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3571
3572 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3573 File_Reading(buf, Value);
3574 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3575
3576 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3577 File_Reading(buf, Value);
3578 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3579
3580 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3581 File_Reading(buf, Value);
3582 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3583
3584 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3585 return RETURN_OK;
3586}
3587
3588INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3589{
3590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3591 CHAR buf[MAX_CMD_SIZE] = {0};
3592 FILE *fp = NULL;
3593 INT count = 0;
3594
3595 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3596 {
3597 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3598 File_Reading(buf, status);
3599 }
3600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3601 return RETURN_OK;
3602}
3603
3604//Get detail radio traffic static info
3605INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3606{
3607
3608#if 0
3609 //ifconfig radio_x
3610 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3611 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3612 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3613 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3614
3615 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3616 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3617 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.
3618 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.
3619
3620 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3621 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].
3622 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3623 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.
3624 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
3625 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
3626 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
3627 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
3628 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
3629
3630 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
3631 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
3632 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
3633 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.
3634
3635 return RETURN_OK;
3636#endif
3637
developera91d99f2022-09-29 15:59:10 +08003638 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003639 BOOL iface_status = FALSE;
3640 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003641
3642 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3643 if (NULL == output_struct)
3644 return RETURN_ERR;
3645
developerac6f1142022-12-20 19:26:35 +08003646 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08003647 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003648
developera91d99f2022-09-29 15:59:10 +08003649 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003650
developera91d99f2022-09-29 15:59:10 +08003651 if (iface_status == TRUE)
3652 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3653 else
3654 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003655
developera91d99f2022-09-29 15:59:10 +08003656 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3657 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3658 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3659 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3660 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3661 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3662 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3663 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003664
3665 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3666 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].
3667 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3668 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.
3669 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
3670 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
3671 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
3672 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
3673 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
3674
3675 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
3676 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
3677 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
3678 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.
3679
3680 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3681
3682 return RETURN_OK;
3683}
3684
3685//Set radio traffic static Measureing rules
3686INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3687{
3688 //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
3689 // Else, save the MeasuringRate and MeasuringInterval for future usage
3690
3691 return RETURN_OK;
3692}
3693
3694//To start or stop RadioTrafficStats
3695INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3696{
3697 //zqiu: If the RadioTrafficStats process running
3698 // if(enable)
3699 // return RETURN_OK.
3700 // else
3701 // Stop RadioTrafficStats process
3702 // Else
3703 // if(enable)
3704 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3705 // else
3706 // return RETURN_OK.
3707
3708 return RETURN_OK;
3709}
3710
3711//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
3712INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3713{
3714 //zqiu: Please ignor signalIndex.
3715 if (NULL == SignalLevel)
3716 return RETURN_ERR;
3717 *SignalLevel=(radioIndex==0)?-19:-19;
3718
3719 return RETURN_OK;
3720}
3721
3722//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3723INT wifi_applyRadioSettings(INT radioIndex)
3724{
3725 return RETURN_OK;
3726}
3727
3728//Get the radio index assocated with this SSID entry
3729INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3730{
developer5b398df2022-11-17 20:39:48 +08003731 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003732 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003733 int max_radio_num = 0;
3734 wifi_getMaxRadioNumber(&max_radio_num);
3735 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003736 return RETURN_OK;
3737}
3738
3739//Device.WiFi.SSID.{i}.Enable
3740//Get SSID enable configuration parameters (not the SSID enable status)
3741INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3742{
3743 if (NULL == output_bool)
3744 return RETURN_ERR;
3745
developer06a01d92022-09-07 16:32:39 +08003746 return wifi_getApEnable(ssidIndex, output_bool);
3747}
3748
3749//Device.WiFi.SSID.{i}.Enable
3750//Set SSID enable configuration parameters
3751INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3752{
developer06a01d92022-09-07 16:32:39 +08003753 return wifi_setApEnable(ssidIndex, enable);
3754}
3755
3756//Device.WiFi.SSID.{i}.Status
3757//Get the SSID enable status
3758INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3759{
3760 char cmd[MAX_CMD_SIZE]={0};
3761 char buf[MAX_BUF_SIZE]={0};
3762 BOOL output_bool;
3763
3764 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3765 if (NULL == output_string)
3766 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003767
developer06a01d92022-09-07 16:32:39 +08003768 wifi_getApEnable(ssidIndex,&output_bool);
3769 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3770
3771 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3772 return RETURN_OK;
3773}
3774
3775// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3776INT wifi_getSSIDName(INT apIndex, CHAR *output)
3777{
3778 char config_file[MAX_BUF_SIZE] = {0};
3779
3780 if (NULL == output)
3781 return RETURN_ERR;
3782
3783 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3784 wifi_hostapdRead(config_file,"ssid",output,32);
3785
3786 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3787 return RETURN_OK;
3788}
3789
3790// Set a max 32 byte string and sets an internal variable to the SSID name
3791INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3792{
3793 char str[MAX_BUF_SIZE]={'\0'};
3794 char cmd[MAX_CMD_SIZE]={'\0'};
3795 struct params params;
3796 char config_file[MAX_BUF_SIZE] = {0};
3797
3798 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer89df4502023-02-16 20:45:02 +08003799 if(NULL == ssid_string || strlen(ssid_string) > 32 || strlen(ssid_string) == 0 )
developer06a01d92022-09-07 16:32:39 +08003800 return RETURN_ERR;
3801
3802 params.name = "ssid";
3803 params.value = ssid_string;
3804 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3805 wifi_hostapdWrite(config_file, &params, 1);
3806 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3807 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3808
3809 return RETURN_OK;
3810}
3811
3812//Get the BSSID
3813INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3814{
3815 char cmd[MAX_CMD_SIZE]="";
3816
3817 if (NULL == output_string)
3818 return RETURN_ERR;
3819
3820 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3821 {
developer1d57d002022-10-12 18:03:15 +08003822 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 +08003823 _syscmd(cmd, output_string, 64);
3824 return RETURN_OK;
3825 }
3826 strncpy(output_string, "\0", 1);
3827
3828 return RETURN_ERR;
3829}
3830
3831//Get the MAC address associated with this Wifi SSID
3832INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3833{
3834 wifi_getBaseBSSID(ssidIndex,output_string);
3835 return RETURN_OK;
3836}
3837
3838//Get the basic SSID traffic static info
3839//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3840//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3841INT wifi_applySSIDSettings(INT ssidIndex)
3842{
developerd946fd62022-12-08 18:03:28 +08003843 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003844 BOOL status = false;
3845 char cmd[MAX_CMD_SIZE] = {0};
3846 char buf[MAX_CMD_SIZE] = {0};
3847 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003848 int max_radio_num = 0;
3849 int radioIndex = 0;
3850
3851 wifi_getMaxRadioNumber(&max_radio_num);
3852
3853 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003854
3855 wifi_getApEnable(ssidIndex,&status);
3856 // Do not apply when ssid index is disabled
3857 if (status == false)
3858 return RETURN_OK;
3859
3860 /* Doing full remove and add for ssid Index
3861 * Not all hostapd options are supported with reload
3862 * for example macaddr_acl
3863 */
3864 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3865 return RETURN_ERR;
3866
3867 ret = wifi_setApEnable(ssidIndex,true);
3868
3869 /* Workaround for hostapd issue with multiple bss definitions
3870 * when first created interface will be removed
3871 * then all vaps other vaps on same phy are removed
3872 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003873 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003874 apIndex = max_radio_num*i+radioIndex;
developerac6f1142022-12-20 19:26:35 +08003875 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08003876 continue;
developerd946fd62022-12-08 18:03:28 +08003877 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003878 _syscmd(cmd, buf, sizeof(buf));
3879 if(*buf == '1')
3880 wifi_setApEnable(apIndex, true);
3881 }
3882
3883 return ret;
3884}
3885
developera3c68b92022-09-13 15:27:29 +08003886struct channels_noise {
3887 int channel;
3888 int noise;
3889};
3890
3891// Return noise array for each channel
3892int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3893{
developerd946fd62022-12-08 18:03:28 +08003894 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003895 FILE *f = NULL;
3896 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003897 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003898 size_t len = 0;
3899 ssize_t read = 0;
3900 int tmp = 0, arr_index = -1;
3901
developerac6f1142022-12-20 19:26:35 +08003902 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003903 return RETURN_ERR;
3904 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003905
3906 if ((f = popen(cmd, "r")) == NULL) {
3907 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3908 return RETURN_ERR;
3909 }
developer5550e242022-09-30 09:59:32 +08003910
3911 while(fgets(line, sizeof(line), f) != NULL) {
3912 if(arr_index < channels_num){
3913 sscanf(line, "%d", &tmp);
3914 if (tmp > 0) { // channel frequency, the first line must be frequency
3915 arr_index++;
3916 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3917 } else { // noise
3918 channels_noise_arr[arr_index].noise = tmp;
3919 }
3920 }else{
3921 break;
developera3c68b92022-09-13 15:27:29 +08003922 }
3923 }
developera3c68b92022-09-13 15:27:29 +08003924 pclose(f);
3925 return RETURN_OK;
3926}
3927
developer06a01d92022-09-07 16:32:39 +08003928//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3929//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3930INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3931{
developera3c68b92022-09-13 15:27:29 +08003932 int index = -1;
3933 wifi_neighbor_ap2_t *scan_array = NULL;
3934 char cmd[256]={0};
3935 char buf[128]={0};
3936 char file_name[32] = {0};
3937 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003938 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08003939 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08003940 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003941 int freq=0;
3942 FILE *f = NULL;
3943 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003944 int channels_num = 0;
3945 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003946 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003947 bool filter_enable = false;
3948 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003949 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003950
developer615510b2022-09-27 10:14:35 +08003951 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003952
developerac6f1142022-12-20 19:26:35 +08003953 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08003954 return RETURN_ERR;
3955
developera3c68b92022-09-13 15:27:29 +08003956 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3957 f = fopen(file_name, "r");
3958 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08003959 fgets(buf, sizeof(file_name), f);
3960 if ((strncmp(buf, "0", 1)) != 0) {
3961 fgets(filter_SSID, sizeof(file_name), f);
3962 if (strlen(filter_SSID) != 0)
3963 filter_enable = true;
3964 }
developera3c68b92022-09-13 15:27:29 +08003965 fclose(f);
3966 }
3967
developer033b37b2022-10-18 11:27:46 +08003968 phyId = radio_index_to_phy(radioIndex);
3969 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003970 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003971 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003972
developer5550e242022-09-30 09:59:32 +08003973
developer06a01d92022-09-07 16:32:39 +08003974
developerd946fd62022-12-08 18:03:28 +08003975 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3976 // 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 +08003977 fprintf(stderr, "cmd: %s\n", cmd);
3978 if ((f = popen(cmd, "r")) == NULL) {
3979 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3980 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003981 }
developer5550e242022-09-30 09:59:32 +08003982
3983 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3984 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3985
developer615510b2022-09-27 10:14:35 +08003986 ret = fgets(line, sizeof(line), f);
3987 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003988 if(strstr(line, "BSS") != NULL) { // new neighbor info
3989 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3990 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3991 // 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 +08003992
developera3c68b92022-09-13 15:27:29 +08003993 if (!filter_BSS) {
3994 index++;
3995 wifi_neighbor_ap2_t *tmp;
3996 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3997 if (tmp == NULL) { // no more memory to use
3998 index--;
3999 wifi_dbg_printf("%s: realloc failed\n", __func__);
4000 break;
4001 }
4002 scan_array = tmp;
4003 }
4004 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4005
4006 filter_BSS = false;
4007 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4008 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4009 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4010 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4011 } else if (strstr(line, "freq") != NULL) {
4012 sscanf(line," freq: %d", &freq);
4013 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4014
4015 if (freq >= 2412 && freq <= 2484) {
4016 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4017 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4018 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4019 }
4020 else if (freq >= 5160 && freq <= 5805) {
4021 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4022 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4023 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4024 }
4025
4026 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08004027 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08004028 for (int i = 0; i < channels_num; i++) {
4029 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4030 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4031 break;
4032 }
4033 }
4034 }
4035 } else if (strstr(line, "beacon interval") != NULL) {
4036 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4037 } else if (strstr(line, "signal") != NULL) {
4038 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4039 } else if (strstr(line,"SSID") != NULL) {
4040 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4041 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4042 filter_BSS = true;
4043 }
4044 } else if (strstr(line, "Supported rates") != NULL) {
4045 char SRate[80] = {0}, *tmp = NULL;
4046 memset(buf, 0, sizeof(buf));
4047 strcpy(SRate, line);
4048 tmp = strtok(SRate, ":");
4049 tmp = strtok(NULL, ":");
4050 strcpy(buf, tmp);
4051 memset(SRate, 0, sizeof(SRate));
4052
4053 tmp = strtok(buf, " \n");
4054 while (tmp != NULL) {
4055 strcat(SRate, tmp);
4056 if (SRate[strlen(SRate) - 1] == '*') {
4057 SRate[strlen(SRate) - 1] = '\0';
4058 }
4059 strcat(SRate, ",");
4060
4061 tmp = strtok(NULL, " \n");
4062 }
4063 SRate[strlen(SRate) - 1] = '\0';
4064 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4065 } else if (strstr(line, "DTIM") != NULL) {
4066 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4067 } else if (strstr(line, "VHT capabilities") != NULL) {
4068 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4069 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4070 } else if (strstr(line, "HT capabilities") != NULL) {
4071 strcat(scan_array[index].ap_SupportedStandards, ",n");
4072 strcpy(scan_array[index].ap_OperatingStandards, "n");
4073 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004074 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004075 sscanf(line," * channel width: %d", &vht_channel_width);
4076 if(vht_channel_width == 1) {
4077 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4078 } else {
4079 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4080 }
4081 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4082 continue;
4083 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08004084 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004085 sscanf(line," * secondary channel offset: %s", &buf);
4086 if (!strcmp(buf, "above")) {
4087 //40Mhz +
4088 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4089 }
4090 else if (!strcmp(buf, "below")) {
4091 //40Mhz -
4092 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4093 } else {
4094 //20Mhz
4095 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4096 }
4097 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4098 continue;
4099 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08004100 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4101 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4102 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004103 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4104 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004105 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08004106 else
developer615510b2022-09-27 10:14:35 +08004107 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08004108 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08004109 if (strstr(line, "HE80/5GHz") != NULL) {
4110 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4111 ret = fgets(line, sizeof(line), f);
4112 } else
4113 continue;
developera3c68b92022-09-13 15:27:29 +08004114 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08004115 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08004116 }
developer615510b2022-09-27 10:14:35 +08004117 continue;
developera3c68b92022-09-13 15:27:29 +08004118 } else if (strstr(line, "WPA") != NULL) {
4119 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4120 } else if (strstr(line, "RSN") != NULL) {
4121 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4122 } else if (strstr(line, "Group cipher") != NULL) {
4123 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4124 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4125 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4126 }
4127 }
developer615510b2022-09-27 10:14:35 +08004128 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08004129 }
4130
4131 if (!filter_BSS) {
4132 *output_array_size = index + 1;
4133 } else {
4134 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4135 *output_array_size = index;
4136 }
4137 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08004138 pclose(f);
developer5550e242022-09-30 09:59:32 +08004139 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08004140 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08004141 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004142}
4143
4144//>> Deprecated: used for old RDKB code.
4145INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4146{
4147 INT status = RETURN_ERR;
4148
4149 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4150 output_struct->wifi_PLCPErrorCount = 0;
4151 output_struct->wifi_FCSErrorCount = 0;
4152 output_struct->wifi_InvalidMACCount = 0;
4153 output_struct->wifi_PacketsOtherReceived = 0;
4154 output_struct->wifi_Noise = 0;
4155 status = RETURN_OK;
4156 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4157 return status;
4158}
4159
4160INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4161{
developerd946fd62022-12-08 18:03:28 +08004162 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004163 char cmd[128] = {0};
4164 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004165 char *pos = NULL;
4166
4167 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4168 if (NULL == output_struct)
4169 return RETURN_ERR;
4170
developerac6f1142022-12-20 19:26:35 +08004171 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004172 return RETURN_ERR;
4173
developer06a01d92022-09-07 16:32:39 +08004174 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4175
developerd946fd62022-12-08 18:03:28 +08004176 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004177 _syscmd(cmd, buf, sizeof(buf));
4178
4179 pos = buf;
4180 if ((pos = strstr(pos, "RX packets:")) == NULL)
4181 return RETURN_ERR;
4182 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4183
4184 if ((pos = strstr(pos, "TX packets:")) == NULL)
4185 return RETURN_ERR;
4186 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4187
4188 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4189 return RETURN_ERR;
4190 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4191
4192 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4193 return RETURN_ERR;
4194 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4195
developerd946fd62022-12-08 18:03:28 +08004196 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004197 _syscmd(cmd, buf, sizeof(buf));
4198 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4199
4200#if 0
4201 //TODO: need to revisit below implementation
4202 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4203 char interface_name[MAX_BUF_SIZE] = {0};
4204 char interface_status[MAX_BUF_SIZE] = {0};
4205 char Value[MAX_BUF_SIZE] = {0};
4206 char buf[MAX_CMD_SIZE] = {0};
4207 char cmd[MAX_CMD_SIZE] = {0};
4208 FILE *fp = NULL;
4209
4210 if (NULL == output_struct) {
4211 return RETURN_ERR;
4212 }
4213
4214 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4215
4216 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4217 {
4218 if(apIndex == 0) //private_wifi for 2.4G
4219 {
developerac6f1142022-12-20 19:26:35 +08004220 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +08004221 }
4222 else if(apIndex == 1) //private_wifi for 5G
4223 {
developerac6f1142022-12-20 19:26:35 +08004224 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +08004225 }
4226 else if(apIndex == 4) //public_wifi for 2.4G
4227 {
4228 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4229 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4230 {
4231 return RETURN_ERR;
4232 }
4233 if(buf[0] == '#')//tp-link
developerac6f1142022-12-20 19:26:35 +08004234 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
developer06a01d92022-09-07 16:32:39 +08004235 else//tenda
developerac6f1142022-12-20 19:26:35 +08004236 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
developer06a01d92022-09-07 16:32:39 +08004237 }
4238 else if(apIndex == 5) //public_wifi for 5G
4239 {
developerac6f1142022-12-20 19:26:35 +08004240 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
developer06a01d92022-09-07 16:32:39 +08004241 }
4242
4243 GetIfacestatus(interface_name, interface_status);
4244
4245 if(0 != strcmp(interface_status, "1"))
4246 return RETURN_ERR;
4247
4248 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4249 system(cmd);
4250
4251 fp = fopen("/tmp/SSID_Stats.txt", "r");
4252 if(fp == NULL)
4253 {
4254 printf("/tmp/SSID_Stats.txt not exists \n");
4255 return RETURN_ERR;
4256 }
4257 fclose(fp);
4258
4259 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4260 File_Reading(buf, Value);
4261 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4262
4263 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4264 File_Reading(buf, Value);
4265 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4266
4267 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4268 File_Reading(buf, Value);
4269 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4270
4271 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4272 File_Reading(buf, Value);
4273 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4274
4275 /* There is no specific parameter from caller to associate the value wifi_Associations */
4276 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4277 //_syscmd(cmd, buf, sizeof(buf));
4278 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4279 }
4280#endif
4281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4282 return RETURN_OK;
4283}
4284
4285INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4286{
4287 char interface_name[MAX_BUF_SIZE] = {0};
4288 char interface_status[MAX_BUF_SIZE] = {0};
4289 char Value[MAX_BUF_SIZE] = {0};
4290 char buf[MAX_CMD_SIZE] = {0};
4291 char cmd[MAX_CMD_SIZE] = {0};
4292 FILE *fp = NULL;
4293
4294 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4295 if (NULL == output_struct)
4296 return RETURN_ERR;
4297
4298 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4299
developerac6f1142022-12-20 19:26:35 +08004300 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08004301 return RETURN_ERR;
4302 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004303
developerd946fd62022-12-08 18:03:28 +08004304 if(0 != strcmp(interface_status, "1"))
4305 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004306
developerd946fd62022-12-08 18:03:28 +08004307 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4308 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004309
developerd946fd62022-12-08 18:03:28 +08004310 fp = fopen("/tmp/SSID_Stats.txt", "r");
4311 if(fp == NULL)
4312 {
4313 printf("/tmp/SSID_Stats.txt not exists \n");
4314 return RETURN_ERR;
4315 }
4316 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004317
developerd946fd62022-12-08 18:03:28 +08004318 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4319 File_Reading(buf, Value);
4320 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004321
developerd946fd62022-12-08 18:03:28 +08004322 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4323 File_Reading(buf, Value);
4324 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004325
developerd946fd62022-12-08 18:03:28 +08004326 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4327 File_Reading(buf, Value);
4328 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004329
developerd946fd62022-12-08 18:03:28 +08004330 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4331 File_Reading(buf, Value);
4332 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004333
4334 output_struct->wifi_UnicastPacketsSent = 0;
4335 output_struct->wifi_UnicastPacketsReceived = 0;
4336 output_struct->wifi_MulticastPacketsSent = 0;
4337 output_struct->wifi_MulticastPacketsReceived = 0;
4338 output_struct->wifi_BroadcastPacketsSent = 0;
4339 output_struct->wifi_BroadcastPacketsRecevied = 0;
4340 output_struct->wifi_UnknownPacketsReceived = 0;
4341
4342 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4343 return RETURN_OK;
4344}
4345
4346INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4347{
4348 INT status = RETURN_ERR;
4349
4350 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4351 //Below values should get updated from hal
4352 output_struct->wifi_RetransCount=0;
4353 output_struct->wifi_FailedRetransCount=0;
4354 output_struct->wifi_RetryCount=0;
4355 output_struct->wifi_MultipleRetryCount=0;
4356 output_struct->wifi_ACKFailureCount=0;
4357 output_struct->wifi_AggregatedPacketCount=0;
4358
4359 status = RETURN_OK;
4360 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4361
4362 return status;
4363}
4364
4365INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4366{
4367 INT status = RETURN_ERR;
4368 UINT index;
4369 wifi_neighbor_ap_t *pt=NULL;
4370
4371 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4372 *output_array_size=2;
4373 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4374 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4375 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4376 strcpy(pt->ap_Radio,"");
4377 strcpy(pt->ap_SSID,"");
4378 strcpy(pt->ap_BSSID,"");
4379 strcpy(pt->ap_Mode,"");
4380 pt->ap_Channel=1;
4381 pt->ap_SignalStrength=0;
4382 strcpy(pt->ap_SecurityModeEnabled,"");
4383 strcpy(pt->ap_EncryptionMode,"");
4384 strcpy(pt->ap_OperatingFrequencyBand,"");
4385 strcpy(pt->ap_SupportedStandards,"");
4386 strcpy(pt->ap_OperatingStandards,"");
4387 strcpy(pt->ap_OperatingChannelBandwidth,"");
4388 pt->ap_BeaconPeriod=1;
4389 pt->ap_Noise=0;
4390 strcpy(pt->ap_BasicDataTransferRates,"");
4391 strcpy(pt->ap_SupportedDataTransferRates,"");
4392 pt->ap_DTIMPeriod=1;
4393 pt->ap_ChannelUtilization = 1;
4394 }
4395
4396 status = RETURN_OK;
4397 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4398
4399 return status;
4400}
4401
4402//----------------- AP HAL -------------------------------
4403
4404//>> Deprecated: used for old RDKB code.
4405INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4406{
4407 if (NULL == output_ulong || NULL == output_struct)
4408 return RETURN_ERR;
4409 *output_ulong = 0;
4410 *output_struct = NULL;
4411 return RETURN_OK;
4412}
4413
4414#ifdef HAL_NETLINK_IMPL
4415static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4416 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4417 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4418 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4419 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4420 char mac_addr[20];
4421 static int count=0;
4422 int rate=0;
4423
4424 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4425
4426 nla_parse(tb,
4427 NL80211_ATTR_MAX,
4428 genlmsg_attrdata(gnlh, 0),
4429 genlmsg_attrlen(gnlh, 0),
4430 NULL);
4431
4432 if(!tb[NL80211_ATTR_STA_INFO]) {
4433 fprintf(stderr, "sta stats missing!\n");
4434 return NL_SKIP;
4435 }
4436
4437
4438 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4439 fprintf(stderr, "failed to parse nested attributes!\n");
4440 return NL_SKIP;
4441 }
4442
4443 //devIndex starts from 1
4444 if( ++count == out->wifi_devIndex )
4445 {
4446 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4447 //Getting the mac addrress
4448 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4449
4450 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4451 fprintf(stderr, "failed to parse nested rate attributes!");
4452 return NL_SKIP;
4453 }
4454
4455 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4456 if(rinfo[NL80211_RATE_INFO_BITRATE])
4457 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4458 out->wifi_devTxRate = rate/10;
4459 }
4460
4461 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4462 fprintf(stderr, "failed to parse nested rate attributes!");
4463 return NL_SKIP;
4464 }
4465
4466 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4467 if(rinfo[NL80211_RATE_INFO_BITRATE])
4468 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4469 out->wifi_devRxRate = rate/10;
4470 }
4471 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4472 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4473
4474 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4475 count = 0; //starts the count for next cycle
4476 return NL_STOP;
4477 }
4478
4479 return NL_SKIP;
4480
4481}
4482#endif
4483
4484INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4485{
4486#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004487 Netlink nl = {0};
4488 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004489 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004490
developer30423732022-12-01 16:17:49 +08004491 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004492 info.wifi_devIndex = devIndex;
4493
developerac6f1142022-12-20 19:26:35 +08004494 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004495 return RETURN_ERR;
4496
4497 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004498
4499 nl.id = initSock80211(&nl);
4500
4501 if (nl.id < 0) {
4502 fprintf(stderr, "Error initializing netlink \n");
4503 return -1;
4504 }
4505
4506 struct nl_msg* msg = nlmsg_alloc();
4507
4508 if (!msg) {
4509 fprintf(stderr, "Failed to allocate netlink message.\n");
4510 nlfree(&nl);
4511 return -2;
4512 }
4513
4514 genlmsg_put(msg,
4515 NL_AUTO_PORT,
4516 NL_AUTO_SEQ,
4517 nl.id,
4518 0,
4519 NLM_F_DUMP,
4520 NL80211_CMD_GET_STATION,
4521 0);
4522
4523 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4524 nl_send_auto(nl.socket, msg);
4525 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4526 nl_recvmsgs(nl.socket, nl.cb);
4527 nlmsg_free(msg);
4528 nlfree(&nl);
4529
4530 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4531 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4532 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4533 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4534 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4535 return RETURN_OK;
4536#else
4537 //iw utility to retrieve station information
4538#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4539#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4540#define MACFILE "/tmp/wifi_AssoMac.txt"
4541#define TXRATEFILE "/tmp/wifi_txrate.txt"
4542#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4543 FILE *file = NULL;
4544 char if_name[10] = {'\0'};
4545 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004546 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004547 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004548 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004549
developerac6f1142022-12-20 19:26:35 +08004550 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004551 return RETURN_ERR;
4552
4553 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004554
4555 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4556 file = popen(pipeCmd, "r");
4557
4558 if(file == NULL)
4559 return RETURN_ERR; //popen failed
4560
4561 fgets(line, sizeof line, file);
4562 device = atoi(line);
4563 pclose(file);
4564
4565 if(device == 0)
4566 return RETURN_ERR; //No devices are connected
4567
4568 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4569 system(pipeCmd);
4570
4571 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4572
4573 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4574
4575 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4576
4577 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4578
4579 //devIndex starts from 1, ++count
4580 if((file = fopen(SIGNALFILE, "r")) != NULL )
4581 {
4582 for(count =0;fgets(line, sizeof line, file) != NULL;)
4583 {
4584 if (++count == devIndex)
4585 {
4586 output_struct->wifi_devSignalStrength = atoi(line);
4587 break;
4588 }
4589 }
4590 fclose(file);
4591 }
4592 else
4593 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4594
4595 if((file = fopen(MACFILE, "r")) != NULL )
4596 {
4597 for(count =0;fgets(line, sizeof line, file) != NULL;)
4598 {
4599 if (++count == devIndex)
4600 {
4601 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]);
4602 break;
4603 }
4604 }
4605 fclose(file);
4606 }
4607 else
4608 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4609
4610 if((file = fopen(TXRATEFILE, "r")) != NULL )
4611 {
4612 for(count =0;fgets(line, sizeof line, file) != NULL;)
4613 {
4614 if (++count == devIndex)
4615 {
4616 output_struct->wifi_devTxRate = atoi(line);
4617 break;
4618 }
4619 }
4620 fclose(file);
4621 }
4622 else
4623 fprintf(stderr,"fopen wifi_txrate.txt failed");
4624
4625 if((file = fopen(RXRATEFILE, "r")) != NULL)
4626 {
4627 for(count =0;fgets(line, sizeof line, file) != NULL;)
4628 {
4629 if (++count == devIndex)
4630 {
4631 output_struct->wifi_devRxRate = atoi(line);
4632 break;
4633 }
4634 }
4635 fclose(file);
4636 }
4637 else
4638 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4639
4640 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4641
4642 return RETURN_OK;
4643#endif
4644}
4645
4646INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4647{
4648 if (NULL == device)
4649 return RETURN_ERR;
4650 return RETURN_OK;
4651}
4652//<<
4653
4654
4655//--------------wifi_ap_hal-----------------------------
4656//enables CTS protection for the radio used by this AP
4657INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4658{
4659 //save config and Apply instantly
4660 return RETURN_ERR;
4661}
4662
4663// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4664INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4665{
developer463d39a2022-09-13 15:32:51 +08004666 char config_file[64] = {'\0'};
4667 char buf[64] = {'\0'};
4668 struct params list;
4669
4670 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4671 list.name = "ht_coex";
4672 snprintf(buf, sizeof(buf), "%d", enable);
4673 list.value = buf;
4674
4675 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4676 wifi_hostapdWrite(config_file, &list, 1);
4677 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4678
4679 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4680
4681 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004682}
4683
4684//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4685INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4686{
developerea4bcce2022-09-13 15:26:13 +08004687 char config_file[MAX_BUF_SIZE] = {'\0'};
4688 char buf[MAX_BUF_SIZE] = {'\0'};
4689 struct params list;
4690
4691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4692 if (threshold < 256 || threshold > 2346 )
4693 return RETURN_ERR;
4694 list.name = "fragm_threshold";
4695 snprintf(buf, sizeof(buf), "%d", threshold);
4696 list.value = buf;
4697
4698 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4699 wifi_hostapdWrite(config_file, &list, 1);
4700 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004701
developerea4bcce2022-09-13 15:26:13 +08004702 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004703
4704 return RETURN_OK;
4705}
4706
4707// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4708INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4709{
developer51a927d2022-09-13 15:42:22 +08004710 char config_file[64] = {'\0'};
developer110b8a32022-12-26 15:56:44 +08004711 char cmd[512] = {'\0'};
4712 char buf[512] = {'\0'};
developer51a927d2022-09-13 15:42:22 +08004713 char stbc_config[16] = {'\0'};
4714 wifi_band band;
4715 int iterator = 0;
4716 BOOL current_stbc = FALSE;
developer110b8a32022-12-26 15:56:44 +08004717 int ant_count = 0;
4718 int ant_bitmap = 0;
4719 struct params list;
developer51a927d2022-09-13 15:42:22 +08004720
4721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4722
4723 band = wifi_index_to_band(radioIndex);
4724 if (band == band_invalid)
4725 return RETURN_ERR;
4726
4727 if (band == band_2_4)
4728 iterator = 1;
4729 else if (band == band_5)
4730 iterator = 2;
4731 else
4732 return RETURN_OK;
4733
developer110b8a32022-12-26 15:56:44 +08004734 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4735 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4736 ant_count += ant_bitmap & 1;
4737
4738 if (ant_count == 1 && STBC_Enable == TRUE) {
4739 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4740 return RETURN_OK;
4741 }
4742
developer51a927d2022-09-13 15:42:22 +08004743 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4744
4745 // set ht and vht config
4746 for (int i = 0; i < iterator; i++) {
4747 memset(stbc_config, 0, sizeof(stbc_config));
4748 memset(cmd, 0, sizeof(cmd));
4749 memset(buf, 0, sizeof(buf));
developer110b8a32022-12-26 15:56:44 +08004750 list.name = (i == 0)?"ht_capab":"vht_capab";
4751 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
developer51a927d2022-09-13 15:42:22 +08004752 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4753 _syscmd(cmd, buf, sizeof(buf));
4754 if (strlen(buf) != 0)
4755 current_stbc = TRUE;
4756 if (current_stbc == STBC_Enable)
4757 continue;
4758
4759 if (STBC_Enable == TRUE) {
4760 // Append the STBC flags in capab config
4761 memset(cmd, 0, sizeof(cmd));
4762 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004763 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004764 else
developer6372c2b2022-10-27 17:39:51 +08004765 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 +08004766 _syscmd(cmd, buf, sizeof(buf));
4767 } else if (STBC_Enable == FALSE) {
4768 // Remove the STBC flags and remain other flags in capab
4769 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004770 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004771 _syscmd(cmd, buf, sizeof(buf));
4772 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004773 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004774 _syscmd(cmd, buf, sizeof(buf));
4775 }
developer110b8a32022-12-26 15:56:44 +08004776 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4777 list.value = buf;
4778 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
developer51a927d2022-09-13 15:42:22 +08004779 }
4780
4781 wifi_reloadAp(radioIndex);
4782
4783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4784 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004785}
4786
4787// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4788INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4789{
developerfe7aefc2022-12-23 17:13:37 +08004790 char cmd[128] = {0};
4791 char buf[128] = {0};
4792 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004793
4794 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4795
4796 if(output_bool == NULL)
4797 return RETURN_ERR;
4798
developerfe7aefc2022-12-23 17:13:37 +08004799 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4800 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004801
developerfe7aefc2022-12-23 17:13:37 +08004802 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4803 _syscmd(cmd, buf, sizeof(buf));
4804
4805 if (strncmp(buf, "1", 1) == 0)
developer54e6b9f2022-09-28 14:41:20 +08004806 *output_bool = TRUE;
4807 else
4808 *output_bool = FALSE;
4809
4810 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4811 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004812}
4813
4814// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4815INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4816{
developerfe7aefc2022-12-23 17:13:37 +08004817 char config_file[128] = {0};
4818 struct params list = {0};
4819 BOOL enable;
developer54e6b9f2022-09-28 14:41:20 +08004820
4821 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4822
developerfe7aefc2022-12-23 17:13:37 +08004823 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08004824 return RETURN_ERR;
developer54e6b9f2022-09-28 14:41:20 +08004825
developerfe7aefc2022-12-23 17:13:37 +08004826 if (amsduEnable == enable)
4827 return RETURN_OK;
4828
4829 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4830 list.name = "amsdu";
4831 list.value = amsduEnable? "1":"0";
4832 wifi_hostapdWrite(config_file, &list, 1);
4833 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4834 wifi_reloadAp(radioIndex);
developer54e6b9f2022-09-28 14:41:20 +08004835
4836 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4837 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004838}
4839
4840//P2 // outputs the number of Tx streams
4841INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4842{
developer2de97692022-09-26 14:00:03 +08004843 char buf[8] = {0};
4844 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004845 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004846
4847 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4848
developer033b37b2022-10-18 11:27:46 +08004849 phyId = radio_index_to_phy(radioIndex);
developerfe7aefc2022-12-23 17:13:37 +08004850 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
developer110b8a32022-12-26 15:56:44 +08004851 _syscmd(cmd, buf, sizeof(buf));
developer2de97692022-09-26 14:00:03 +08004852
developer110b8a32022-12-26 15:56:44 +08004853 *output_int = (INT)strtol(buf, NULL, 16);
developer2de97692022-09-26 14:00:03 +08004854
4855 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4856
4857 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004858}
4859
developer110b8a32022-12-26 15:56:44 +08004860INT fitChainMask(INT radioIndex, int antcount)
4861{
4862 char buf[128] = {0};
4863 char cmd[128] = {0};
4864 char config_file[64] = {0};
4865 wifi_band band;
4866 struct params list[2] = {0};
4867
4868 band = wifi_index_to_band(radioIndex);
4869 if (band == band_invalid)
4870 return RETURN_ERR;
4871
4872 list[0].name = "he_mu_beamformer";
4873 list[1].name = "he_su_beamformer";
4874
4875 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4876 if (antcount == 1) {
4877 // remove config about multiple antennas
4878 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4879 _syscmd(cmd, buf, sizeof(buf));
4880
4881 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4882 _syscmd(cmd, buf, sizeof(buf));
4883
4884 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4885 _syscmd(cmd, buf, sizeof(buf));
4886
4887 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4888 _syscmd(cmd, buf, sizeof(buf));
4889
4890 list[0].value = "0";
4891 list[1].value = "0";
4892 } else {
4893 // 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.
4894 if (band == band_2_4 || band == band_5) {
4895 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4896 _syscmd(cmd, buf, sizeof(buf));
4897 if (strlen(buf) > 0) {
4898 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4899 _syscmd(cmd, buf, sizeof(buf));
4900 }
4901 }
4902 if (band == band_5) {
4903 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4904 _syscmd(cmd, buf, sizeof(buf));
4905 if (strlen(buf) > 0) {
4906 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4907 _syscmd(cmd, buf, sizeof(buf));
4908 }
4909 }
4910
4911 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4912 _syscmd(cmd, buf, sizeof(buf));
4913 if (strlen(buf) == 0) {
4914 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4915 _syscmd(cmd, buf, sizeof(buf));
4916 }
4917
4918 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4919 _syscmd(cmd, buf, sizeof(buf));
4920 if (strlen(buf) == 0) {
4921 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4922 _syscmd(cmd, buf, sizeof(buf));
4923 }
4924
4925 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4926 _syscmd(cmd, buf, sizeof(buf));
4927 if (strlen(buf) == 0) {
4928 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4929 } else {
4930 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4931 }
4932 _syscmd(cmd, buf, sizeof(buf));
4933
4934 list[0].value = "1";
4935 list[1].value = "1";
4936 }
4937 wifi_hostapdWrite(config_file, list, 2);
4938}
4939
developer06a01d92022-09-07 16:32:39 +08004940//P2 // sets the number of Tx streams to an enviornment variable
4941INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4942{
developer2de97692022-09-26 14:00:03 +08004943 char cmd[128] = {0};
4944 char buf[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004945 int phyId = 0;
developer110b8a32022-12-26 15:56:44 +08004946 int cur_mask = 0;
4947 int antcount = 0;
4948 wifi_band band;
developer2de97692022-09-26 14:00:03 +08004949
4950 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4951
developer110b8a32022-12-26 15:56:44 +08004952 if (numStreams <= 0) {
4953 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
developer2de97692022-09-26 14:00:03 +08004954 return RETURN_ERR;
4955 }
developer110b8a32022-12-26 15:56:44 +08004956
4957 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
4958 if (cur_mask == numStreams)
4959 return RETURN_OK;
4960
developer2de97692022-09-26 14:00:03 +08004961 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004962
4963 phyId = radio_index_to_phy(radioIndex);
4964 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004965 _syscmd(cmd, buf, sizeof(buf));
4966
4967 if (strlen(buf) > 0) {
4968 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4969 return RETURN_ERR;
4970 }
developer2de97692022-09-26 14:00:03 +08004971
developer110b8a32022-12-26 15:56:44 +08004972 // if chain mask changed, we need to make the hostapd config valid.
4973 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
4974 antcount += cur_mask & 1;
developer2de97692022-09-26 14:00:03 +08004975 }
developer110b8a32022-12-26 15:56:44 +08004976 fitChainMask(radioIndex, antcount);
4977
4978 wifi_setRadioEnable(radioIndex, TRUE);
4979
developer2de97692022-09-26 14:00:03 +08004980 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4981 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004982}
4983
4984//P2 // outputs the number of Rx streams
4985INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4986{
developer110b8a32022-12-26 15:56:44 +08004987 char buf[8] = {0};
4988 char cmd[128] = {0};
4989 int phyId = 0;
4990
developer2de97692022-09-26 14:00:03 +08004991 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08004992
4993 phyId = radio_index_to_phy(radioIndex);
4994 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
4995 _syscmd(cmd, buf, sizeof(buf));
4996
4997 *output_int = (INT)strtol(buf, NULL, 16);
4998
developer2de97692022-09-26 14:00:03 +08004999 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer110b8a32022-12-26 15:56:44 +08005000
developer06a01d92022-09-07 16:32:39 +08005001 return RETURN_OK;
5002}
5003
5004//P2 // sets the number of Rx streams to an enviornment variable
5005INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5006{
developer2de97692022-09-26 14:00:03 +08005007 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5008 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5009 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5010 return RETURN_ERR;
5011 }
5012 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005013 return RETURN_ERR;
5014}
5015
5016//Get radio RDG enable setting
5017INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5018{
5019 if (NULL == output_bool)
5020 return RETURN_ERR;
5021 *output_bool = TRUE;
5022 return RETURN_OK;
5023}
5024
5025//Get radio RDG enable setting
5026INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5027{
5028 if (NULL == output_bool)
5029 return RETURN_ERR;
5030 *output_bool = TRUE;
5031 return RETURN_OK;
5032}
5033
5034//Set radio RDG enable setting
5035INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5036{
5037 return RETURN_ERR;
5038}
5039
5040//Get radio ADDBA enable setting
5041INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5042{
5043 if (NULL == output_bool)
5044 return RETURN_ERR;
5045 *output_bool = TRUE;
5046 return RETURN_OK;
5047}
5048
5049//Set radio ADDBA enable setting
5050INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5051{
5052 return RETURN_ERR;
5053}
5054
5055//Get radio auto block ack enable setting
5056INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5057{
5058 if (NULL == output_bool)
5059 return RETURN_ERR;
5060 *output_bool = TRUE;
5061 return RETURN_OK;
5062}
5063
5064//Set radio auto block ack enable setting
5065INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5066{
5067 return RETURN_ERR;
5068}
5069
5070//Get radio 11n pure mode enable support
5071INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5072{
5073 if (NULL == output_bool)
5074 return RETURN_ERR;
5075 *output_bool = TRUE;
5076 return RETURN_OK;
5077}
5078
5079//Get radio 11n pure mode enable setting
5080INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5081{
5082 if (NULL == output_bool)
5083 return RETURN_ERR;
5084 *output_bool = TRUE;
5085 return RETURN_OK;
5086}
5087
5088//Set radio 11n pure mode enable setting
5089INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5090{
5091 return RETURN_ERR;
5092}
5093
5094//Get radio IGMP snooping enable setting
5095INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5096{
developerd946fd62022-12-08 18:03:28 +08005097 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005098 char cmd[128]={0};
5099 char buf[4]={0};
5100 bool bridge = FALSE, mac80211 = FALSE;
5101 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5102
5103 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08005104 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08005105
5106 *output_bool = FALSE;
5107
5108 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5109 _syscmd(cmd, buf, sizeof(buf));
5110 if (strncmp(buf, "1", 1) == 0)
5111 bridge = TRUE;
5112
developerac6f1142022-12-20 19:26:35 +08005113 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005114 return RETURN_ERR;
5115 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 +08005116 _syscmd(cmd, buf, sizeof(buf));
5117 if (strncmp(buf, "1", 1) == 0)
5118 mac80211 = TRUE;
5119
5120 if (bridge && mac80211)
5121 *output_bool = TRUE;
5122
5123 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08005124 return RETURN_OK;
5125}
5126
5127//Set radio IGMP snooping enable setting
5128INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5129{
developerd946fd62022-12-08 18:03:28 +08005130 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08005131 char cmd[128]={0};
5132 char buf[4]={0};
developer804c64f2022-10-19 13:54:40 +08005133 int max_num_radios =0;
developer81bf2ed2022-09-13 15:31:14 +08005134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5135
5136 // bridge
5137 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
5138 _syscmd(cmd, buf, sizeof(buf));
5139
developer804c64f2022-10-19 13:54:40 +08005140 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08005141 // mac80211
developer804c64f2022-10-19 13:54:40 +08005142 for (int i = 0; i < max_num_radios; i++) {
developerac6f1142022-12-20 19:26:35 +08005143 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005144 return RETURN_ERR;
5145 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 +08005146 _syscmd(cmd, buf, sizeof(buf));
5147 }
5148 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5149 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005150}
5151
5152//Get the Reset count of radio
5153INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5154{
5155 if (NULL == output_int)
5156 return RETURN_ERR;
5157 *output_int = (radioIndex==0)? 1: 3;
5158
5159 return RETURN_OK;
5160}
5161
5162
5163//---------------------------------------------------------------------------------------------------
5164//
5165// Additional Wifi AP level APIs used for Access Point devices
5166//
5167//---------------------------------------------------------------------------------------------------
5168
5169// creates a new ap and pushes these parameters to the hardware
5170INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5171{
developer7930d352022-12-21 17:55:42 +08005172 // Deprecated when use hal version 3, use wifi_createVap() instead.
developer06a01d92022-09-07 16:32:39 +08005173 return RETURN_OK;
5174}
5175
5176// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5177INT wifi_deleteAp(INT apIndex)
5178{
developerd946fd62022-12-08 18:03:28 +08005179 char interface_name[16] = {0};
developer89df4502023-02-16 20:45:02 +08005180 char buf[128] = {0};
5181 char cmd[128] = {0};
developer06a01d92022-09-07 16:32:39 +08005182
developerac6f1142022-12-20 19:26:35 +08005183 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005184 return RETURN_ERR;
developera77d84b2023-02-22 16:10:50 +08005185
developer89df4502023-02-16 20:45:02 +08005186 if (wifi_setApEnable(apIndex, FALSE) != RETURN_OK)
5187 return RETURN_ERR;
5188
developer7930d352022-12-21 17:55:42 +08005189 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08005190 _syscmd(cmd, buf, sizeof(buf));
5191
5192 wifi_removeApSecVaribles(apIndex);
developer06a01d92022-09-07 16:32:39 +08005193 return RETURN_OK;
5194}
5195
5196// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5197INT wifi_getApName(INT apIndex, CHAR *output_string)
5198{
developerd946fd62022-12-08 18:03:28 +08005199 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005200 if(NULL == output_string)
5201 return RETURN_ERR;
5202
developerac6f1142022-12-20 19:26:35 +08005203 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer67b8ee92022-12-20 10:48:43 +08005204 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08005205 else
5206 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005207 return RETURN_OK;
5208}
5209
5210// Outputs the index number in that corresponds to the SSID string
5211INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5212{
developerd946fd62022-12-08 18:03:28 +08005213 char cmd [128] = {0};
5214 char buf[32] = {0};
5215 char *apIndex_str = NULL;
developerd946fd62022-12-08 18:03:28 +08005216 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08005217
developerd946fd62022-12-08 18:03:28 +08005218 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5219 _syscmd(cmd, buf, sizeof(buf));
developer67b8ee92022-12-20 10:48:43 +08005220
developerac6f1142022-12-20 19:26:35 +08005221 if (strlen(buf) != 0) {
5222 apIndex_str = strtok(buf, "\n");
5223 *output_int = strtoul(apIndex_str, NULL, 10);
5224 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005225 }
developer67b8ee92022-12-20 10:48:43 +08005226
5227 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5228 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5229 if (apIndex_str) {
5230 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5231 return RETURN_OK;
5232 }
developerd946fd62022-12-08 18:03:28 +08005233 *output_int = -1;
5234 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005235}
5236
5237INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5238{
5239 return wifi_getIndexFromName(inputSsidString, output_int);
5240}
5241
5242// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5243INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5244{
5245 char buf[MAX_BUF_SIZE] = {0};
5246 char cmd[MAX_CMD_SIZE] = {0};
5247 char config_file[MAX_BUF_SIZE] = {0};
5248
5249 if(NULL == output_string)
5250 return RETURN_ERR;
5251
5252 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5253 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5254 if((strcmp(buf,"3")==0))
5255 snprintf(output_string, 32, "WPAand11i");
5256 else if((strcmp(buf,"2")==0))
5257 snprintf(output_string, 32, "11i");
5258 else if((strcmp(buf,"1")==0))
5259 snprintf(output_string, 32, "WPA");
5260 else
5261 snprintf(output_string, 32, "None");
5262
5263 return RETURN_OK;
5264}
5265
5266// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5267INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5268{
5269 char config_file[MAX_BUF_SIZE] = {0};
5270 struct params list;
5271
5272 if (NULL == beaconTypeString)
5273 return RETURN_ERR;
5274 list.name = "wpa";
5275 list.value = "0";
5276
5277 if((strcmp(beaconTypeString,"WPAand11i")==0))
5278 list.value="3";
5279 else if((strcmp(beaconTypeString,"11i")==0))
5280 list.value="2";
5281 else if((strcmp(beaconTypeString,"WPA")==0))
5282 list.value="1";
5283
5284 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5285 wifi_hostapdWrite(config_file, &list, 1);
5286 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5287 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5288 return RETURN_OK;
5289}
5290
5291// sets the beacon interval on the hardware for this AP
5292INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5293{
developer5f222492022-09-13 15:21:52 +08005294 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5295 struct params params={'\0'};
5296 char buf[MAX_BUF_SIZE] = {'\0'};
5297 char config_file[MAX_BUF_SIZE] = {'\0'};
5298
5299 params.name = "beacon_int";
5300 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5301 params.value = buf;
5302
5303 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5304 wifi_hostapdWrite(config_file, &params, 1);
5305
5306 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5307 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5308 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005309}
5310
5311INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5312{
developer5b398df2022-11-17 20:39:48 +08005313 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5314 return RETURN_ERR;
5315 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005316}
5317
5318// Get the packet size threshold supported.
5319INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5320{
5321 //save config and apply instantly
5322 if (NULL == output_bool)
5323 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005324 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005325 return RETURN_OK;
5326}
5327
5328// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5329INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5330{
developer514406b2022-12-05 17:20:21 +08005331 char buf[16] = {0};
5332 char config_file[128] = {0};
5333 struct params param = {0};
5334
5335 if (threshold > 65535) {
5336 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5337 return RETURN_ERR;
5338 }
developer06a01d92022-09-07 16:32:39 +08005339
developer23e71282023-01-18 10:25:19 +08005340 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer514406b2022-12-05 17:20:21 +08005341 snprintf(buf, sizeof(buf), "%u", threshold);
5342 param.name = "rts_threshold";
5343 param.value = buf;
5344 wifi_hostapdWrite(config_file, &param, 1);
5345 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5346 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005347
5348 return RETURN_OK;
5349}
5350
5351// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5352INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5353{
5354 if (NULL == output_string)
5355 return RETURN_ERR;
5356 snprintf(output_string, 32, "TKIPandAESEncryption");
5357 return RETURN_OK;
5358
5359}
5360
5361// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5362INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5363{
5364 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005365 char *param_name = NULL;
5366 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005367
5368 if(NULL == output_string)
5369 return RETURN_ERR;
5370
5371 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5372 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5373
5374 if(strcmp(buf,"0")==0)
5375 {
5376 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5377 snprintf(output_string, 32, "None");
5378 return RETURN_OK;
5379 }
5380 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5381 param_name = "rsn_pairwise";
5382 else if((strcmp(buf,"1")==0))
5383 param_name = "wpa_pairwise";
5384 else
5385 return RETURN_ERR;
5386 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005387 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005388 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5389 param_name = "wpa_pairwise";
5390 memset(output_string, '\0', 32);
5391 wifi_hostapdRead(config_file, param_name, output_string, 32);
5392 }
developer06a01d92022-09-07 16:32:39 +08005393 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5394
developer72ec5572023-01-05 16:27:13 +08005395 if(strcmp(output_string,"TKIP CCMP") == 0)
5396 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5397 else if(strcmp(output_string,"TKIP") == 0)
developer06a01d92022-09-07 16:32:39 +08005398 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5399 else if(strcmp(output_string,"CCMP") == 0)
5400 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer06a01d92022-09-07 16:32:39 +08005401
5402 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5403 return RETURN_OK;
5404}
5405
5406// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5407INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5408{
5409 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5410 struct params params={'\0'};
5411 char output_string[32];
developer72ec5572023-01-05 16:27:13 +08005412 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08005413
5414 memset(output_string,'\0',32);
developer72ec5572023-01-05 16:27:13 +08005415 wifi_getApBeaconType(apIndex,output_string);
developer06a01d92022-09-07 16:32:39 +08005416
5417 if(strcmp(encMode, "TKIPEncryption") == 0)
5418 params.value = "TKIP";
5419 else if(strcmp(encMode,"AESEncryption") == 0)
5420 params.value = "CCMP";
5421 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5422 params.value = "TKIP CCMP";
5423
5424 if((strcmp(output_string,"WPAand11i")==0))
5425 {
5426 params.name = "wpa_pairwise";
5427 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5428 wifi_hostapdWrite(config_file, &params, 1);
5429 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5430
developer30423732022-12-01 16:17:49 +08005431 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005432 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5433 wifi_hostapdWrite(config_file, &params, 1);
5434 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5435
5436 return RETURN_OK;
5437 }
5438 else if((strcmp(output_string,"11i")==0))
5439 {
5440 params.name = "rsn_pairwise";
5441 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5442 wifi_hostapdWrite(config_file, &params, 1);
5443 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5444 return RETURN_OK;
5445 }
5446 else if((strcmp(output_string,"WPA")==0))
5447 {
5448 params.name = "wpa_pairwise";
5449 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5450 wifi_hostapdWrite(config_file, &params, 1);
5451 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5452 return RETURN_OK;
5453 }
5454
5455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5456 return RETURN_OK;
5457}
5458
5459// deletes internal security varable settings for this ap
5460INT wifi_removeApSecVaribles(INT apIndex)
5461{
5462 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005463 //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 +08005464 //_syscmd(cmd, buf, sizeof(buf));
5465
developerd946fd62022-12-08 18:03:28 +08005466 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005467 //_syscmd(cmd, buf, sizeof(buf));
5468 return RETURN_ERR;
5469}
5470
5471// changes the hardware settings to disable encryption on this ap
5472INT wifi_disableApEncryption(INT apIndex)
5473{
5474 //Apply instantly
5475 return RETURN_ERR;
5476}
5477
5478// set the authorization mode on this ap
5479// mode mapping as: 1: open, 2: shared, 4:auto
5480INT wifi_setApAuthMode(INT apIndex, INT mode)
5481{
developeraf95c502022-09-13 16:18:22 +08005482 struct params params={0};
5483 char config_file[64] = {0};
5484 int ret;
5485
5486 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5487
5488 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5489 params.name = "auth_algs";
5490
developer72ec5572023-01-05 16:27:13 +08005491 if ((mode & 1 && mode & 2) || mode & 4)
developeraf95c502022-09-13 16:18:22 +08005492 params.value = "3";
5493 else if (mode & 2)
5494 params.value = "2";
5495 else if (mode & 1)
5496 params.value = "1";
5497 else
5498 params.value = "0";
5499
5500 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5501 wifi_hostapdWrite(config_file, &params, 1);
5502 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer72ec5572023-01-05 16:27:13 +08005503 wifi_reloadAp(apIndex);
developeraf95c502022-09-13 16:18:22 +08005504 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5505
5506 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005507}
5508
5509// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5510INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5511{
5512 //save to wifi config, and wait for wifi restart to apply
5513 struct params params={'\0'};
5514 char config_file[MAX_BUF_SIZE] = {0};
5515 int ret;
5516
5517 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5518 if(authMode == NULL)
5519 return RETURN_ERR;
5520
5521 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5522 params.name = "wpa_key_mgmt";
5523
5524 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5525 params.value = "WPA-PSK";
5526 else if(strcmp(authMode,"EAPAuthentication") == 0)
5527 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005528 else if (strcmp(authMode, "SAEAuthentication") == 0)
5529 params.value = "SAE";
5530 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5531 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005532 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5533 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer5c9fee82023-01-13 14:44:16 +08005534 else if (strcmp(authMode, "Enhanced_Open") == 0)
5535 params.value = "OWE";
developer06a01d92022-09-07 16:32:39 +08005536 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5537 return RETURN_OK; //This is taken careof in beaconType
5538
5539 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5540 ret=wifi_hostapdWrite(config_file,&params,1);
5541 if(!ret)
5542 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5544
5545 return ret;
5546}
5547
5548// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5549INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5550{
5551 //save to wifi config, and wait for wifi restart to apply
5552 char BeaconType[50] = {0};
5553 char config_file[MAX_BUF_SIZE] = {0};
5554
5555 *authMode = 0;
5556 wifi_getApBeaconType(apIndex,BeaconType);
5557 printf("%s____%s \n",__FUNCTION__,BeaconType);
5558
5559 if(strcmp(BeaconType,"None") == 0)
5560 strcpy(authMode,"None");
5561 else
5562 {
5563 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5564 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5565 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5566 if(strcmp(authMode,"WPA-PSK") == 0)
5567 strcpy(authMode,"SharedAuthentication");
5568 else if(strcmp(authMode,"WPA-EAP") == 0)
5569 strcpy(authMode,"EAPAuthentication");
5570 }
5571
5572 return RETURN_OK;
5573}
5574
5575// Outputs the number of stations associated per AP
5576INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5577{
developerd946fd62022-12-08 18:03:28 +08005578 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005579 char cmd[128]={0};
5580 char buf[128]={0};
5581 BOOL status = false;
5582
5583 if(apIndex > MAX_APS)
5584 return RETURN_ERR;
5585
5586 wifi_getApEnable(apIndex,&status);
5587 if (!status)
5588 return RETURN_OK;
5589
developerd946fd62022-12-08 18:03:28 +08005590 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
developerac6f1142022-12-20 19:26:35 +08005591 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005592 return RETURN_ERR;
5593 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005594 _syscmd(cmd, buf, sizeof(buf));
5595 sscanf(buf,"%lu", output_ulong);
5596
5597 return RETURN_OK;
5598}
5599
5600// manually removes any active wi-fi association with the device specified on this ap
5601INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5602{
developerd946fd62022-12-08 18:03:28 +08005603 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005604 char buf[126]={'\0'};
5605
developerac6f1142022-12-20 19:26:35 +08005606 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005607 return RETURN_ERR;
5608 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005609 system(buf);
5610
5611 return RETURN_OK;
5612}
5613
5614// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5615INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5616{
5617 if(NULL == output_int)
5618 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005619 int max_radio_num = 0;
5620 wifi_getMaxRadioNumber(&max_radio_num);
5621 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005622 return RETURN_OK;
5623}
5624
5625// sets the radio index for the specific ap
5626INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5627{
5628 //set to config only and wait for wifi reset to apply settings
5629 return RETURN_ERR;
5630}
5631
5632// Get the ACL MAC list per AP
5633INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5634{
developerd946fd62022-12-08 18:03:28 +08005635 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005636 char cmd[MAX_CMD_SIZE]={'\0'};
5637 int ret = 0;
5638
developerac6f1142022-12-20 19:26:35 +08005639 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005640 return RETURN_ERR;
5641 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005642 ret = _syscmd(cmd,macArray,buf_size);
5643 if (ret != 0)
5644 return RETURN_ERR;
5645
5646 return RETURN_OK;
5647}
5648
developere6aafda2022-09-13 14:59:28 +08005649INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5650{
developerd946fd62022-12-08 18:03:28 +08005651 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005652 char cmd[MAX_CMD_SIZE]={'\0'};
5653 int ret = 0;
5654
developerac6f1142022-12-20 19:26:35 +08005655 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005656 return RETURN_ERR;
5657 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005658 ret = _syscmd(cmd,macArray,buf_size);
5659 if (ret != 0)
5660 return RETURN_ERR;
5661
5662 return RETURN_OK;
5663}
5664
developer06a01d92022-09-07 16:32:39 +08005665// Get the list of stations associated per AP
5666INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5667{
developerd946fd62022-12-08 18:03:28 +08005668 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005669 char cmd[128];
5670
5671 if(apIndex > 3) //Currently supporting apIndex upto 3
5672 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08005673 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005674 return RETURN_ERR;
5675 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5676 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005677 _syscmd(cmd, macArray, buf_size);
5678
5679 return RETURN_OK;
5680}
5681
developer2f995fb2023-02-24 10:40:44 +08005682INT getAddressControlMode(INT apIndex, INT *mode)
5683{
5684 char buf [16] = {0};
5685 char config_file[64] = {0};
5686
5687 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5688 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
5689
5690 *mode = -1;
5691 // 0 use deny file, 1 use accept file
5692 if (strncmp(buf, "0", 1) == 0 || strncmp(buf, "1", 1) == 0)
5693 *mode = (INT)strtol(buf, NULL, 10);
5694
5695 return RETURN_OK;
5696}
5697
developer06a01d92022-09-07 16:32:39 +08005698// adds the mac address to the filter list
5699//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5700INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5701{
5702 char cmd[MAX_CMD_SIZE]={'\0'};
5703 char buf[MAX_BUF_SIZE]={'\0'};
5704
developer2f995fb2023-02-24 10:40:44 +08005705 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +08005706 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005707
developer06a01d92022-09-07 16:32:39 +08005708 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5709 if(_syscmd(cmd,buf,sizeof(buf)))
5710 return RETURN_ERR;
5711
5712 return RETURN_OK;
5713}
5714
developer2f995fb2023-02-24 10:40:44 +08005715INT wifi_addApDenyAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5716{
5717 char cmd[MAX_CMD_SIZE]={'\0'};
5718 char buf[MAX_BUF_SIZE]={'\0'};
5719
5720 if (wifi_delApAclDevice(apIndex, DeviceMacAddress) != RETURN_OK)
5721 return RETURN_ERR;
5722
5723 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5724 if(_syscmd(cmd,buf,sizeof(buf)))
5725 return RETURN_ERR;
5726
5727 return RETURN_OK;
5728}
5729
developer06a01d92022-09-07 16:32:39 +08005730// deletes the mac address from the filter list
5731//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5732INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5733{
5734 char cmd[MAX_CMD_SIZE]={'\0'};
5735 char buf[MAX_BUF_SIZE]={'\0'};
5736
5737#if 0
developerd946fd62022-12-08 18:03:28 +08005738 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005739 if(_syscmd(cmd,buf,sizeof(buf)))
5740 return RETURN_ERR;
5741
5742#endif
developer2f995fb2023-02-24 10:40:44 +08005743 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005744 if(_syscmd(cmd,buf,sizeof(buf)))
5745 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005746 sprintf(cmd, "sed -i '/%s/d' %s%d", DeviceMacAddress, DENY_PREFIX, apIndex);
5747 if(_syscmd(cmd,buf,sizeof(buf)))
5748 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005749
5750 return RETURN_OK;
5751}
5752
5753// outputs the number of devices in the filter list
5754INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5755{
developere6aafda2022-09-13 14:59:28 +08005756 char cmd[MAX_BUF_SIZE]={0};
5757 char buf[MAX_CMD_SIZE]={0};
developer2f995fb2023-02-24 10:40:44 +08005758 int mode = -1;
developere6aafda2022-09-13 14:59:28 +08005759
5760 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5761 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005762 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005763
developer2f995fb2023-02-24 10:40:44 +08005764 getAddressControlMode(apIndex, &mode);
5765 if (mode == -1)
5766 return RETURN_OK;
5767
5768 if (mode == 0)
5769 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", DENY_PREFIX, apIndex);
5770 else if (mode == 1)
5771 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
developere6aafda2022-09-13 14:59:28 +08005772 _syscmd(cmd, buf, sizeof(buf));
5773
developer2f995fb2023-02-24 10:40:44 +08005774 *output_uint = strtol(buf, NULL, 10);
developere6aafda2022-09-13 14:59:28 +08005775
5776 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5777 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005778}
5779
5780INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5781{
5782 char cmd[128]={'\0'};
5783 char buf[128]={'\0'};
5784
5785 if(strcmp(action,"DENY")==0)
5786 {
5787 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5788 system(buf);
5789 return RETURN_OK;
5790 }
5791
5792 if(strcmp(action,"ALLOW")==0)
5793 {
5794 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5795 system(buf);
5796 return RETURN_OK;
5797 }
5798
5799 return RETURN_ERR;
5800
5801}
5802
5803// enable kick for devices on acl black list
5804INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5805{
5806 char aclArray[512] = {0}, *acl = NULL;
5807 char assocArray[512] = {0}, *asso = NULL;
5808
developere6aafda2022-09-13 14:59:28 +08005809 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005810 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5811
5812 // if there are no devices connected there is nothing to do
5813 if (strlen(assocArray) < 17)
5814 return RETURN_OK;
5815
5816 if (enable == TRUE)
5817 {
5818 //kick off the MAC which is in ACL array (deny list)
5819 acl = strtok(aclArray, "\r\n");
5820 while (acl != NULL) {
5821 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5822 wifi_kickApAssociatedDevice(apIndex, acl);
5823
5824 acl = strtok(NULL, "\r\n");
5825 }
developere6aafda2022-09-13 14:59:28 +08005826 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005827 }
5828 else
5829 {
developere6aafda2022-09-13 14:59:28 +08005830 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005831 }
5832
5833#if 0
5834 //TODO: need to revisit below implementation
5835 char aclArray[512]={0}, *acl=NULL;
5836 char assocArray[512]={0}, *asso=NULL;
5837 char buf[256]={'\0'};
5838 char action[10]={'\0'};
5839 FILE *fr=NULL;
5840 char interface[10]={'\0'};
5841 char config_file[MAX_BUF_SIZE] = {0};
5842
5843 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5844 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5845 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5846 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5847
5848 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5849 system(buf);
5850 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5851 system(buf);
5852 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5853 system(buf);
5854 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5855 system(buf);
5856 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5857 system(buf);
5858
5859 if ( enable == TRUE )
5860 {
5861 int device_count=0;
5862 strcpy(action,"DENY");
5863 //kick off the MAC which is in ACL array (deny list)
5864 acl = strtok (aclArray,",");
5865 while (acl != NULL) {
5866 if(strlen(acl)>=17)
5867 {
5868 apply_rules(apIndex, acl,action,interface);
5869 device_count++;
5870 //Register mac to be blocked ,in syscfg.db persistent storage
5871 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5872 system(buf);
5873 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5874 system(buf);
5875 system("syscfg commit");
5876
5877 wifi_kickApAssociatedDevice(apIndex, acl);
5878 }
5879 acl = strtok (NULL, ",");
5880 }
5881 }
5882 else
5883 {
5884 int device_count=0;
5885 char cmdmac[20]={'\0'};
5886 strcpy(action,"ALLOW");
5887 //kick off the MAC which is not in ACL array (allow list)
5888 acl = strtok (aclArray,",");
5889 while (acl != NULL) {
5890 if(strlen(acl)>=17)
5891 {
5892 apply_rules(apIndex, acl,action,interface);
5893 device_count++;
5894 //Register mac to be Allowed ,in syscfg.db persistent storage
5895 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5896 system(buf);
5897 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5898 system(buf);
5899 sprintf(cmdmac,"%s",acl);
5900 }
5901 acl = strtok (NULL, ",");
5902 }
5903 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5904 system(buf);
5905
5906 //Disconnect the mac which is not in ACL
5907 asso = strtok (assocArray,",");
5908 while (asso != NULL) {
5909 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5910 wifi_kickApAssociatedDevice(apIndex, asso);
5911 asso = strtok (NULL, ",");
5912 }
5913 }
5914#endif
5915 return RETURN_OK;
5916}
5917
5918INT wifi_setPreferPrivateConnection(BOOL enable)
5919{
developer06a01d92022-09-07 16:32:39 +08005920 return RETURN_OK;
5921}
5922
5923// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5924INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5925{
developerd946fd62022-12-08 18:03:28 +08005926 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005927 int items = 1;
5928 struct params list[2];
5929 char buf[MAX_BUF_SIZE] = {0};
5930 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005931 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005932
5933 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005934
developer10adcc12022-09-13 14:39:17 +08005935 if (filterMode == 0) {
5936 sprintf(buf, "%d", 0);
5937 list[0].value = buf;
5938
developer2f995fb2023-02-24 10:40:44 +08005939 char cmd[128] = {0};
developerac6f1142022-12-20 19:26:35 +08005940 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08005941 return RETURN_ERR;
developer2f995fb2023-02-24 10:40:44 +08005942 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR 2> /dev/null", interface_name);
5943 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08005944 memset(cmd,0,sizeof(cmd));
5945 // Delete deny_mac_file in hostapd configuration
5946 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
developer2f995fb2023-02-24 10:40:44 +08005947 _syscmd(cmd, cmd, sizeof(cmd));
developer10adcc12022-09-13 14:39:17 +08005948 }
5949 else if (filterMode == 1) {
5950 sprintf(buf, "%d", filterMode);
5951 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005952 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5953 list[1].name = "accept_mac_file";
5954 list[1].value = acl_file;
5955 items = 2;
developer10adcc12022-09-13 14:39:17 +08005956 } else if (filterMode == 2) {
5957 //TODO: deny_mac_file
5958 sprintf(buf, "%d", 0);
5959 list[0].value = buf;
5960 list[1].name = "deny_mac_file";
5961 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5962 list[1].value = deny_file;
5963 items = 2;
5964 } else {
5965 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005966 }
developer10adcc12022-09-13 14:39:17 +08005967
developer06a01d92022-09-07 16:32:39 +08005968 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5969 wifi_hostapdWrite(config_file, list, items);
developer2f995fb2023-02-24 10:40:44 +08005970 if (multiple_set == FALSE) {
5971 wifi_setApEnable(apIndex, FALSE);
5972 wifi_setApEnable(apIndex, TRUE);
5973 }
developer06a01d92022-09-07 16:32:39 +08005974
5975 return RETURN_OK;
5976
5977#if 0
5978 if(apIndex==0 || apIndex==1)
5979 {
5980 //set the filtermode
5981 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5982 system(buf);
5983 system("syscfg commit");
5984
5985 if(filterMode==0)
5986 {
5987 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5988 system(buf);
5989 return RETURN_OK;
5990 }
5991 }
5992 return RETURN_OK;
5993#endif
5994}
5995
5996// 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.
5997INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5998{
5999 return RETURN_ERR;
6000}
6001
6002// gets the vlan ID for this ap from an internal enviornment variable
6003INT wifi_getApVlanID(INT apIndex, INT *output_int)
6004{
developer30423732022-12-01 16:17:49 +08006005 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08006006 {
6007 *output_int=100;
6008 return RETURN_OK;
6009 }
6010
6011 return RETURN_ERR;
6012}
6013
6014// sets the vlan ID for this ap to an internal enviornment variable
6015INT wifi_setApVlanID(INT apIndex, INT vlanId)
6016{
6017 //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)
6018 return RETURN_ERR;
6019}
6020
6021// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6022INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6023{
6024 snprintf(bridgeName, 32, "brlan0");
6025 snprintf(IP, 32, "10.0.0.1");
6026 snprintf(subnet, 32, "255.255.255.0");
6027
6028 return RETURN_OK;
6029}
6030
6031//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6032INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6033{
6034 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6035 return RETURN_ERR;
6036}
6037
6038// reset the vlan configuration for this ap
6039INT wifi_resetApVlanCfg(INT apIndex)
6040{
developerf5fef612022-09-20 19:38:26 +08006041 char original_config_file[64] = {0};
6042 char current_config_file[64] = {0};
6043 char buf[64] = {0};
6044 char cmd[64] = {0};
6045 char vlan_file[64] = {0};
6046 char vlan_tagged_interface[16] = {0};
6047 char vlan_bridge[16] = {0};
6048 char vlan_naming[16] = {0};
6049 struct params list[4] = {0};
6050 wifi_band band;
6051
6052 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6053
6054 band = wifi_index_to_band(apIndex);
6055 if (band == band_2_4)
6056 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006057 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08006058 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006059 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08006060 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6061
6062 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6063
6064 if (strlen(vlan_file) == 0)
6065 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08006066
developerf5fef612022-09-20 19:38:26 +08006067 // The file should exist or this vap would not work.
6068 if (access(vlan_file, F_OK) != 0) {
6069 sprintf(cmd, "touch %s", vlan_file);
6070 _syscmd(cmd, buf, sizeof(buf));
6071 }
6072 list[0].name = "vlan_file";
6073 list[0].value = vlan_file;
6074
6075 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6076 list[1].name = "vlan_tagged_interface";
6077 list[1].value = vlan_tagged_interface;
6078
6079 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6080 list[2].name = "vlan_bridge";
6081 list[2].value = vlan_bridge;
6082
6083 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6084 list[3].name = "vlan_naming";
6085 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08006086
developerf5fef612022-09-20 19:38:26 +08006087 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6088 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08006089 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08006090 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08006091
developerf5fef612022-09-20 19:38:26 +08006092 // restart this ap
6093 wifi_setApEnable(apIndex, FALSE);
6094 wifi_setApEnable(apIndex, TRUE);
6095
6096 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6097
6098 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006099}
6100
6101// 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.
6102INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6103{
6104 return RETURN_ERR;
6105}
6106
6107// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6108INT wifi_startHostApd()
6109{
6110 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6111 system("systemctl start hostapd.service");
6112 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6113 return RETURN_OK;
6114 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6115}
6116
6117// stops hostapd
6118INT wifi_stopHostApd()
6119{
6120 char cmd[128] = {0};
6121 char buf[128] = {0};
6122
6123 sprintf(cmd,"systemctl stop hostapd");
6124 _syscmd(cmd, buf, sizeof(buf));
6125
6126 return RETURN_OK;
6127}
6128
6129// restart hostapd dummy function
6130INT wifi_restartHostApd()
6131{
6132 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6133 system("systemctl restart hostapd-global");
6134 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6135
6136 return RETURN_OK;
6137}
6138
6139static int align_hostapd_config(int index)
6140{
6141 ULONG lval;
6142 wifi_getRadioChannel(index%2, &lval);
6143 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08006144 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006145}
6146
6147// sets the AP enable status variable for the specified ap.
6148INT wifi_setApEnable(INT apIndex, BOOL enable)
6149{
developerd946fd62022-12-08 18:03:28 +08006150 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006151 char config_file[MAX_BUF_SIZE] = {0};
6152 char cmd[MAX_CMD_SIZE] = {0};
6153 char buf[MAX_BUF_SIZE] = {0};
6154 BOOL status;
developer033b37b2022-10-18 11:27:46 +08006155 int max_radio_num = 0;
6156 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08006157
6158 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08006159
6160 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08006161 if (enable == status)
6162 return RETURN_OK;
6163
developerac6f1142022-12-20 19:26:35 +08006164 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006165 return RETURN_ERR;
6166
developer06a01d92022-09-07 16:32:39 +08006167 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08006168 int radioIndex = apIndex % max_radio_num;
6169 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08006170 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6171 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08006172 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006173 _syscmd(cmd, buf, sizeof(buf));
developer2f18b9f2023-03-17 19:32:57 +08006174 if (!(apIndex/max_radio_num)) {
6175 sprintf(cmd, "iw %s del", interface_name);
6176 _syscmd(cmd, buf, sizeof(buf));
6177 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6178 _syscmd(cmd, buf, sizeof(buf));
6179 }
developer033b37b2022-10-18 11:27:46 +08006180 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08006181 _syscmd(cmd, buf, sizeof(buf));
6182 }
6183 else {
developerd946fd62022-12-08 18:03:28 +08006184 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08006185 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08006186 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08006187 _syscmd(cmd, buf, sizeof(buf));
6188 }
developera77d84b2023-02-22 16:10:50 +08006189
developer431128d2022-12-16 15:30:41 +08006190 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08006191 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08006192 _syscmd(cmd, buf, sizeof(buf));
6193 //Wait for wifi up/down to apply
6194 return RETURN_OK;
6195}
6196
6197// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6198INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6199{
developerd946fd62022-12-08 18:03:28 +08006200 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006201 char cmd[MAX_CMD_SIZE] = {'\0'};
6202 char buf[MAX_BUF_SIZE] = {'\0'};
6203
6204 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6205 return RETURN_ERR;
6206
6207 *output_bool = 0;
6208
6209 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6210 {
developerac6f1142022-12-20 19:26:35 +08006211 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
developerd946fd62022-12-08 18:03:28 +08006212 *output_bool = FALSE;
6213 return RETURN_OK;
6214 }
6215 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08006216 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6217 }
6218
6219 return RETURN_OK;
6220}
6221
6222// Outputs the AP "Enabled" "Disabled" status from driver
6223INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6224{
6225 char cmd[128] = {0};
6226 char buf[128] = {0};
6227 BOOL output_bool;
6228
6229 if ( NULL == output_string)
6230 return RETURN_ERR;
6231 wifi_getApEnable(apIndex,&output_bool);
6232
6233 if(output_bool == 1)
6234 snprintf(output_string, 32, "Up");
6235 else
6236 snprintf(output_string, 32, "Disable");
6237
6238 return RETURN_OK;
6239}
6240
6241//Indicates whether or not beacons include the SSID name.
6242// outputs a 1 if SSID on the AP is enabled, else outputs 0
6243INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6244{
6245 //get the running status
6246 char config_file[MAX_BUF_SIZE] = {0};
6247 char buf[16] = {0};
6248
6249 if (!output)
6250 return RETURN_ERR;
6251
6252 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6253 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006254 // default is enable
6255 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6256 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08006257
6258 return RETURN_OK;
6259}
6260
6261// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6262INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6263{
6264 //store the config, apply instantly
6265 char config_file[MAX_BUF_SIZE] = {0};
6266 struct params list;
6267
6268 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6269 list.name = "ignore_broadcast_ssid";
6270 list.value = enable?"0":"1";
6271
6272 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6273 wifi_hostapdWrite(config_file, &list, 1);
6274 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6275 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08006276 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08006277 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6278
6279 return RETURN_OK;
6280}
6281
6282//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6283INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6284{
6285 //get the running status
6286 if(!output_uint)
6287 return RETURN_ERR;
6288 *output_uint=16;
6289 return RETURN_OK;
6290}
6291
6292INT wifi_setApRetryLimit(INT apIndex, UINT number)
6293{
6294 //apply instantly
6295 return RETURN_ERR;
6296}
6297
6298//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6299INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6300{
6301 if(!output)
6302 return RETURN_ERR;
6303 *output=TRUE;
6304 return RETURN_OK;
6305}
6306
6307//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6308INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6309{
6310 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006311 char cmd[128] = {0};
6312 char buf[128] = {0};
6313 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006314 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006315
developer0b246d12022-09-30 15:24:20 +08006316 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006317
developer0b246d12022-09-30 15:24:20 +08006318 wifi_getMaxRadioNumber(&max_radio_num);
6319 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006320 phyId = radio_index_to_phy(radioIndex);
6321 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006322 _syscmd(cmd,buf, sizeof(buf));
6323
6324 if (strlen(buf) > 0)
6325 *output = true;
6326
6327 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006328
developer06a01d92022-09-07 16:32:39 +08006329 return RETURN_OK;
6330}
6331
6332//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6333INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6334{
6335 //get the running status from driver
6336 if(!output)
6337 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006338
6339 char config_file[MAX_BUF_SIZE] = {0};
6340 char buf[16] = {0};
6341
6342 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6343 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006344 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006345 *output = TRUE;
6346 else
6347 *output = FALSE;
6348
developer06a01d92022-09-07 16:32:39 +08006349 return RETURN_OK;
6350}
6351
6352// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6353INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6354{
6355 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006356 char config_file[MAX_BUF_SIZE] = {0};
6357 struct params list;
6358
6359 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6360 list.name = "wmm_enabled";
6361 list.value = enable?"1":"0";
6362
6363 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6364 wifi_hostapdWrite(config_file, &list, 1);
6365 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6366 wifi_reloadAp(apIndex);
6367 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6368
6369 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006370}
6371
6372//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.
6373INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6374{
6375 //get the running status from driver
6376 if(!output)
6377 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006378
6379 char config_file[128] = {0};
6380 char buf[16] = {0};
6381
6382 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6383 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6384 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6385 *output = TRUE;
6386 else
6387 *output = FALSE;
6388
developer06a01d92022-09-07 16:32:39 +08006389 return RETURN_OK;
6390}
6391
6392// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6393INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6394{
6395 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006396 char config_file[MAX_BUF_SIZE] = {0};
6397 struct params list;
6398
6399 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6400 list.name = "uapsd_advertisement_enabled";
6401 list.value = enable?"1":"0";
6402
6403 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6404 wifi_hostapdWrite(config_file, &list, 1);
6405 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6406 wifi_reloadAp(apIndex);
6407 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6408
6409 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006410}
6411
developer6daeb3f2022-09-30 13:36:39 +08006412// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006413INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6414{
developerd946fd62022-12-08 18:03:28 +08006415 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006416 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6417 char cmd[128] = {0};
6418 char buf[128] = {0};
6419 char ack_filepath[128] = {0};
6420 uint16_t bitmap = 0;
6421 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6422 FILE *f = NULL;
6423
6424 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6425
6426 // Get current setting
6427 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6428 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6429 _syscmd(cmd, buf, sizeof(buf));
6430 if (strlen(buf) > 0)
6431 bitmap = strtoul(buf, NULL, 10);
6432
6433 bitmap = strtoul(buf, NULL, 10);
6434
6435 if (ackPolicy == TRUE) { // True, unset this class
6436 bitmap &= ~class_map[class];
6437 } else { // False, set this class
6438 bitmap |= class_map[class];
6439 }
6440
6441 f = fopen(ack_filepath, "w");
6442 if (f == NULL) {
6443 fprintf(stderr, "%s: fopen failed\n", __func__);
6444 return RETURN_ERR;
6445 }
6446 fprintf(f, "%hu", bitmap);
6447 fclose(f);
6448
developerac6f1142022-12-20 19:26:35 +08006449 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08006450 return RETURN_ERR;
6451 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006452 _syscmd(cmd, buf, sizeof(buf));
6453
6454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6455 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006456}
6457
6458//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.
6459INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6460{
6461 //get the running status from driver
6462 if(!output_uint)
6463 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006464
6465 char output[16]={'\0'};
6466 char config_file[MAX_BUF_SIZE] = {0};
6467
6468 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6469 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6470 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6471 else {
6472 int device_num = atoi(output);
6473 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6474 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6475 return RETURN_ERR;
6476 }
6477 else {
6478 *output_uint = device_num;
6479 }
6480 }
6481
developer06a01d92022-09-07 16:32:39 +08006482 return RETURN_OK;
6483}
6484
6485INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6486{
6487 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006488 char str[MAX_BUF_SIZE]={'\0'};
6489 char cmd[MAX_CMD_SIZE]={'\0'};
6490 struct params params;
6491 char config_file[MAX_BUF_SIZE] = {0};
6492
6493 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006494 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006495 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
developer72ec5572023-01-05 16:27:13 +08006496 return RETURN_OK;
developer0947e1a2022-09-13 14:15:25 +08006497 }
6498 sprintf(str, "%d", number);
6499 params.name = "max_num_sta";
6500 params.value = str;
6501
6502 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6503 int ret = wifi_hostapdWrite(config_file, &params, 1);
6504 if (ret) {
6505 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6506 ,__func__, ret);
6507 }
6508
6509 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6510 if (ret) {
6511 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6512 ,__func__, ret);
6513 }
6514 wifi_reloadAp(apIndex);
6515 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6516
6517 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006518}
6519
6520//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.
6521INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6522{
6523 //get the current threshold
6524 if(!output_uint)
6525 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006526 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6527 if (*output_uint == 0)
6528 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006529 return RETURN_OK;
6530}
6531
6532INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6533{
6534 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006535 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6536 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006537 return RETURN_ERR;
6538}
6539
6540//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.
6541INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6542{
6543 if(!output_uint)
6544 return RETURN_ERR;
6545 *output_uint = 3;
6546 return RETURN_OK;
6547}
6548
6549//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6550INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6551{
6552 if(!output_uint)
6553 return RETURN_ERR;
6554 *output_uint = 3;
6555 return RETURN_OK;
6556}
6557
6558//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.
6559INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6560{
6561 if(!output_in_seconds)
6562 return RETURN_ERR;
6563 *output_in_seconds = 0;
6564 return RETURN_OK;
6565}
6566
6567//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
6568INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6569{
6570 if(!output || apIndex>=MAX_APS)
6571 return RETURN_ERR;
6572 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006573 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006574 return RETURN_OK;
6575}
6576
6577//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6578INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6579{
developer587c1b62022-09-27 15:58:59 +08006580 char config_file[128] = {0};
6581 char wpa[16] = {0};
6582 char key_mgmt[64] = {0};
6583 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006584 if (!output)
6585 return RETURN_ERR;
6586
6587 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006588 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006589
developer587c1b62022-09-27 15:58:59 +08006590 strcpy(output, "None");//Copying "None" to output string for default case
6591 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006592 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006593 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006594 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006595 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006596 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006597 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006598 snprintf(output, 32, "WPA-WPA2-Personal");
6599
developer72ec5572023-01-05 16:27:13 +08006600 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6601 snprintf(output, 32, "WPA3-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006602 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006603 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006604 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006605 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006606 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006607 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006608 snprintf(output, 32, "WPA-WPA2-Enterprise");
6609 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006610 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006611 snprintf(output, 32, "WPA3-Personal");
6612 else
developer4a359672022-10-13 15:30:46 +08006613 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006614 }
developer06a01d92022-09-07 16:32:39 +08006615
6616 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6617 return RETURN_OK;
6618#if 0
6619 //TODO: need to revisit below implementation
6620 char securityType[32], authMode[32];
6621 int enterpriseMode=0;
6622
6623 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6624 if(!output)
6625 return RETURN_ERR;
6626
6627 wifi_getApBeaconType(apIndex, securityType);
6628 strcpy(output,"None");//By default, copying "None" to output string
6629 if (strncmp(securityType,"None", strlen("None")) == 0)
6630 return RETURN_OK;
6631
6632 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6633 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6634
6635 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6636 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6637 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6638 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6639 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6640 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6642
6643 return RETURN_OK;
6644#endif
6645}
6646
6647INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6648{
6649 char securityType[32];
6650 char authMode[32];
6651
6652 //store settings and wait for wifi up to apply
6653 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6654 if(!encMode)
6655 return RETURN_ERR;
6656
developer06a01d92022-09-07 16:32:39 +08006657 if (strcmp(encMode, "None")==0)
6658 {
6659 strcpy(securityType,"None");
6660 strcpy(authMode,"None");
6661 }
6662 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6663 {
6664 strcpy(securityType,"WPAand11i");
6665 strcpy(authMode,"PSKAuthentication");
6666 }
6667 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6668 {
6669 strcpy(securityType,"WPAand11i");
6670 strcpy(authMode,"EAPAuthentication");
6671 }
6672 else if (strcmp(encMode, "WPA-Personal")==0)
6673 {
6674 strcpy(securityType,"WPA");
6675 strcpy(authMode,"PSKAuthentication");
6676 }
6677 else if (strcmp(encMode, "WPA-Enterprise")==0)
6678 {
6679 strcpy(securityType,"WPA");
6680 strcpy(authMode,"EAPAuthentication");
6681 }
6682 else if (strcmp(encMode, "WPA2-Personal")==0)
6683 {
6684 strcpy(securityType,"11i");
6685 strcpy(authMode,"PSKAuthentication");
6686 }
6687 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6688 {
6689 strcpy(securityType,"11i");
6690 strcpy(authMode,"EAPAuthentication");
6691 }
developer587c1b62022-09-27 15:58:59 +08006692 else if (strcmp(encMode, "WPA3-Personal") == 0)
6693 {
6694 strcpy(securityType,"11i");
6695 strcpy(authMode,"SAEAuthentication");
6696 }
developer4a359672022-10-13 15:30:46 +08006697 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006698 {
6699 strcpy(securityType, "11i");
6700 strcpy(authMode, "PSK-SAEAuthentication");
6701 }
developer587c1b62022-09-27 15:58:59 +08006702 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6703 {
6704 strcpy(securityType,"11i");
6705 strcpy(authMode,"EAP_192-bit_Authentication");
6706 }
developer5c9fee82023-01-13 14:44:16 +08006707 else if (strcmp(encMode, "OWE") == 0)
6708 {
6709 strcpy(securityType,"11i");
6710 strcpy(authMode,"Enhanced_Open");
6711 }
developer06a01d92022-09-07 16:32:39 +08006712 else
6713 {
6714 strcpy(securityType,"None");
6715 strcpy(authMode,"None");
6716 }
6717 wifi_setApBeaconType(apIndex, securityType);
6718 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6719 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6720
6721 return RETURN_OK;
6722}
6723
6724
developer4b102122023-02-15 10:53:03 +08006725// Get PreSharedKey associated with a Access Point.
developer06a01d92022-09-07 16:32:39 +08006726//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006727INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6728{
developer30423732022-12-01 16:17:49 +08006729 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006730 char config_file[MAX_BUF_SIZE] = {0};
6731
6732 if(output_string==NULL)
6733 return RETURN_ERR;
6734
6735 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6736 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6737
6738 if(strcmp(buf,"0")==0)
6739 {
6740 printf("wpa_mode is %s ......... \n",buf);
6741 return RETURN_ERR;
6742 }
6743
6744 wifi_dbg_printf("\nFunc=%s\n",__func__);
6745 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developer4b102122023-02-15 10:53:03 +08006746 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer06a01d92022-09-07 16:32:39 +08006747 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6748
6749 return RETURN_OK;
6750}
6751
developer4b102122023-02-15 10:53:03 +08006752// Set PreSharedKey associated with a Access Point.
6753// A literal PreSharedKey (PSK) expressed as a hexadecimal string.
developer06a01d92022-09-07 16:32:39 +08006754INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6755{
6756 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6757 struct params params={'\0'};
6758 int ret;
6759 char config_file[MAX_BUF_SIZE] = {0};
6760
6761 if(NULL == preSharedKey)
6762 return RETURN_ERR;
6763
developer4b102122023-02-15 10:53:03 +08006764 params.name = "wpa_psk";
developer06a01d92022-09-07 16:32:39 +08006765
developer4b102122023-02-15 10:53:03 +08006766 if(strlen(preSharedKey) != 64)
developer06a01d92022-09-07 16:32:39 +08006767 {
developer4b102122023-02-15 10:53:03 +08006768 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer06a01d92022-09-07 16:32:39 +08006769 return RETURN_ERR;
6770 }
6771 params.value = preSharedKey;
6772 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6773 ret = wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +08006774 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006775 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006776 wifi_reloadAp(apIndex);
6777 }
developer06a01d92022-09-07 16:32:39 +08006778 return ret;
6779 //TODO: call hostapd_cli for dynamic_config_control
6780}
6781
6782//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6783// outputs the passphrase, maximum 63 characters
6784INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6785{
6786 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6787
6788 wifi_dbg_printf("\nFunc=%s\n",__func__);
6789 if (NULL == output_string)
6790 return RETURN_ERR;
6791
6792 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6793 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6794 if(strcmp(buf,"0")==0)
6795 {
6796 printf("wpa_mode is %s ......... \n",buf);
6797 return RETURN_ERR;
6798 }
6799
6800 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6801 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6802
6803 return RETURN_OK;
6804}
6805
6806// sets the passphrase enviornment variable, max 63 characters
6807INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6808{
6809 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6810 struct params params={'\0'};
6811 char config_file[MAX_BUF_SIZE] = {0};
6812 int ret;
6813
6814 if(NULL == passPhrase)
6815 return RETURN_ERR;
6816
6817 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6818 {
6819 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6820 return RETURN_ERR;
6821 }
6822 params.name = "wpa_passphrase";
6823 params.value = passPhrase;
6824 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6825 ret=wifi_hostapdWrite(config_file,&params,1);
developer4b102122023-02-15 10:53:03 +08006826 if(!ret) {
developer06a01d92022-09-07 16:32:39 +08006827 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developer4b102122023-02-15 10:53:03 +08006828 wifi_reloadAp(apIndex);
6829 }
developer06a01d92022-09-07 16:32:39 +08006830
6831 return ret;
6832}
6833
6834//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.
6835INT wifi_setApSecurityReset(INT apIndex)
6836{
developer8d583982022-09-20 11:28:22 +08006837 char original_config_file[64] = {0};
6838 char current_config_file[64] = {0};
6839 char buf[64] = {0};
6840 char cmd[64] = {0};
6841 char wpa[4] = {0};
6842 char wpa_psk[64] = {0};
6843 char wpa_passphrase[64] = {0};
6844 char wpa_psk_file[128] = {0};
6845 char wpa_key_mgmt[64] = {0};
6846 char wpa_pairwise[32] = {0};
6847 wifi_band band;
6848 struct params list[6];
6849
6850 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6851
6852 band = wifi_index_to_band(apIndex);
6853 if (band == band_2_4)
6854 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006855 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006856 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006857 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006858 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6859 else
6860 return RETURN_ERR;
6861
6862 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6863 list[0].name = "wpa";
6864 list[0].value = wpa;
6865
6866 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6867 list[1].name = "wpa_psk";
6868 list[1].value = wpa_psk;
6869
6870 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6871 list[2].name = "wpa_passphrase";
6872 list[2].value = wpa_passphrase;
6873
6874 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6875
6876 if (strlen(wpa_psk_file) == 0)
6877 strcpy(wpa_psk_file, PSK_FILE);
6878
6879 if (access(wpa_psk_file, F_OK) != 0) {
6880 sprintf(cmd, "touch %s", wpa_psk_file);
6881 _syscmd(cmd, buf, sizeof(buf));
6882 }
6883 list[3].name = "wpa_psk_file";
6884 list[3].value = wpa_psk_file;
6885
6886 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6887 list[4].name = "wpa_key_mgmt";
6888 list[4].value = wpa_key_mgmt;
6889
6890 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6891 list[5].name = "wpa_pairwise";
6892 list[5].value = wpa_pairwise;
6893
6894 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6895 wifi_hostapdWrite(current_config_file, list, 6);
6896
6897 wifi_setApEnable(apIndex, FALSE);
6898 wifi_setApEnable(apIndex, TRUE);
6899
6900 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6901 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006902}
6903
6904//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).
6905INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6906{
developer8f2ddd52022-09-13 15:39:24 +08006907 char config_file[64] = {0};
6908 char buf[64] = {0};
6909 char cmd[256] = {0};
6910
6911 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6912
developer06a01d92022-09-07 16:32:39 +08006913 if(!IP_output || !Port_output || !RadiusSecret_output)
6914 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006915
developer8f2ddd52022-09-13 15:39:24 +08006916 // Read the first matched config
6917 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6918 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6919 _syscmd(cmd, buf, sizeof(buf));
6920 strncpy(IP_output, buf, 64);
6921
6922 memset(buf, 0, sizeof(buf));
6923 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6924 _syscmd(cmd, buf, sizeof(buf));
6925 *Port_output = atoi(buf);
6926
6927 memset(buf, 0, sizeof(buf));
6928 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6929 _syscmd(cmd, buf, sizeof(buf));
6930 strncpy(RadiusSecret_output, buf, 64);
6931
6932 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006933 return RETURN_OK;
6934}
6935
6936INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6937{
developer8f2ddd52022-09-13 15:39:24 +08006938 char config_file[64] = {0};
6939 char port_str[8] = {0};
6940 char cmd[256] = {0};
6941 char buf[128] = {0};
6942
6943 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08006944 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
6945 return RETURN_ERR;
6946
6947 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
6948 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006949
6950 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6951
6952 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6953 _syscmd(cmd, buf, sizeof(buf));
6954 memset(cmd, 0, sizeof(cmd));
6955
6956 snprintf(port_str, sizeof(port_str), "%d", port);
6957 if (strlen(buf) == 0)
6958 // Append
6959 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6960 "auth_server_addr=%s\\n"
6961 "auth_server_port=%s\\n"
6962 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6963 else {
6964 // Delete the three lines setting after the "# radius 1" comment
6965 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6966 _syscmd(cmd, buf, sizeof(buf));
6967 memset(cmd, 0, sizeof(cmd));
6968 // Use "# radius 1" comment to find the location to insert the radius setting
6969 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6970 "# radius 1\\n"
6971 "auth_server_addr=%s\\n"
6972 "auth_server_port=%s\\n"
6973 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6974 }
6975 if(_syscmd(cmd, buf, sizeof(buf))) {
6976 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6977 return RETURN_ERR;
6978 }
6979
6980 wifi_reloadAp(apIndex);
6981 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6982 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006983}
6984
6985INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6986{
developer8f2ddd52022-09-13 15:39:24 +08006987 char config_file[64] = {0};
6988 char buf[64] = {0};
6989 char cmd[256] = {0};
6990
6991 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6992
developer06a01d92022-09-07 16:32:39 +08006993 if(!IP_output || !Port_output || !RadiusSecret_output)
6994 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006995
6996 // Read the second matched config
6997 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6998 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6999 _syscmd(cmd, buf, sizeof(buf));
7000 strncpy(IP_output, buf, 64);
7001
7002 memset(buf, 0, sizeof(buf));
7003 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7004 _syscmd(cmd, buf, sizeof(buf));
7005 *Port_output = atoi(buf);
7006
7007 memset(buf, 0, sizeof(buf));
7008 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7009 _syscmd(cmd, buf, sizeof(buf));
7010 strncpy(RadiusSecret_output, buf, 64);
7011
7012 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007013 return RETURN_OK;
7014}
7015
7016INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7017{
developer8f2ddd52022-09-13 15:39:24 +08007018 char config_file[64] = {0};
7019 char port_str[8] = {0};
7020 char cmd[256] = {0};
7021 char buf[128] = {0};
7022
7023 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer4b102122023-02-15 10:53:03 +08007024 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7025 return RETURN_ERR;
7026
7027 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7028 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08007029
7030 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7031
7032 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7033 _syscmd(cmd, buf, sizeof(buf));
7034 memset(cmd, 0, sizeof(cmd));
7035
7036 snprintf(port_str, sizeof(port_str), "%d", port);
7037 if (strlen(buf) == 0)
7038 // Append
7039 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7040 "auth_server_addr=%s\\n"
7041 "auth_server_port=%s\\n"
7042 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7043 else {
7044 // Delete the three lines setting after the "# radius 2" comment
7045 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7046 _syscmd(cmd, buf, sizeof(buf));
7047 memset(cmd, 0, sizeof(cmd));
7048 // Use "# radius 2" comment to find the location to insert the radius setting
7049 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7050 "# radius 2\\n"
7051 "auth_server_addr=%s\\n"
7052 "auth_server_port=%s\\n"
7053 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7054 }
7055 if(_syscmd(cmd, buf, sizeof(buf))) {
7056 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7057 return RETURN_ERR;
7058 }
7059
7060 wifi_reloadAp(apIndex);
7061 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7062 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08007063}
7064
7065//RadiusSettings
7066INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7067{
7068 if(!output)
7069 return RETURN_ERR;
7070
7071 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7072 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7073 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7074 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7075 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7076 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.
7077 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7078 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7079 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7080 //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.
7081
7082 return RETURN_OK;
7083}
7084
7085INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7086{
7087 //store the paramters, and apply instantly
7088 return RETURN_ERR;
7089}
7090
7091//Device.WiFi.AccessPoint.{i}.WPS.Enable
7092//Enables or disables WPS functionality for this access point.
7093// outputs the WPS enable state of this ap in output_bool
7094INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7095{
developerd946fd62022-12-08 18:03:28 +08007096 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007097 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer5b398df2022-11-17 20:39:48 +08007098 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08007099 return RETURN_ERR;
developerac6f1142022-12-20 19:26:35 +08007100 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007101 return RETURN_ERR;
7102 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007103 _syscmd(cmd, buf, sizeof(buf));
7104 if(strstr(buf, "configured"))
7105 *output_bool=TRUE;
7106 else
7107 *output_bool=FALSE;
7108
7109 return RETURN_OK;
7110}
7111
7112//Device.WiFi.AccessPoint.{i}.WPS.Enable
7113// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7114INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7115{
7116 char config_file[MAX_BUF_SIZE] = {0};
developer72ec5572023-01-05 16:27:13 +08007117 char buf[128] = {0};
developer06a01d92022-09-07 16:32:39 +08007118 struct params params;
7119
developer06a01d92022-09-07 16:32:39 +08007120 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7121 //store the paramters, and wait for wifi up to apply
7122 params.name = "wps_state";
developer72ec5572023-01-05 16:27:13 +08007123 if (enable == TRUE) {
7124 wifi_getApBeaconType(apIndex, buf);
7125 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7126 params.value = "1";
7127 else // If ap set encryption
7128 params.value = "2";
7129 } else {
7130 params.value = "0";
7131 }
developer06a01d92022-09-07 16:32:39 +08007132
7133 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7134 wifi_hostapdWrite(config_file, &params, 1);
7135 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7136 wifi_reloadAp(apIndex);
7137
7138 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7139 return RETURN_OK;
7140}
7141
7142//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
7143INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7144{
7145 if(!output)
7146 return RETURN_ERR;
7147 snprintf(output, 128, "PushButton,PIN");
7148 return RETURN_OK;
7149}
7150
7151//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7152//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.
7153// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7154INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7155{
7156 if(!output)
7157 return RETURN_ERR;
7158 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7159
7160 return RETURN_OK;
7161}
7162
7163//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7164// 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
7165INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7166{
7167 //apply instantly. No setting need to be stored.
7168 char methods[MAX_BUF_SIZE], *token, *next_token;
7169 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7170 struct params params;
7171
developer5b398df2022-11-17 20:39:48 +08007172 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08007173 return RETURN_ERR;
7174 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7175 //store the paramters, and wait for wifi up to apply
7176
7177 snprintf(methods, sizeof(methods), "%s", methodString);
7178 for(token=methods; *token; token=next_token)
7179 {
7180 strtok_r(token, ",", &next_token);
7181 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7182 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7183 else if(*token=='E')
7184 {
7185 if(!strcmp(methods, "Ethernet"))
7186 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7187 else if(!strcmp(methods, "ExternalNFCToken"))
7188 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7189 else
7190 printf("%s: Unknown WpsConfigMethod\n", __func__);
7191 }
7192 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7193 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7194 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7195 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7196 else if(*token=='P' )
7197 {
7198 if(!strcmp(token, "PushButton"))
7199 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
7200 else if(!strcmp(token, "PIN"))
7201 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7202 else
7203 printf("%s: Unknown WpsConfigMethod\n", __func__);
7204 }
7205 else
7206 printf("%s: Unknown WpsConfigMethod\n", __func__);
7207 }
7208 params.name = "config_methods";
7209 params.value = config_methods;
7210 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7211 wifi_hostapdWrite(config_file, &params, 1);
7212 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7213 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7214
7215 return RETURN_OK;
7216}
7217
7218// outputs the pin value, ulong_pin must be allocated by the caller
7219INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7220{
7221 char buf[MAX_BUF_SIZE] = {0};
7222 char cmd[MAX_CMD_SIZE] = {0};
7223
developer5b398df2022-11-17 20:39:48 +08007224 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08007225 return RETURN_ERR;
7226 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7227 _syscmd(cmd, buf, sizeof(buf));
7228 if(strlen(buf) > 0)
7229 *output_ulong=strtoul(buf, NULL, 10);
7230
7231 return RETURN_OK;
7232}
7233
7234// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7235INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7236{
7237 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7238 char ap_pin[16] = {0};
7239 char buf[MAX_BUF_SIZE] = {0};
7240 char config_file[MAX_BUF_SIZE] = {0};
7241 ULONG prev_pin = 0;
7242 struct params params;
7243
developer06a01d92022-09-07 16:32:39 +08007244 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7245 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7246 params.name = "ap_pin";
7247 params.value = ap_pin;
7248 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7249 wifi_hostapdWrite(config_file, &params, 1);
7250 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7251 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7252
7253 return RETURN_OK;
7254}
7255
7256// Output string is either Not configured or Configured, max 32 characters
7257INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7258{
developerd946fd62022-12-08 18:03:28 +08007259 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007260 char cmd[MAX_CMD_SIZE];
7261 char buf[MAX_BUF_SIZE]={0};
7262
developer5b398df2022-11-17 20:39:48 +08007263 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08007264 return RETURN_ERR;
7265 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7266 snprintf(output_string, 32, "Not configured");
developerac6f1142022-12-20 19:26:35 +08007267 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007268 return RETURN_ERR;
7269 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08007270 _syscmd(cmd, buf, sizeof(buf));
7271
developer348e3d92022-09-13 14:48:41 +08007272 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08007273 snprintf(output_string, 32, "Configured");
7274 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7275
7276 return RETURN_OK;
7277}
7278
7279// sets the WPS pin for this AP
7280INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7281{
developerd946fd62022-12-08 18:03:28 +08007282 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007283 char cmd[MAX_CMD_SIZE];
7284 char buf[MAX_BUF_SIZE]={0};
7285 BOOL enable;
7286
developer06a01d92022-09-07 16:32:39 +08007287 wifi_getApEnable(apIndex, &enable);
7288 if (!enable)
7289 return RETURN_ERR;
7290 wifi_getApWpsEnable(apIndex, &enable);
7291 if (!enable)
7292 return RETURN_ERR;
7293
developerac6f1142022-12-20 19:26:35 +08007294 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007295 return RETURN_ERR;
7296 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08007297 _syscmd(cmd, buf, sizeof(buf));
7298 if((strstr(buf, "OK"))!=NULL)
7299 return RETURN_OK;
7300
7301 return RETURN_ERR;
7302}
7303
7304// This function is called when the WPS push button has been pressed for this AP
7305INT wifi_setApWpsButtonPush(INT apIndex)
7306{
7307 char cmd[MAX_CMD_SIZE];
7308 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08007309 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007310 BOOL enable=FALSE;
7311
developer06a01d92022-09-07 16:32:39 +08007312 wifi_getApEnable(apIndex, &enable);
7313 if (!enable)
7314 return RETURN_ERR;
7315
7316 wifi_getApWpsEnable(apIndex, &enable);
7317 if (!enable)
7318 return RETURN_ERR;
7319
developerac6f1142022-12-20 19:26:35 +08007320 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007321 return RETURN_ERR;
7322
7323 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
developer06a01d92022-09-07 16:32:39 +08007324 _syscmd(cmd, buf, sizeof(buf));
7325
7326 if((strstr(buf, "OK"))!=NULL)
7327 return RETURN_OK;
7328 return RETURN_ERR;
7329}
7330
7331// cancels WPS mode for this AP
7332INT wifi_cancelApWPS(INT apIndex)
7333{
developerd946fd62022-12-08 18:03:28 +08007334 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007335 char cmd[MAX_CMD_SIZE];
7336 char buf[MAX_BUF_SIZE]={0};
7337
developerac6f1142022-12-20 19:26:35 +08007338 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007339 return RETURN_ERR;
7340 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007341 _syscmd(cmd,buf, sizeof(buf));
7342
7343 if((strstr(buf, "OK"))!=NULL)
7344 return RETURN_OK;
7345 return RETURN_ERR;
7346}
7347
7348//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7349//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7350INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7351{
developerd946fd62022-12-08 18:03:28 +08007352 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007353 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007354 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007355 char cmd[256] = {0}, buf[2048] = {0};
7356 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007357 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007358 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007359 wifi_associated_dev_t *dev=NULL;
7360
7361 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7362 *associated_dev_array = NULL;
developerac6f1142022-12-20 19:26:35 +08007363 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08007364 return RETURN_ERR;
7365 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007366 _syscmd(cmd,buf,sizeof(buf));
7367 *output_array_size = atoi(buf);
7368
7369 if (*output_array_size <= 0)
7370 return RETURN_OK;
7371
7372 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7373 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007374 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007375 _syscmd(cmd,buf,sizeof(buf));
7376 f = fopen("/tmp/connected_devices.txt", "r");
7377 if (f==NULL)
7378 {
7379 *output_array_size=0;
7380 return RETURN_ERR;
7381 }
developer30423732022-12-01 16:17:49 +08007382 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007383 {
7384 param = strtok(line,"=");
7385 value = strtok(NULL,"=");
7386
7387 if( strcmp("flags",param) == 0 )
7388 {
7389 value[strlen(value)-1]='\0';
7390 if(strstr (value,"AUTHORIZED") != NULL )
7391 {
7392 dev[auth_temp].cli_AuthenticationState = 1;
7393 dev[auth_temp].cli_Active = 1;
7394 auth_temp++;
7395 read_flag=1;
7396 }
7397 }
7398 if(read_flag==1)
7399 {
7400 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7401 {
7402 value[strlen(value)-1]='\0';
7403 sscanf(value, "%x:%x:%x:%x:%x:%x",
7404 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7405 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7406 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7407 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7408 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7409 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7410 mac_temp++;
7411 read_flag=0;
7412 }
7413 }
7414 }
7415 *output_array_size = auth_temp;
7416 auth_temp=0;
7417 mac_temp=0;
7418 free(line);
7419 fclose(f);
7420 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7421 return RETURN_OK;
7422}
7423
7424#define MACADDRESS_SIZE 6
7425
7426INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7427{
7428 FILE *fp = NULL;
7429 char str[MAX_BUF_SIZE] = {0};
7430 int wificlientindex = 0 ;
7431 int count = 0;
7432 int signalstrength = 0;
7433 int arr[MACADDRESS_SIZE] = {0};
7434 unsigned char mac[MACADDRESS_SIZE] = {0};
7435 UINT wifi_count = 0;
7436 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7437 char pipeCmd[MAX_CMD_SIZE] = {0};
7438
7439 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7440 *output_array_size = 0;
7441 *associated_dev_array = NULL;
7442
7443 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7444 fp = popen(pipeCmd, "r");
7445 if (fp == NULL)
7446 {
7447 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7448 return RETURN_ERR;
7449 }
7450
7451 /* Read the output a line at a time - output it. */
7452 fgets(str, sizeof(str)-1, fp);
7453 wifi_count = (unsigned int) atoi ( str );
7454 *output_array_size = wifi_count;
7455 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7456 pclose(fp);
7457
7458 if(wifi_count == 0)
7459 {
7460 return RETURN_OK;
7461 }
7462 else
7463 {
7464 wifi_associated_dev3_t* temp = NULL;
7465 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7466 if(temp == NULL)
7467 {
7468 printf("Error Statement. Insufficient memory \n");
7469 return RETURN_ERR;
7470 }
7471
7472 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7473 system(pipeCmd);
7474 memset(pipeCmd,0,sizeof(pipeCmd));
7475 if(apIndex == 0)
7476 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7477 else if(apIndex == 1)
7478 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7479 system(pipeCmd);
7480
7481 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7482 if(fp == NULL)
7483 {
7484 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007485 free(temp);
developer06a01d92022-09-07 16:32:39 +08007486 return RETURN_ERR;
7487 }
7488 fclose(fp);
7489
developer30423732022-12-01 16:17:49 +08007490 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007491 fp = popen(pipeCmd, "r");
7492 if(fp)
7493 {
7494 for(count =0 ; count < wifi_count; count++)
7495 {
7496 fgets(str, MAX_BUF_SIZE, fp);
7497 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7498 {
7499 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7500 {
7501 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7502
7503 }
7504 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7505 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]);
7506 }
7507 temp[count].cli_AuthenticationState = 1; //TODO
7508 temp[count].cli_Active = 1; //TODO
7509 }
7510 pclose(fp);
7511 }
7512
developer30423732022-12-01 16:17:49 +08007513 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 +08007514 fp = popen(pipeCmd, "r");
7515 if(fp)
7516 {
7517 pclose(fp);
7518 }
7519 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7520 if(fp)
7521 {
7522 for(count =0 ; count < wifi_count ;count++)
7523 {
7524 fgets(str, MAX_BUF_SIZE, fp);
7525 signalstrength = atoi(str);
7526 temp[count].cli_SignalStrength = signalstrength;
7527 temp[count].cli_RSSI = signalstrength;
7528 temp[count].cli_SNR = signalstrength + 95;
7529 }
7530 pclose(fp);
7531 }
7532
7533
7534 if((apIndex == 0) || (apIndex == 4))
7535 {
7536 for(count =0 ; count < wifi_count ;count++)
7537 {
7538 strcpy(temp[count].cli_OperatingStandard,"g");
7539 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7540 }
7541
7542 //BytesSent
developer30423732022-12-01 16:17:49 +08007543 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 +08007544 fp = popen(pipeCmd, "r");
7545 if(fp)
7546 {
7547 pclose(fp);
7548 }
7549 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7550 if(fp)
7551 {
7552 for (count = 0; count < wifi_count; count++)
7553 {
7554 fgets(str, MAX_BUF_SIZE, fp);
7555 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7556 }
7557 pclose(fp);
7558 }
7559
7560 //BytesReceived
developer30423732022-12-01 16:17:49 +08007561 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 +08007562 fp = popen(pipeCmd, "r");
7563 if (fp)
7564 {
7565 pclose(fp);
7566 }
7567 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7568 if (fp)
7569 {
7570 for (count = 0; count < wifi_count; count++)
7571 {
7572 fgets(str, MAX_BUF_SIZE, fp);
7573 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7574 }
7575 pclose(fp);
7576 }
7577
7578 //PacketsSent
developer30423732022-12-01 16:17:49 +08007579 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 +08007580 fp = popen(pipeCmd, "r");
7581 if (fp)
7582 {
7583 pclose(fp);
7584 }
7585
7586 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7587 if (fp)
7588 {
7589 for (count = 0; count < wifi_count; count++)
7590 {
7591 fgets(str, MAX_BUF_SIZE, fp);
7592 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7593 }
7594 pclose(fp);
7595 }
7596
7597 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007598 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 +08007599 fp = popen(pipeCmd, "r");
7600 if (fp)
7601 {
7602 pclose(fp);
7603 }
7604 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7605 if (fp)
7606 {
7607 for (count = 0; count < wifi_count; count++)
7608 {
7609 fgets(str, MAX_BUF_SIZE, fp);
7610 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7611 }
7612 pclose(fp);
7613 }
7614
7615 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007616 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 +08007617 fp = popen(pipeCmd, "r");
7618 if (fp)
7619 {
7620 pclose(fp);
7621 }
7622 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7623 if (fp)
7624 {
7625 for (count = 0; count < wifi_count; count++)
7626 {
7627 fgets(str, MAX_BUF_SIZE, fp);
7628 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7629 }
7630 pclose(fp);
7631 }
7632
7633 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007634 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 +08007635 fp = popen(pipeCmd, "r");
7636 if (fp)
7637 {
7638 pclose(fp);
7639 }
7640 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7641 if (fp)
7642 {
7643 for (count = 0; count < wifi_count; count++)
7644 {
7645 fgets(str, MAX_BUF_SIZE, fp);
7646 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7647 }
7648 pclose(fp);
7649 }
7650
7651 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007652 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 +08007653 fp = popen(pipeCmd, "r");
7654 if (fp)
7655 {
7656 pclose(fp);
7657 }
7658 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7659 if (fp)
7660 {
7661 for (count = 0; count < wifi_count; count++)
7662 {
7663 fgets(str, MAX_BUF_SIZE, fp);
7664 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7665 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7666 }
7667 pclose(fp);
7668 }
7669
7670 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007671 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 +08007672 fp = popen(pipeCmd, "r");
7673 if (fp)
7674 {
7675 pclose(fp);
7676 }
7677 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7678 if (fp)
7679 {
7680 for (count = 0; count < wifi_count; count++)
7681 {
7682 fgets(str, MAX_BUF_SIZE, fp);
7683 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7684 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7685 }
7686 pclose(fp);
7687 }
7688
7689 }
7690 else if ((apIndex == 1) || (apIndex == 5))
7691 {
7692 for (count = 0; count < wifi_count; count++)
7693 {
7694 strcpy(temp[count].cli_OperatingStandard, "a");
7695 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7696 temp[count].cli_BytesSent = 0;
7697 temp[count].cli_BytesReceived = 0;
7698 temp[count].cli_LastDataUplinkRate = 0;
7699 temp[count].cli_LastDataDownlinkRate = 0;
7700 temp[count].cli_PacketsSent = 0;
7701 temp[count].cli_PacketsReceived = 0;
7702 temp[count].cli_ErrorsSent = 0;
7703 }
7704 }
7705
7706 for (count = 0; count < wifi_count; count++)
7707 {
7708 temp[count].cli_Retransmissions = 0;
7709 temp[count].cli_DataFramesSentAck = 0;
7710 temp[count].cli_DataFramesSentNoAck = 0;
7711 temp[count].cli_MinRSSI = 0;
7712 temp[count].cli_MaxRSSI = 0;
7713 strncpy(temp[count].cli_InterferenceSources, "", 64);
7714 memset(temp[count].cli_IPAddress, 0, 64);
7715 temp[count].cli_RetransCount = 0;
7716 temp[count].cli_FailedRetransCount = 0;
7717 temp[count].cli_RetryCount = 0;
7718 temp[count].cli_MultipleRetryCount = 0;
7719 }
7720 *associated_dev_array = temp;
7721 }
7722 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7723 return RETURN_OK;
7724}
7725
7726int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7727{
7728 FILE *fp = NULL;
7729 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7730 char cmd[MAX_CMD_SIZE];
7731 int count = 0;
7732
7733 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7734 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7735 fp = popen(cmd,"r");
7736 if(fp == NULL)
7737 {
7738 printf("Failed to run command in Function %s\n",__FUNCTION__);
7739 return 0;
7740 }
7741 if(fgets(path, sizeof(path)-1, fp) != NULL)
7742 {
7743 for(count=0;path[count]!='\n';count++)
7744 status[count]=path[count];
7745 status[count]='\0';
7746 }
7747 strcpy(wifi_status,status);
7748 pclose(fp);
7749 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7750 return RETURN_OK;
7751}
7752
7753/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7754struct hostapd_sta_param {
7755 char key[50];
7756 char value[100];
7757}
7758
7759static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7760 int i = 0;
7761
7762 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7763 if (strncmp(params[i].key,key,50) == 0){
7764 return &params[i].value;
7765 }
7766 i++;
7767 }
7768 return NULL;
7769
7770} */
7771
7772static unsigned int count_occurences(const char *buf, const char *word)
7773{
7774 unsigned int n = 0;
7775 char *ptr = strstr(buf, word);
7776
7777 while (ptr++) {
7778 n++;
7779 ptr = strstr(ptr, word);
7780 }
7781
7782 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7783 return n;
7784}
7785
7786static const char *get_line_from_str_buf(const char *buf, char *line)
7787{
7788 int i;
7789 int n = strlen(buf);
7790
7791 for (i = 0; i < n; i++) {
7792 line[i] = buf[i];
7793 if (buf[i] == '\n') {
7794 line[i] = '\0';
7795 return &buf[i + 1];
7796 }
7797 }
7798
7799 return NULL;
7800}
7801
7802INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7803{
7804 unsigned int assoc_cnt = 0;
7805 char interface_name[50] = {0};
7806 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7807 char cmd[MAX_CMD_SIZE] = {'\0'};
7808 char line[256] = {'\0'};
7809 int i = 0;
7810 int ret = 0;
7811 const char *ptr = NULL;
7812 char *key = NULL;
7813 char *val = NULL;
7814 wifi_associated_dev3_t *temp = NULL;
7815 int rssi;
7816
7817 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7818
7819 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7820 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7821 return RETURN_ERR;
7822 }
7823
7824 // Example filtered output of 'iw dev' command:
7825 // Station 0a:69:72:10:d2:fa (on wifi0)
7826 // signal avg:-67 [-71, -71] dBm
7827 // Station 28:c2:1f:25:5f:99 (on wifi0)
7828 // signal avg:-67 [-71, -70] dBm
7829 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7830 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7831 return RETURN_ERR;
7832 }
7833
7834 ret = _syscmd(cmd, buf, sizeof(buf));
7835 if (ret == RETURN_ERR) {
7836 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7837 return RETURN_ERR;
7838 }
7839
7840 *output_array_size = count_occurences(buf, "Station");
7841 if (*output_array_size == 0) return RETURN_OK;
7842
7843 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7844 if (temp == NULL) {
7845 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7846 return RETURN_ERR;
7847 }
7848 *associated_dev_array = temp;
7849
7850 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7851 ptr = get_line_from_str_buf(buf, line);
7852 i = -1;
7853 while (ptr) {
7854 if (strstr(line, "Station")) {
7855 i++;
7856 key = strtok(line, " ");
7857 val = strtok(NULL, " ");
7858 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7859 &temp[i].cli_MACAddress[0],
7860 &temp[i].cli_MACAddress[1],
7861 &temp[i].cli_MACAddress[2],
7862 &temp[i].cli_MACAddress[3],
7863 &temp[i].cli_MACAddress[4],
7864 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7865 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7866 free(*associated_dev_array);
7867 return RETURN_ERR;
7868 }
7869 }
7870 else if (i < 0) {
7871 ptr = get_line_from_str_buf(ptr, line);
7872 continue; // We didn't detect 'station' entry yet
7873 }
7874 else if (strstr(line, "signal avg")) {
7875 key = strtok(line, ":");
7876 val = strtok(NULL, " ");
7877 if (sscanf(val, "%d", &rssi) <= 0 ) {
7878 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7879 free(*associated_dev_array);
7880 return RETURN_ERR;
7881 }
7882 temp[i].cli_RSSI = rssi;
7883 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7884 }
7885 // Here other fields can be parsed if added to filter of 'iw dev' command
7886
7887 ptr = get_line_from_str_buf(ptr, line);
7888 };
7889
7890 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7891
7892 return RETURN_OK;
7893}
7894
7895#if 0
7896//To-do
7897INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7898{
7899 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7900
7901 //Using different approach to get required WiFi Parameters from system available commands
7902#if 0
7903 FILE *f;
7904 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7905 char cmd[256], buf[2048];
7906 char *param , *value, *line=NULL;
7907 size_t len = 0;
7908 ssize_t nread;
7909 wifi_associated_dev3_t *dev=NULL;
7910 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007911 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007912 _syscmd(cmd,buf,sizeof(buf));
7913 *output_array_size = atoi(buf);
7914
7915 if (*output_array_size <= 0)
7916 return RETURN_OK;
7917
7918 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7919 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007920 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007921 _syscmd(cmd,buf,sizeof(buf));
7922 f = fopen("/tmp/connected_devices.txt", "r");
7923 if (f==NULL)
7924 {
7925 *output_array_size=0;
7926 return RETURN_ERR;
7927 }
7928 while ((nread = getline(&line, &len, f)) != -1)
7929 {
7930 param = strtok(line,"=");
7931 value = strtok(NULL,"=");
7932
7933 if( strcmp("flags",param) == 0 )
7934 {
7935 value[strlen(value)-1]='\0';
7936 if(strstr (value,"AUTHORIZED") != NULL )
7937 {
7938 dev[auth_temp].cli_AuthenticationState = 1;
7939 dev[auth_temp].cli_Active = 1;
7940 auth_temp++;
7941 read_flag=1;
7942 }
7943 }
7944 if(read_flag==1)
7945 {
7946 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7947 {
7948 value[strlen(value)-1]='\0';
7949 sscanf(value, "%x:%x:%x:%x:%x:%x",
7950 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7951 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7952 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7953 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7954 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7955 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7956
7957 }
7958 else if( strcmp("rx_packets",param) == 0 )
7959 {
7960 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7961 }
7962
7963 else if( strcmp("tx_packets",param) == 0 )
7964 {
7965 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7966 }
7967
7968 else if( strcmp("rx_bytes",param) == 0 )
7969 {
7970 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7971 }
7972
7973 else if( strcmp("tx_bytes",param) == 0 )
7974 {
7975 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7976 mac_temp++;
7977 read_flag=0;
7978 }
7979 }
7980 }
7981
7982 *output_array_size = auth_temp;
7983 auth_temp=0;
7984 mac_temp=0;
7985 free(line);
7986 fclose(f);
7987#endif
7988 char interface_name[MAX_BUF_SIZE] = {0};
7989 char wifi_status[MAX_BUF_SIZE] = {0};
7990 char hostapdconf[MAX_BUF_SIZE] = {0};
7991
7992 wifi_associated_dev3_t *dev_array = NULL;
7993 ULONG wifi_count = 0;
7994
7995 *associated_dev_array = NULL;
7996 *output_array_size = 0;
7997
7998 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7999 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8000 {
8001 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8002
developerac6f1142022-12-20 19:26:35 +08008003 wifi_GetInterfaceName(interface_name, hostapdconf);
developer06a01d92022-09-07 16:32:39 +08008004
8005 if(strlen(interface_name) > 1)
8006 {
8007 wifihal_interfacestatus(wifi_status,interface_name);
8008 if(strcmp(wifi_status,"RUNNING") == 0)
8009 {
8010 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8011
8012 *associated_dev_array = dev_array;
8013 *output_array_size = wifi_count;
8014 }
8015 else
8016 {
8017 *associated_dev_array = NULL;
8018 }
8019 }
8020 }
8021
8022 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8023 return RETURN_OK;
8024}
8025#endif
8026
8027/* getIPAddress function */
8028/**
8029* @description Returning IpAddress of the Matched String
8030*
8031* @param
8032* @str Having MacAddress
8033* @ipaddr Having ipaddr
8034* @return The status of the operation
8035* @retval RETURN_OK if successful
8036* @retval RETURN_ERR if any error is detected
8037*
8038*/
8039
8040INT getIPAddress(char *str,char *ipaddr)
8041{
8042 FILE *fp = NULL;
8043 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8044 int LeaseTime = 0,ret = 0;
8045 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8046 {
8047 return RETURN_ERR;
8048 }
8049
8050 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8051 {
8052 /*
8053 Sample:sss
8054 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8055 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8056 */
8057 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08008058 &(LeaseTime),
8059 phyAddr,
8060 ipAddr,
8061 hostName
8062 );
developer06a01d92022-09-07 16:32:39 +08008063 if(ret != 4)
8064 continue;
8065 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08008066 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08008067 }
developerd946fd62022-12-08 18:03:28 +08008068 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08008069 return RETURN_OK;
8070}
8071
8072/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8073/**
8074* @description Returning Inactive wireless connected clients informations
8075*
8076* @param
8077* @filename Holding private_wifi 2g/5g content files
8078* @associated_dev_array Having inactiv wireless clients informations
8079* @output_array_size Returning Inactive wireless counts
8080* @return The status of the operation
8081* @retval RETURN_OK if successful
8082* @retval RETURN_ERR if any error is detected
8083*
8084*/
8085
8086INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8087{
8088 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8089 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8090 FILE *fp = NULL;
8091 int arr[MACADDRESS_SIZE] = {0};
8092 unsigned char mac[MACADDRESS_SIZE] = {0};
8093 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8094 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8095 fp = popen(buf,"r");
8096 if(fp == NULL)
8097 return RETURN_ERR;
8098 else
8099 {
8100 fgets(path,sizeof(path),fp);
8101 maccount = atoi(path);
8102 }
8103 pclose(fp);
8104 *output_array_size = maccount;
8105 wifi_associated_dev3_t* temp = NULL;
8106 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8107 *associated_dev_array = temp;
8108 if(temp == NULL)
8109 {
8110 printf("Error Statement. Insufficient memory \n");
8111 return RETURN_ERR;
8112 }
8113 memset(buf,0,sizeof(buf));
8114 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8115 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08008116 if (fp == NULL) {
8117 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8118 return RETURN_ERR;
8119 }
developer06a01d92022-09-07 16:32:39 +08008120 for(count = 0; count < maccount ; count++)
8121 {
8122 fgets(path,sizeof(path),fp);
8123 for(i = 0; path[i]!='\n';i++)
8124 str[i]=path[i];
8125 str[i]='\0';
8126 getIPAddress(str,ipaddr);
8127 memset(buf,0,sizeof(buf));
8128 if(strlen(ipaddr) > 0)
8129 {
8130 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8131 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8132 {
8133 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8134 {
8135 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8136 {
8137 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8138
8139 }
8140 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8141 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]);
8142 }
8143 temp[count].cli_AuthenticationState = 0; //TODO
8144 temp[count].cli_Active = 0; //TODO
8145 temp[count].cli_SignalStrength = 0;
8146 }
8147 else //Active wireless clients info
8148 {
8149 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8150 {
8151 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8152 {
8153 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8154
8155 }
8156 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8157 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]);
8158 }
8159 temp[count].cli_Active = 1;
8160 }
8161 }
8162 memset(ipaddr,0,sizeof(ipaddr));
8163 }
8164 pclose(fp);
8165 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8166 return RETURN_OK;
8167}
8168//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8169//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8170//To get Band Steering Capability
8171INT wifi_getBandSteeringCapability(BOOL *support)
8172{
8173 *support = FALSE;
8174 return RETURN_OK;
8175}
8176
8177
8178//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8179//To get Band Steering enable status
8180INT wifi_getBandSteeringEnable(BOOL *enable)
8181{
8182 *enable = FALSE;
8183 return RETURN_OK;
8184}
8185
8186//To turn on/off Band steering
8187INT wifi_setBandSteeringEnable(BOOL enable)
8188{
8189 return RETURN_OK;
8190}
8191
8192//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8193//To get Band Steering AP group
8194INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8195{
8196 if (NULL == output_ApGroup)
8197 return RETURN_ERR;
8198
8199 strcpy(output_ApGroup, "1,2");
8200 return RETURN_OK;
8201}
8202
8203//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8204//to set and read the band steering BandUtilizationThreshold parameters
8205INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8206{
8207 return RETURN_ERR;
8208}
8209
8210INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8211{
8212 return RETURN_ERR;
8213}
8214
8215//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8216//to set and read the band steering RSSIThreshold parameters
8217INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8218{
8219 return RETURN_ERR;
8220}
8221
8222INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8223{
8224 return RETURN_ERR;
8225}
8226
8227
8228//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8229//to set and read the band steering physical modulation rate threshold parameters
8230INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8231{
8232 //If chip is not support, return -1
8233 return RETURN_ERR;
8234}
8235
8236INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8237{
8238 //If chip is not support, return -1
8239 return RETURN_ERR;
8240}
8241
8242//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8243//to set and read the inactivity time (in seconds) for steering under overload condition
8244INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8245{
8246 return RETURN_ERR;
8247}
8248
8249INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8250{
8251 return RETURN_ERR;
8252}
8253
8254//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8255//to set and read the inactivity time (in seconds) for steering under Idle condition
8256INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8257{
8258 return RETURN_ERR;
8259}
8260
8261INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8262{
8263 return RETURN_ERR;
8264}
8265
8266//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8267//pClientMAC[64]
8268//pSourceSSIDIndex[64]
8269//pDestSSIDIndex[64]
8270//pSteeringReason[256]
8271INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8272{
8273 //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
8274 *pSteeringTime=time(NULL);
8275 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8276 return RETURN_OK;
8277}
8278
8279INT wifi_ifConfigDown(INT apIndex)
8280{
8281 INT status = RETURN_OK;
8282 char cmd[64];
8283
8284 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8285 printf("%s: %s\n", __func__, cmd);
8286 system(cmd);
8287
8288 return status;
8289}
8290
8291INT wifi_ifConfigUp(INT apIndex)
8292{
developerd946fd62022-12-08 18:03:28 +08008293 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008294 char cmd[128];
8295 char buf[1024];
8296
developerac6f1142022-12-20 19:26:35 +08008297 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008298 return RETURN_ERR;
8299 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08008300 _syscmd(cmd, buf, sizeof(buf));
8301 return 0;
8302}
8303
8304//>> Deprecated. Replace with wifi_applyRadioSettings
8305INT wifi_pushBridgeInfo(INT apIndex)
8306{
developerd946fd62022-12-08 18:03:28 +08008307 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08008308 char ip[32] = {0};
8309 char subnet[32] = {0};
8310 char bridge[32] = {0};
8311 int vlanId = 0;
8312 char cmd[128] = {0};
8313 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08008314
8315 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8316 wifi_getApVlanID(apIndex,&vlanId);
8317
developerac6f1142022-12-20 19:26:35 +08008318 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008319 return RETURN_ERR;
8320 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008321 _syscmd(cmd,buf, sizeof(buf));
8322
8323 return 0;
8324}
8325
8326INT wifi_pushChannel(INT radioIndex, UINT channel)
8327{
developerd946fd62022-12-08 18:03:28 +08008328 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008329 char cmd[128];
8330 char buf[1024];
8331 int apIndex;
8332
8333 apIndex=(radioIndex==0)?0:1;
developerac6f1142022-12-20 19:26:35 +08008334 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008335 return RETURN_ERR;
8336 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008337 _syscmd(cmd,buf, sizeof(buf));
8338
8339 return 0;
8340}
8341
8342INT wifi_pushChannelMode(INT radioIndex)
8343{
8344 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8345 return RETURN_ERR;
8346}
8347
8348INT wifi_pushDefaultValues(INT radioIndex)
8349{
8350 //Apply Comcast specified default radio settings instantly
8351 //AMPDU=1
8352 //AMPDUFrames=32
8353 //AMPDULim=50000
8354 //txqueuelen=1000
8355
8356 return RETURN_ERR;
8357}
8358
8359INT wifi_pushTxChainMask(INT radioIndex)
8360{
8361 //Apply default TxChainMask instantly
8362 return RETURN_ERR;
8363}
8364
8365INT wifi_pushRxChainMask(INT radioIndex)
8366{
8367 //Apply default RxChainMask instantly
8368 return RETURN_ERR;
8369}
8370
8371INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8372{
8373 INT status;
8374
8375 status = wifi_setSSIDName(apIndex,ssid);
8376 wifi_setApEnable(apIndex,FALSE);
8377 wifi_setApEnable(apIndex,TRUE);
8378
8379 return status;
8380}
8381
8382INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8383{
8384 //Apply default Ssid Advertisement instantly
8385 return RETURN_ERR;
8386}
8387
8388INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8389{
8390 INT status = RETURN_ERR;
8391 *output = 0;
8392 return RETURN_ERR;
8393}
8394
8395INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8396{
8397 return RETURN_OK;
8398}
8399
8400INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8401{
8402 return RETURN_OK;
8403}
8404
8405//To-do
8406INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8407{
developereb199ae2022-09-13 14:04:27 +08008408 char output[16]={'\0'};
8409 char config_file[MAX_BUF_SIZE] = {0};
8410
8411 if (!output_string)
8412 return RETURN_ERR;
8413
8414 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8415 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8416
8417 if (strlen(output) == 0)
8418 snprintf(output_string, 64, "Disabled");
8419 else if (strncmp(output, "0", 1) == 0)
8420 snprintf(output_string, 64, "Disabled");
8421 else if (strncmp(output, "1", 1) == 0)
8422 snprintf(output_string, 64, "Optional");
8423 else if (strncmp(output, "2", 1) == 0)
8424 snprintf(output_string, 64, "Required");
8425 else {
8426 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8427 return RETURN_ERR;
8428 }
8429
8430 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008431 return RETURN_OK;
8432}
8433INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8434{
developereb199ae2022-09-13 14:04:27 +08008435 char str[MAX_BUF_SIZE]={'\0'};
8436 char cmd[MAX_CMD_SIZE]={'\0'};
8437 struct params params;
8438 char config_file[MAX_BUF_SIZE] = {0};
8439
8440 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8441 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8442 return RETURN_ERR;
8443
8444 params.name = "ieee80211w";
8445 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8446 params.value = "0";
8447 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8448 params.value = "1";
8449 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8450 params.value = "2";
8451 else{
8452 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8453 return RETURN_ERR;
8454 }
8455 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8456 wifi_hostapdWrite(config_file, &params, 1);
8457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008458 return RETURN_OK;
8459}
8460INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8461{
8462 char output[16]={'\0'};
8463 char config_file[MAX_BUF_SIZE] = {0};
8464
8465 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8466 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8467 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8468
8469 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8470 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8471
8472 return RETURN_OK;
8473}
8474
8475INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8476{
8477 return RETURN_OK;
8478}
8479
8480INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8481{
8482 return RETURN_OK;
8483}
8484
8485INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8486{
8487 return RETURN_OK;
8488}
8489
8490INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8491{
8492 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8493 char config_file[MAX_BUF_SIZE] = {0};
8494
8495 if (NULL == output)
8496 return RETURN_ERR;
8497 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8498 wifi_hostapdRead(config_file,"hw_mode",output,64);
8499
8500 if(strcmp(output,"b")==0)
8501 sprintf(output, "%s", "1,2,5.5,11");
8502 else if (strcmp(output,"a")==0)
8503 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8504 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8505 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8506
8507 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8508 return RETURN_OK;
8509}
8510
8511INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8512{
8513 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8514 char *temp;
8515 char temp_output[128];
8516 char temp_TransmitRates[128];
8517 char config_file[MAX_BUF_SIZE] = {0};
8518
8519 if (NULL == output)
8520 return RETURN_ERR;
8521
8522 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8523 wifi_hostapdRead(config_file,"supported_rates",output,64);
8524
developer5b398df2022-11-17 20:39:48 +08008525 if (strlen(output) == 0) {
8526 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8527 return RETURN_OK;
8528 }
developer06a01d92022-09-07 16:32:39 +08008529 strcpy(temp_TransmitRates,output);
8530 strcpy(temp_output,"");
8531 temp = strtok(temp_TransmitRates," ");
8532 while(temp!=NULL)
8533 {
8534 temp[strlen(temp)-1]=0;
8535 if((temp[0]=='5') && (temp[1]=='\0'))
8536 {
8537 temp="5.5";
8538 }
8539 strcat(temp_output,temp);
8540 temp = strtok(NULL," ");
8541 if(temp!=NULL)
8542 {
8543 strcat(temp_output,",");
8544 }
8545 }
8546 strcpy(output,temp_output);
8547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8548
8549 return RETURN_OK;
8550}
8551
8552INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8553{
8554 return RETURN_OK;
8555}
8556
8557
8558INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8559{
8560 int i=0;
8561 char *temp;
developeref938762022-10-19 17:21:01 +08008562 char temp1[128] = {0};
8563 char temp_output[128] = {0};
8564 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008565 struct params params={'\0'};
8566 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008567 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008568
8569 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8570 if(NULL == output)
8571 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008572 strcpy(temp_TransmitRates,output);
8573
8574 for(i=0;i<strlen(temp_TransmitRates);i++)
8575 {
developeref938762022-10-19 17:21:01 +08008576 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008577 {
8578 continue;
8579 }
8580 else
8581 {
8582 return RETURN_ERR;
8583 }
8584 }
8585 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008586 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008587 while(temp!=NULL)
8588 {
8589 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008590 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008591 {
developeref938762022-10-19 17:21:01 +08008592 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008593 {
8594 return RETURN_ERR;
8595 }
8596 }
8597
8598 if(strcmp(temp,"5.5")==0)
8599 {
8600 strcpy(temp1,"55");
8601 }
8602 else
8603 {
8604 strcat(temp1,"0");
8605 }
8606 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008607 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008608 if(temp!=NULL)
8609 {
8610 strcat(temp_output," ");
8611 }
8612 }
8613 strcpy(output,temp_output);
8614
developer06a01d92022-09-07 16:32:39 +08008615 params.name = "supported_rates";
8616 params.value = output;
8617
8618 wifi_dbg_printf("\n%s:",__func__);
8619 wifi_dbg_printf("params.value=%s\n",params.value);
8620 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8621 wifi_hostapdWrite(config_file,&params,1);
8622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8623
8624 return RETURN_OK;
8625}
8626
8627
8628static char *sncopy(char *dst, int dst_sz, const char *src)
8629{
8630 if (src && dst && dst_sz > 0) {
8631 strncpy(dst, src, dst_sz);
8632 dst[dst_sz - 1] = '\0';
8633 }
8634 return dst;
8635}
8636
8637static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8638{
8639 if (0 == strcmp(ht_mode, "HT40") ||
8640 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008641 0 == strcmp(ht_mode, "HT160") ||
8642 0 == strcmp(ht_mode, "HT320")) {
developer06a01d92022-09-07 16:32:39 +08008643 switch (channel) {
8644 case 1 ... 7:
8645 case 36:
8646 case 44:
8647 case 52:
8648 case 60:
8649 case 100:
8650 case 108:
8651 case 116:
8652 case 124:
8653 case 132:
8654 case 140:
8655 case 149:
8656 case 157:
8657 return 1;
8658 case 8 ... 13:
8659 case 40:
8660 case 48:
8661 case 56:
8662 case 64:
8663 case 104:
8664 case 112:
8665 case 120:
8666 case 128:
8667 case 136:
8668 case 144:
8669 case 153:
8670 case 161:
8671 return -1;
8672 default:
8673 return -EINVAL;
8674 }
8675 }
8676
8677 return -EINVAL;
8678}
8679
developerb7593de2022-10-18 09:51:57 +08008680static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8681{
8682 int idx = channel%8;
8683 if (0 == strcmp(ht_mode, "HT40") ||
8684 0 == strcmp(ht_mode, "HT80") ||
developer7c4cd202023-03-01 10:56:29 +08008685 0 == strcmp(ht_mode, "HT160") ||
8686 0 == strcmp(ht_mode, "HT320")) {
developerb7593de2022-10-18 09:51:57 +08008687 switch (idx) {
8688 case 1:
8689 return 1;
8690 case 5:
8691 return -1;
8692 default:
8693 return -EINVAL;
8694 }
8695 }
8696
8697 return -EINVAL;
8698}
developer06a01d92022-09-07 16:32:39 +08008699static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8700{
8701 if (NULL == hw_mode) return;
8702
8703 if (0 == strcmp(hw_mode, "ac"))
8704 sncopy(bw_mode, bw_mode_len, "ht vht");
8705
8706 if (0 == strcmp(hw_mode, "n"))
8707 sncopy(bw_mode, bw_mode_len, "ht");
8708
8709 return;
8710}
8711
8712static int util_chan_to_freq(int chan)
8713{
8714 if (chan == 14)
8715 return 2484;
8716 else if (chan < 14)
8717 return 2407 + chan * 5;
8718 else if (chan >= 182 && chan <= 196)
8719 return 4000 + chan * 5;
8720 else
8721 return 5000 + chan * 5;
8722 return 0;
8723}
8724
developerb7593de2022-10-18 09:51:57 +08008725static int util_6G_chan_to_freq(int chan)
8726{
8727 if (chan)
8728 return 5950 + chan * 5;
8729 else
8730 return 0;
8731
8732}
developer06a01d92022-09-07 16:32:39 +08008733const int *util_unii_5g_chan2list(int chan, int width)
8734{
8735 static const int lists[] = {
8736 // <width>, <chan1>, <chan2>..., 0,
8737 20, 36, 0,
8738 20, 40, 0,
8739 20, 44, 0,
8740 20, 48, 0,
8741 20, 52, 0,
8742 20, 56, 0,
8743 20, 60, 0,
8744 20, 64, 0,
8745 20, 100, 0,
8746 20, 104, 0,
8747 20, 108, 0,
8748 20, 112, 0,
8749 20, 116, 0,
8750 20, 120, 0,
8751 20, 124, 0,
8752 20, 128, 0,
8753 20, 132, 0,
8754 20, 136, 0,
8755 20, 140, 0,
8756 20, 144, 0,
8757 20, 149, 0,
8758 20, 153, 0,
8759 20, 157, 0,
8760 20, 161, 0,
8761 20, 165, 0,
8762 40, 36, 40, 0,
8763 40, 44, 48, 0,
8764 40, 52, 56, 0,
8765 40, 60, 64, 0,
8766 40, 100, 104, 0,
8767 40, 108, 112, 0,
8768 40, 116, 120, 0,
8769 40, 124, 128, 0,
8770 40, 132, 136, 0,
8771 40, 140, 144, 0,
8772 40, 149, 153, 0,
8773 40, 157, 161, 0,
8774 80, 36, 40, 44, 48, 0,
8775 80, 52, 56, 60, 64, 0,
8776 80, 100, 104, 108, 112, 0,
8777 80, 116, 120, 124, 128, 0,
8778 80, 132, 136, 140, 144, 0,
8779 80, 149, 153, 157, 161, 0,
8780 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8781 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8782 -1 // final delimiter
8783 };
8784 const int *start;
8785 const int *p;
8786
8787 for (p = lists; *p != -1; p++) {
8788 if (*p == width) {
8789 for (start = ++p; *p != 0; p++) {
8790 if (*p == chan)
8791 return start;
8792 }
8793 }
8794 // move to the end of channel list of given width
8795 while (*p != 0) {
8796 p++;
8797 }
8798 }
8799
8800 return NULL;
8801}
8802
8803static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8804{
8805 if (NULL == ht_mode)
8806 return 0;
8807
8808 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8809 const int *chans = util_unii_5g_chan2list(channel, width);
8810 int sum = 0;
8811 int cnt = 0;
8812
8813 if (NULL == chans)
8814 return 0;
8815
8816 while (*chans) {
8817 sum += *chans;
8818 cnt++;
8819 chans++;
8820 }
developer30423732022-12-01 16:17:49 +08008821 if (cnt == 0)
8822 return 0;
developer06a01d92022-09-07 16:32:39 +08008823 return sum / cnt;
8824}
8825
developerb7593de2022-10-18 09:51:57 +08008826static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8827{
8828 if (NULL == ht_mode)
8829 return 0;
8830
8831 int width = strtol((ht_mode + 2), NULL, 10);
8832
8833 int idx = 0 ;
8834 int centerchan = 0;
8835 int chan_ofs = 1;
8836
8837 if (width == 40){
8838 idx = ((channel/4) + chan_ofs)%2;
8839 switch (idx) {
8840 case 0:
8841 centerchan = (channel - 2);
8842 break;
8843 case 1:
8844 centerchan = (channel + 2);
8845 break;
8846 default:
8847 return -EINVAL;
8848 }
8849 }else if (width == 80){
8850 idx = ((channel/4) + chan_ofs)%4;
8851 switch (idx) {
8852 case 0:
8853 centerchan = (channel - 6);
8854 break;
8855 case 1:
8856 centerchan = (channel + 6);
8857 break;
8858 case 2:
8859 centerchan = (channel + 2);
8860 break;
8861 case 3:
8862 centerchan = (channel - 2);
8863 break;
8864 default:
8865 return -EINVAL;
8866 }
8867 }else if (width == 160){
8868 switch (channel) {
8869 case 1 ... 29:
8870 centerchan = 15;
8871 break;
8872 case 33 ... 61:
8873 centerchan = 47;
8874 break;
8875 case 65 ... 93:
8876 centerchan = 79;
8877 break;
8878 case 97 ... 125:
8879 centerchan = 111;
8880 break;
8881 case 129 ... 157:
8882 centerchan = 143;
8883 break;
8884 case 161 ... 189:
8885 centerchan = 175;
8886 break;
8887 case 193 ... 221:
8888 centerchan = 207;
8889 break;
8890 default:
8891 return -EINVAL;
8892 }
developer7c4cd202023-03-01 10:56:29 +08008893 }else if (width == 320){
8894 switch (channel) {
8895 case 1 ... 29:
8896 centerchan = 31;
8897 break;
8898 case 33 ... 93:
8899 centerchan = 63;
8900 break;
8901 case 97 ... 157:
8902 centerchan = 127;
8903 break;
8904 case 161 ... 221:
8905 centerchan = 191;
8906 break;
8907 default:
8908 return -EINVAL;
8909 }
developerb7593de2022-10-18 09:51:57 +08008910 }
8911 return centerchan;
8912}
developer06a01d92022-09-07 16:32:39 +08008913static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8914{
8915 BOOL onlyG, onlyN, onlyA;
8916 CHAR tmp[64];
8917 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8918 if (ret == RETURN_OK) {
8919 sncopy(hw_mode, hw_mode_size, tmp);
8920 }
8921 return ret;
8922}
8923
8924INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8925{
8926 // Sample commands:
8927 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8928 // hostapd_cli -i wifi0 chan_switch 30 2437
8929 char cmd[MAX_CMD_SIZE] = {0};
8930 char buf[MAX_BUF_SIZE] = {0};
8931 int freq = 0, ret = 0;
8932 char center_freq1_str[32] = ""; // center_freq1=%d
8933 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8934 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8935 char hw_mode[16] = ""; // n|ac
8936 char bw_mode[16] = ""; // ht|ht vht
8937 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08008938 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008939 int sec_chan_offset;
8940 int width;
developer4fb0b922022-09-30 14:29:09 +08008941 char config_file[64] = {0};
8942 BOOL stbcEnable = FALSE;
developer7c4cd202023-03-01 10:56:29 +08008943 BOOL setEHT320 = FALSE;
developer5884e982022-10-06 10:52:50 +08008944 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008945 wifi_band band = band_invalid;
8946 int center_chan = 0;
8947 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008948
developer4fb0b922022-09-30 14:29:09 +08008949 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008950
developerac6f1142022-12-20 19:26:35 +08008951 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08008952 return RETURN_ERR;
8953
developer06a01d92022-09-07 16:32:39 +08008954 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8955
developerb7593de2022-10-18 09:51:57 +08008956 band = wifi_index_to_band(radioIndex);
8957
developer5884e982022-10-06 10:52:50 +08008958 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008959
8960 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008961 if (channel){
developerb7593de2022-10-18 09:51:57 +08008962 if (band == band_6){
8963 freq = util_6G_chan_to_freq(channel);
8964 }else{
8965 freq = util_chan_to_freq(channel);
8966 }
developer7c4cd202023-03-01 10:56:29 +08008967 if (width == 320) {
8968 width = 160; // We should set HE central channel as 160, and additionally modify EHT central channel with 320
8969 setEHT320 = TRUE;
8970 }
developer5884e982022-10-06 10:52:50 +08008971 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008972
developer5884e982022-10-06 10:52:50 +08008973 // Provide bandwith if specified
8974 if (channel_width_MHz > 20) {
8975 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8976 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8977 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008978
developer5884e982022-10-06 10:52:50 +08008979 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8980 }else if (channel_width_MHz == 20){
8981 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8982 }
developer06a01d92022-09-07 16:32:39 +08008983
developerb7593de2022-10-18 09:51:57 +08008984
developer5884e982022-10-06 10:52:50 +08008985 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008986 if (band == band_6){
8987 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8988 if(center_chan){
8989 center_freq1 = util_6G_chan_to_freq(center_chan);
8990 }
8991 }else{
8992 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8993 if(center_chan){
8994 center_freq1 = util_chan_to_freq(center_chan);
8995 }
developer5884e982022-10-06 10:52:50 +08008996 }
developerb7593de2022-10-18 09:51:57 +08008997
8998 if (center_freq1)
8999 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9000
9001 }
9002
9003 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9004 if (band == band_6){
9005 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9006 }else{
9007 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08009008 }
developerb7593de2022-10-18 09:51:57 +08009009 if (sec_chan_offset != -EINVAL)
9010 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08009011
developer5884e982022-10-06 10:52:50 +08009012 // Only the first AP, other are hanging on the same radio
9013 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08009014 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9015 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08009016 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9017 wifi_dbg_printf("execute: '%s'\n", cmd);
9018 ret = _syscmd(cmd, buf, sizeof(buf));
developerfa41b1f2023-01-06 10:25:51 +08009019 wifi_reloadAp(radioIndex);
developer06a01d92022-09-07 16:32:39 +08009020
developer5884e982022-10-06 10:52:50 +08009021 ret = wifi_setRadioChannel(radioIndex, channel);
9022 if (ret != RETURN_OK) {
9023 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9024 return RETURN_ERR;
9025 }
9026
9027 if (sec_chan_offset == 1) ext_str = "Above";
9028 else if (sec_chan_offset == -1) ext_str = "Below";
9029
9030 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08009031
developer5884e982022-10-06 10:52:50 +08009032 } else {
9033 if (channel_width_MHz > 20)
9034 ext_str = "Above";
9035 }
developer4fb0b922022-09-30 14:29:09 +08009036
developer06a01d92022-09-07 16:32:39 +08009037 char mhz_str[16];
9038 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
developer7c4cd202023-03-01 10:56:29 +08009039 if (setEHT320 == TRUE)
9040 wifi_setRadioOperatingChannelBandwidth(radioIndex, "320MHz");
9041 else
9042 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
developer06a01d92022-09-07 16:32:39 +08009043
developer57fa24a2023-03-15 17:25:07 +08009044 writeBandWidth(radioIndex, mhz_str);
9045 if (band == band_2_4 || band == band_5) {
9046 if (width == 20)
9047 wifi_RemoveRadioExtChannel(radioIndex, ext_str);
9048 else
9049 wifi_setRadioExtChannel(radioIndex, ext_str);
9050 }
developer06a01d92022-09-07 16:32:39 +08009051 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9052
9053 return RETURN_OK;
9054}
9055
9056INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9057{
developer615510b2022-09-27 10:14:35 +08009058 int index = -1;
developer06a01d92022-09-07 16:32:39 +08009059 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08009060 char cmd[256]={0};
9061 char buf[128]={0};
9062 char file_name[32] = {0};
9063 char filter_SSID[32] = {0};
9064 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08009065 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009066 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08009067 int freq=0;
developer06a01d92022-09-07 16:32:39 +08009068 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08009069 size_t len=0;
9070 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08009071 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08009072 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08009073 bool filter_enable = false;
9074 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08009075 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009076
developer615510b2022-09-27 10:14:35 +08009077 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009078
developer615510b2022-09-27 10:14:35 +08009079 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9080 f = fopen(file_name, "r");
9081 if (f != NULL) {
developer72ec5572023-01-05 16:27:13 +08009082 fgets(buf, sizeof(file_name), f);
9083 if ((strncmp(buf, "0", 1)) != 0) {
9084 fgets(filter_SSID, sizeof(file_name), f);
9085 if (strlen(filter_SSID) != 0)
9086 filter_enable = true;
9087 }
developer615510b2022-09-27 10:14:35 +08009088 fclose(f);
9089 }
9090
developerac6f1142022-12-20 19:26:35 +08009091 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009092 return RETURN_ERR;
9093
developer033b37b2022-10-18 11:27:46 +08009094 phyId = radio_index_to_phy(radio_index);
9095
9096 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08009097 _syscmd(cmd, buf, sizeof(buf));
9098 channels_num = strtol(buf, NULL, 10);
9099
developerd946fd62022-12-08 18:03:28 +08009100 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9101 // 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 +08009102 fprintf(stderr, "cmd: %s\n", cmd);
9103 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08009104 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9105 return RETURN_ERR;
9106 }
developer5550e242022-09-30 09:59:32 +08009107
9108 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9109 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9110
developer615510b2022-09-27 10:14:35 +08009111 ret = fgets(line, sizeof(line), f);
9112 while (ret != NULL) {
9113 if(strstr(line, "BSS") != NULL) { // new neighbor info
9114 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9115 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9116 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9117
9118 if (!filter_BSS) {
9119 index++;
9120 wifi_neighbor_ap2_t *tmp;
9121 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9122 if (tmp == NULL) { // no more memory to use
9123 index--;
9124 wifi_dbg_printf("%s: realloc failed\n", __func__);
9125 break;
9126 }
9127 scan_array = tmp;
9128 }
9129 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08009130
developer615510b2022-09-27 10:14:35 +08009131 filter_BSS = false;
9132 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9133 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9134 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9135 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9136 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08009137 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08009138 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08009139
developer615510b2022-09-27 10:14:35 +08009140 if (freq >= 2412 && freq <= 2484) {
9141 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9142 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9143 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9144 }
9145 else if (freq >= 5160 && freq <= 5805) {
9146 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9147 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9148 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9149 }
developer06a01d92022-09-07 16:32:39 +08009150
developer615510b2022-09-27 10:14:35 +08009151 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08009152 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08009153 for (int i = 0; i < channels_num; i++) {
9154 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9155 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9156 break;
9157 }
9158 }
developer06a01d92022-09-07 16:32:39 +08009159 }
developer615510b2022-09-27 10:14:35 +08009160 } else if (strstr(line, "beacon interval") != NULL) {
9161 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9162 } else if (strstr(line, "signal") != NULL) {
9163 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9164 } else if (strstr(line,"SSID") != NULL) {
9165 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9166 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9167 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08009168 }
developer615510b2022-09-27 10:14:35 +08009169 } else if (strstr(line, "Supported rates") != NULL) {
9170 char SRate[80] = {0}, *tmp = NULL;
9171 memset(buf, 0, sizeof(buf));
9172 strcpy(SRate, line);
9173 tmp = strtok(SRate, ":");
9174 tmp = strtok(NULL, ":");
9175 strcpy(buf, tmp);
9176 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08009177
developer615510b2022-09-27 10:14:35 +08009178 tmp = strtok(buf, " \n");
9179 while (tmp != NULL) {
9180 strcat(SRate, tmp);
9181 if (SRate[strlen(SRate) - 1] == '*') {
9182 SRate[strlen(SRate) - 1] = '\0';
9183 }
9184 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08009185
developer615510b2022-09-27 10:14:35 +08009186 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08009187 }
developer615510b2022-09-27 10:14:35 +08009188 SRate[strlen(SRate) - 1] = '\0';
9189 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9190 } else if (strstr(line, "DTIM") != NULL) {
9191 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9192 } else if (strstr(line, "VHT capabilities") != NULL) {
9193 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9194 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9195 } else if (strstr(line, "HT capabilities") != NULL) {
9196 strcat(scan_array[index].ap_SupportedStandards, ",n");
9197 strcpy(scan_array[index].ap_OperatingStandards, "n");
9198 } else if (strstr(line, "VHT operation") != NULL) {
9199 ret = fgets(line, sizeof(line), f);
9200 sscanf(line," * channel width: %d", &vht_channel_width);
9201 if(vht_channel_width == 1) {
9202 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9203 } else {
9204 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9205 }
9206 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9207 continue;
9208 } else if (strstr(line, "HT operation") != NULL) {
9209 ret = fgets(line, sizeof(line), f);
9210 sscanf(line," * secondary channel offset: %s", &buf);
9211 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08009212 //40Mhz +
developer615510b2022-09-27 10:14:35 +08009213 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 +08009214 }
developer615510b2022-09-27 10:14:35 +08009215 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08009216 //40Mhz -
developer615510b2022-09-27 10:14:35 +08009217 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9218 } else {
9219 //20Mhz
9220 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 +08009221 }
developer615510b2022-09-27 10:14:35 +08009222 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08009223 continue;
developer615510b2022-09-27 10:14:35 +08009224 } else if (strstr(line, "HE capabilities") != NULL) {
9225 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9226 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9227 ret = fgets(line, sizeof(line), f);
9228 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9229 if (strstr(line, "HE40/2.4GHz") != NULL)
9230 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9231 else
9232 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9233 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9234 if (strstr(line, "HE80/5GHz") != NULL) {
9235 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9236 ret = fgets(line, sizeof(line), f);
9237 } else
9238 continue;
9239 if (strstr(line, "HE160/5GHz") != NULL)
9240 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08009241 }
developer615510b2022-09-27 10:14:35 +08009242 continue;
9243 } else if (strstr(line, "WPA") != NULL) {
9244 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9245 } else if (strstr(line, "RSN") != NULL) {
9246 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9247 } else if (strstr(line, "Group cipher") != NULL) {
9248 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9249 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9250 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08009251 }
developer06a01d92022-09-07 16:32:39 +08009252 }
developer615510b2022-09-27 10:14:35 +08009253 ret = fgets(line, sizeof(line), f);
9254 }
9255
9256 if (!filter_BSS) {
9257 *output_array_size = index + 1;
9258 } else {
9259 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9260 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08009261 }
developer06a01d92022-09-07 16:32:39 +08009262 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08009263 pclose(f);
developer5550e242022-09-30 09:59:32 +08009264 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08009265 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009266 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009267}
developer615510b2022-09-27 10:14:35 +08009268
developer06a01d92022-09-07 16:32:39 +08009269INT wifi_getApAssociatedDeviceStats(
9270 INT apIndex,
9271 mac_address_t *clientMacAddress,
9272 wifi_associated_dev_stats_t *associated_dev_stats,
9273 u64 *handle)
9274{
9275 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9276 char interface_name[50] = {0};
9277 char cmd[1024] = {0};
9278 char mac_str[18] = {0};
9279 char *key = NULL;
9280 char *val = NULL;
9281 FILE *f = NULL;
9282 char *line = NULL;
9283 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08009284
9285 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9286 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9287 return RETURN_ERR;
9288 }
9289
9290 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9291 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9292 if((f = popen(cmd, "r")) == NULL) {
9293 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9294 return RETURN_ERR;
9295 }
9296
developer30423732022-12-01 16:17:49 +08009297 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08009298 key = strtok(line,":");
9299 val = strtok(NULL,":");
9300
9301 if(!strncmp(key,"rx bytes",8))
9302 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9303 if(!strncmp(key,"tx bytes",8))
9304 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9305 if(!strncmp(key,"rx packets",10))
9306 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9307 if(!strncmp(key,"tx packets",10))
9308 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9309 if(!strncmp(key,"tx retries",10))
9310 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9311 if(!strncmp(key,"tx failed",9))
9312 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9313 if(!strncmp(key,"rx drop misc",13))
9314 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9315 if(!strncmp(key,"rx bitrate",10)) {
9316 val = strtok(val, " ");
9317 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9318 }
9319 if(!strncmp(key,"tx bitrate",10)) {
9320 val = strtok(val, " ");
9321 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9322 }
9323 }
9324 free(line);
9325 pclose(f);
9326 return RETURN_OK;
9327}
9328
9329INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9330{
developerd946fd62022-12-08 18:03:28 +08009331 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009332 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9333
9334 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9335 if (NULL == output_string)
9336 return RETURN_ERR;
9337
developerac6f1142022-12-20 19:26:35 +08009338 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009339 return RETURN_ERR;
9340 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 +08009341 _syscmd(cmd, buf, sizeof(buf));
9342
9343 //size of SSID name restricted to value less than 32 bytes
9344 snprintf(output_string, 32, "%s", buf);
9345 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9346
9347 return RETURN_OK;
9348}
9349
9350INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9351{
9352 //char cmd[MAX_CMD_SIZE] = {0};
9353 char config_file[MAX_BUF_SIZE] = {0};
9354 char buf[32] = {0};
9355
9356 if (!output_filterMode)
9357 return RETURN_ERR;
9358
9359 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9360 //_syscmd(cmd, buf, sizeof(buf));
9361 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9362 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009363 if(strlen(buf) == 0) {
9364 *output_filterMode = 0;
9365 }
9366 else {
9367 int macaddr_acl_mode = strtol(buf, NULL, 10);
9368 if (macaddr_acl_mode == 1) {
9369 *output_filterMode = 1;
9370 } else if (macaddr_acl_mode == 0) {
9371 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9372 if (strlen(buf) == 0) {
9373 *output_filterMode = 0;
9374 } else {
9375 *output_filterMode = 2;
9376 }
9377 } else {
9378 return RETURN_ERR;
9379 }
9380 }
developer06a01d92022-09-07 16:32:39 +08009381
9382 return RETURN_OK;
9383}
9384
9385INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9386{
9387 FILE *fp = NULL;
9388 char str[MAX_BUF_SIZE] = {0};
9389 int wificlientindex = 0 ;
9390 int count = 0;
9391 int signalstrength = 0;
9392 int arr[MACADDRESS_SIZE] = {0};
9393 unsigned char mac[MACADDRESS_SIZE] = {0};
9394 UINT wifi_count = 0;
9395 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9396 char pipeCmd[MAX_CMD_SIZE] = {0};
9397
9398 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9399 *output_array_size = 0;
9400 *associated_dev_array = NULL;
9401 char interface_name[50] = {0};
9402
9403 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9404 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9405 return RETURN_ERR;
9406 }
9407
9408 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9409 fp = popen(pipeCmd, "r");
9410 if (fp == NULL)
9411 {
9412 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9413 return RETURN_ERR;
9414 }
9415
9416 /* Read the output a line at a time - output it. */
9417 fgets(str, sizeof(str)-1, fp);
9418 wifi_count = (unsigned int) atoi ( str );
9419 *output_array_size = wifi_count;
9420 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9421 pclose(fp);
9422
9423 if(wifi_count == 0)
9424 {
9425 return RETURN_OK;
9426 }
9427 else
9428 {
9429 wifi_associated_dev2_t* temp = NULL;
9430 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9431 *associated_dev_array = temp;
9432 if(temp == NULL)
9433 {
9434 printf("Error Statement. Insufficient memory \n");
9435 return RETURN_ERR;
9436 }
9437
9438 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9439 system(pipeCmd);
9440
9441 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9442 if(fp == NULL)
9443 {
9444 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9445 return RETURN_ERR;
9446 }
9447 fclose(fp);
9448
developer30423732022-12-01 16:17:49 +08009449 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009450 fp = popen(pipeCmd, "r");
9451 if(fp)
9452 {
9453 for(count =0 ; count < wifi_count; count++)
9454 {
9455 fgets(str, MAX_BUF_SIZE, fp);
9456 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9457 {
9458 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9459 {
9460 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9461
9462 }
9463 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9464 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]);
9465 }
9466 temp[count].cli_AuthenticationState = 1; //TODO
9467 temp[count].cli_Active = 1; //TODO
9468 }
9469 pclose(fp);
9470 }
9471
9472 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009473 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 +08009474 fp = popen(pipeCmd, "r");
9475 if(fp)
9476 {
9477 pclose(fp);
9478 }
9479 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9480 if(fp)
9481 {
9482 for(count =0 ; count < wifi_count ;count++)
9483 {
9484 fgets(str, MAX_BUF_SIZE, fp);
9485 signalstrength = atoi(str);
9486 temp[count].cli_RSSI = signalstrength;
9487 }
9488 pclose(fp);
9489 }
9490
9491
9492 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009493 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 +08009494 fp = popen(pipeCmd, "r");
9495 if (fp)
9496 {
9497 pclose(fp);
9498 }
9499 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9500 if (fp)
9501 {
9502 for (count = 0; count < wifi_count; count++)
9503 {
9504 fgets(str, MAX_BUF_SIZE, fp);
9505 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9506 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9507 }
9508 pclose(fp);
9509 }
9510
9511 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009512 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 +08009513 fp = popen(pipeCmd, "r");
9514 if (fp)
9515 {
9516 pclose(fp);
9517 }
9518 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9519 if (fp)
9520 {
9521 for (count = 0; count < wifi_count; count++)
9522 {
9523 fgets(str, MAX_BUF_SIZE, fp);
9524 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9525 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9526 }
9527 pclose(fp);
9528 }
9529 }
9530 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9531 return RETURN_OK;
9532
9533}
9534
9535INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9536{
9537#if 0
9538 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009539 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009540 _syscmd(cmd, buf, sizeof(buf));*/
9541
9542 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9543 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9544 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9545 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9546
9547 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.
9548 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].
9549 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].
9550 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].
9551 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9552 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9553
9554 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9555 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9556 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9557 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.
9558 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.
9559 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.
9560 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.
9561 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.
9562 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.
9563 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.
9564 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9565#endif
9566
9567 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009568 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009569 char pipeCmd[128] = {0};
9570 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009571 wifi_ssidTrafficStats2_t *out = output_struct;
9572
developerce736392022-09-13 15:24:34 +08009573 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009574 if (!output_struct)
9575 return RETURN_ERR;
9576
developerce736392022-09-13 15:24:34 +08009577 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerac6f1142022-12-20 19:26:35 +08009578 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
developerdbbd6782022-12-16 14:26:20 +08009579 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009580 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009581
developer06a01d92022-09-07 16:32:39 +08009582 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009583 if (fp == NULL) {
9584 fprintf(stderr, "%s: popen failed\n", __func__);
9585 return RETURN_ERR;
9586 }
9587 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009588 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009589
developerce736392022-09-13 15:24:34 +08009590 if (strlen(str) == 0) // interface not exist
9591 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009592
developerce736392022-09-13 15:24:34 +08009593 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9594 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009595
developerce736392022-09-13 15:24:34 +08009596 memset(str, 0, sizeof(str));
9597 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009598 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009599 if (fp == NULL) {
9600 fprintf(stderr, "%s: popen failed\n", __func__);
9601 return RETURN_ERR;
9602 }
9603 fgets(str, sizeof(str), fp);
9604
9605 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9606 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009607 pclose(fp);
developerce736392022-09-13 15:24:34 +08009608
9609 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9610 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9611
9612 // Not supported
9613 output_struct->ssid_RetransCount = 0;
9614 output_struct->ssid_FailedRetransCount = 0;
9615 output_struct->ssid_RetryCount = 0;
9616 output_struct->ssid_MultipleRetryCount = 0;
9617 output_struct->ssid_ACKFailureCount = 0;
9618 output_struct->ssid_AggregatedPacketCount = 0;
9619
developer06a01d92022-09-07 16:32:39 +08009620 return RETURN_OK;
9621}
9622
9623//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).
9624INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9625{
9626 char output_val[16]={'\0'};
9627 char config_file[MAX_BUF_SIZE] = {0};
9628
9629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9630 if (!output)
9631 return RETURN_ERR;
9632 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9633 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9634
9635 if( strcmp(output_val,"1") == 0 )
9636 *output = TRUE;
9637 else
9638 *output = FALSE;
9639 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9640
9641 return RETURN_OK;
9642}
9643
9644INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9645{
9646 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9647 char str[MAX_BUF_SIZE]={'\0'};
9648 char string[MAX_BUF_SIZE]={'\0'};
9649 char cmd[MAX_CMD_SIZE]={'\0'};
9650 char *ch;
9651 char config_file[MAX_BUF_SIZE] = {0};
9652 struct params params;
9653
9654 if(enable == TRUE)
9655 strcpy(string,"1");
9656 else
9657 strcpy(string,"0");
9658
9659 params.name = "ap_isolate";
9660 params.value = string;
9661
9662 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9663 wifi_hostapdWrite(config_file,&params,1);
9664 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9665
9666 return RETURN_OK;
9667}
9668
9669INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9670{
9671 if (NULL == output_dBm)
9672 return RETURN_ERR;
9673
9674 *output_dBm = 0;
9675 return RETURN_OK;
9676}
9677
9678INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9679{
9680 return RETURN_OK;
9681}
9682INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9683{
9684 return RETURN_OK;
9685}
9686INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9687{
9688 return RETURN_OK;
9689}
9690INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9691{
9692 return RETURN_OK;
9693}
9694INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9695{
9696 return RETURN_OK;
9697}
9698INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9699{
9700 char config_file[MAX_BUF_SIZE] = {0};
9701 struct params list;
9702
9703 list.name = "bss_transition";
9704 list.value = activate?"1":"0";
9705 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9706 wifi_hostapdWrite(config_file, &list, 1);
9707
9708 return RETURN_OK;
9709}
9710wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9711
9712void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9713{
9714 return;
9715}
9716
9717INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9718{
9719 // TODO Implement me!
9720 return RETURN_OK;
9721}
9722
9723INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9724{
developera3c68b92022-09-13 15:27:29 +08009725 char file_name[128] = {0};
developera3c68b92022-09-13 15:27:29 +08009726 FILE *f = NULL;
9727
developer72ec5572023-01-05 16:27:13 +08009728 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08009729
developer72ec5572023-01-05 16:27:13 +08009730 if (essid == NULL)
9731 return RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08009732
developer72ec5572023-01-05 16:27:13 +08009733 if (strlen(essid) == 0 || apIndex == -1) {
9734 // When essid is blank (apIndex==-1), the configured SSID on that interface is used.
9735 wifi_getSSIDName(apIndex, essid);
developera3c68b92022-09-13 15:27:29 +08009736 }
9737
developer72ec5572023-01-05 16:27:13 +08009738 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9739 f = fopen(file_name, "w");
9740 if (f == NULL)
9741 return RETURN_ERR;
9742
9743 // For mode == 0 is to disable filter, just don't write ssid to the file.
9744 fprintf(f, "%d\n%s", mode, mode?essid:"");
9745 fclose(f);
9746 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009747 return RETURN_OK;
9748}
9749
9750INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9751{
9752 // TODO Implement me!
9753 //Apply wifi_pushRadioChannel() instantly
9754 return RETURN_ERR;
9755}
9756
9757INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9758{
9759 // TODO Implement me!
9760 return RETURN_OK;
9761}
9762
9763#ifdef HAL_NETLINK_IMPL
9764static int tidStats_callback(struct nl_msg *msg, void *arg) {
9765 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9766 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9767 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9768 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9769 int rem , tid_index = 0;
9770
9771 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9772 wifi_associated_dev_tid_entry_t *stats_entry;
9773
9774 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9775 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9776 };
9777 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9778 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9779 };
9780
9781 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9782 genlmsg_attrlen(gnlh, 0), NULL);
9783
9784
9785 if (!tb[NL80211_ATTR_STA_INFO]) {
9786 fprintf(stderr, "station stats missing!\n");
9787 return NL_SKIP;
9788 }
9789
9790 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9791 tb[NL80211_ATTR_STA_INFO],
9792 stats_policy)) {
9793 fprintf(stderr, "failed to parse nested attributes!\n");
9794 return NL_SKIP;
9795 }
9796
9797 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9798 {
9799 stats_entry = &out->tid_array[tid_index];
9800
9801 stats_entry->tid = tid_index;
9802 stats_entry->ac = _tid_ac_index_get[tid_index];
9803
9804 if(sinfo[NL80211_STA_INFO_TID_STATS])
9805 {
9806 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9807 printf("failed to parse nested stats attributes!");
9808 return NL_SKIP;
9809 }
9810 }
9811 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9812 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9813
9814 if(tid_index < (PS_MAX_TID - 1))
9815 tid_index++;
9816 }
9817 //ToDo: sum_time_ms, ewma_time_ms
9818 return NL_SKIP;
9819}
9820#endif
9821
9822INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9823{
9824#ifdef HAL_NETLINK_IMPL
9825 Netlink nl;
9826 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009827 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009828
developerac6f1142022-12-20 19:26:35 +08009829 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009830 return RETURN_ERR;
9831
9832 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009833
9834 nl.id = initSock80211(&nl);
9835
9836 if (nl.id < 0) {
9837 fprintf(stderr, "Error initializing netlink \n");
9838 return -1;
9839 }
9840
9841 struct nl_msg* msg = nlmsg_alloc();
9842
9843 if (!msg) {
9844 fprintf(stderr, "Failed to allocate netlink message.\n");
9845 nlfree(&nl);
9846 return -2;
9847 }
9848
9849 genlmsg_put(msg,
9850 NL_AUTO_PORT,
9851 NL_AUTO_SEQ,
9852 nl.id,
9853 0,
9854 0,
9855 NL80211_CMD_GET_STATION,
9856 0);
9857
9858 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9859 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9860 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9861 nl_send_auto(nl.socket, msg);
9862 nl_recvmsgs(nl.socket, nl.cb);
9863 nlmsg_free(msg);
9864 nlfree(&nl);
9865 return RETURN_OK;
9866#else
9867//iw implementation
9868#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9869#define TOTAL_MAX_LINES 50
9870
9871 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009872 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009873 FILE *fp=NULL;
9874 char pipeCmd[1024]= {'\0'};
9875 int lines,tid_index=0;
9876 char mac_addr[20] = {'\0'};
9877
developerac6f1142022-12-20 19:26:35 +08009878 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009879 return RETURN_ERR;
9880
developer06a01d92022-09-07 16:32:39 +08009881 wifi_associated_dev_tid_entry_t *stats_entry;
9882
developer06a01d92022-09-07 16:32:39 +08009883 strcpy(mac_addr,clientMacAddress);
9884
9885 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9886 fp= popen(pipeCmd,"r");
9887 if(fp == NULL)
9888 {
9889 perror("popen for station dump failed\n");
9890 return RETURN_ERR;
9891 }
9892 pclose(fp);
9893
9894 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9895 fp=popen(pipeCmd,"r");
9896 if(fp == NULL)
9897 {
9898 perror("popen for grep station failed\n");
9899 return RETURN_ERR;
9900 }
9901 else if(fgets(buf,sizeof(buf),fp) != NULL)
9902 lines=atoi(buf);
9903 else
9904 {
9905 pclose(fp);
9906 fprintf(stderr,"No devices are connected \n");
9907 return RETURN_ERR;
9908 }
9909 pclose(fp);
9910
9911 if(lines == 1)
9912 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9913
9914 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9915 {
9916 stats_entry = &tid_stats->tid_array[tid_index];
9917 stats_entry->tid = tid_index;
9918
9919 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);
9920
9921 fp=popen(pipeCmd,"r");
9922 if(fp ==NULL)
9923 {
9924 perror("Failed to read from tid file \n");
9925 return RETURN_ERR;
9926 }
9927 else if(fgets(buf,sizeof(buf),fp) != NULL)
9928 stats_entry->num_msdus = atol(buf);
9929
9930 pclose(fp);
9931 stats_entry->ac = _tid_ac_index_get[tid_index];
9932// TODO:
9933// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9934// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9935 }
9936 return RETURN_OK;
9937#endif
9938}
9939
9940
9941INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9942{
developerd946fd62022-12-08 18:03:28 +08009943 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009944 char cmd[128]={0};
9945 char buf[128]={0};
9946 int freq = 0;
9947
9948 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9949
9950 // full mode is used to scan all channels.
9951 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9952 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9953 ieee80211_channel_to_frequency(chan_list[0], &freq);
9954
developerac6f1142022-12-20 19:26:35 +08009955 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08009956 return RETURN_ERR;
9957
developer615510b2022-09-27 10:14:35 +08009958 if (freq)
developerd946fd62022-12-08 18:03:28 +08009959 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +08009960 else
developerd946fd62022-12-08 18:03:28 +08009961 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +08009962
9963 _syscmd(cmd, buf, sizeof(buf));
9964 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9965
developer06a01d92022-09-07 16:32:39 +08009966 return RETURN_OK;
9967}
9968
9969
9970INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9971{
9972 // TODO Implement me!
9973 return RETURN_ERR;
9974}
9975
9976INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9977{
9978 // TODO Implement me!
9979 return RETURN_ERR;
9980}
9981
9982INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9983{
9984 // TODO Implement me!
9985 return RETURN_ERR;
9986}
9987
9988INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9989{
9990 // TODO Implement me!
9991 return RETURN_ERR;
9992}
9993
9994INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9995{
9996 // TODO Implement me!
9997 return RETURN_ERR;
9998}
9999
10000INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10001{
10002 // TODO Implement me!
10003 return RETURN_ERR;
10004}
10005
10006INT wifi_steering_eventUnregister(void)
10007{
10008 // TODO Implement me!
10009 return RETURN_ERR;
10010}
10011
10012INT wifi_delApAclDevices(INT apIndex)
10013{
10014#if 0
10015 char cmd[MAX_BUF_SIZE] = {0};
10016 char buf[MAX_BUF_SIZE] = {0};
10017
10018 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +080010019 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +080010020 if(_syscmd(cmd,buf,sizeof(buf)))
10021 return RETURN_ERR;
10022#endif
developer9988c232023-03-06 14:57:08 +080010023 char cmd[256]={0};
10024 char buf[64]={0};
developer06a01d92022-09-07 16:32:39 +080010025
developere6aafda2022-09-13 14:59:28 +080010026 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer9988c232023-03-06 14:57:08 +080010027 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 +080010028 if(_syscmd(cmd, buf, sizeof(buf)))
10029 return RETURN_ERR;
10030 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010031
10032 return RETURN_OK;
10033}
10034
10035#ifdef HAL_NETLINK_IMPL
10036static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10037 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10038 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10039 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10040 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10041 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10042 char mac_addr[20],dev[20];
10043
10044 nla_parse(tb,
10045 NL80211_ATTR_MAX,
10046 genlmsg_attrdata(gnlh, 0),
10047 genlmsg_attrlen(gnlh, 0),
10048 NULL);
10049
10050 if(!tb[NL80211_ATTR_STA_INFO]) {
10051 fprintf(stderr, "sta stats missing!\n");
10052 return NL_SKIP;
10053 }
10054
10055 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10056 fprintf(stderr, "failed to parse nested attributes!\n");
10057 return NL_SKIP;
10058 }
10059 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10060
10061 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10062
10063 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10064 fprintf(stderr, "failed to parse nested rate attributes!");
10065 return NL_SKIP;
10066 }
10067
10068 if(sinfo[NL80211_STA_INFO_TID_STATS])
10069 {
10070 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10071 printf("failed to parse nested stats attributes!");
10072 return NL_SKIP;
10073 }
10074 }
10075
10076 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10077 {
10078 printf("Type is VHT\n");
10079 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10080 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10081
10082 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10083 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10084 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10085 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10086 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10087 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10088 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10089 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10090 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10091 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10092 }
10093 else
10094 {
10095 printf(" OFDM or CCK \n");
10096 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10097 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10098 }
10099
10100 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10101 if(rinfo[NL80211_RATE_INFO_MCS])
10102 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10103 }
10104 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10105 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10106 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10107 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10108
10109 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10110 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10111
10112 if (sinfo[NL80211_STA_INFO_SIGNAL])
10113 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10114 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10115 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10116 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10117 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10118 //rssi_array need to be filled
10119 return NL_SKIP;
10120}
10121#endif
10122
10123INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10124{
10125#ifdef HAL_NETLINK_IMPL
10126 Netlink nl;
developerd946fd62022-12-08 18:03:28 +080010127 char if_name[32];
developerac6f1142022-12-20 19:26:35 +080010128 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010129 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010130
10131 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10132
10133 if (*output_array_size <= 0)
10134 return RETURN_OK;
10135
developer06a01d92022-09-07 16:32:39 +080010136 nl.id = initSock80211(&nl);
10137
10138 if (nl.id < 0) {
10139 fprintf(stderr, "Error initializing netlink \n");
10140 return 0;
10141 }
10142
10143 struct nl_msg* msg = nlmsg_alloc();
10144
10145 if (!msg) {
10146 fprintf(stderr, "Failed to allocate netlink message.\n");
10147 nlfree(&nl);
10148 return 0;
10149 }
10150
10151 genlmsg_put(msg,
10152 NL_AUTO_PORT,
10153 NL_AUTO_SEQ,
10154 nl.id,
10155 0,
10156 0,
10157 NL80211_CMD_GET_STATION,
10158 0);
10159
10160 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10161 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10162 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10163 nl_send_auto(nl.socket, msg);
10164 nl_recvmsgs(nl.socket, nl.cb);
10165 nlmsg_free(msg);
10166 nlfree(&nl);
10167 return RETURN_OK;
10168#else
10169 //TODO Implement me
10170 return RETURN_OK;
10171#endif
10172}
10173
10174#ifdef HAL_NETLINK_IMPL
10175static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10176 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10177 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10178 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10179 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10180 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10181 char mac_addr[20],dev[20];
10182
10183 nla_parse(tb,
10184 NL80211_ATTR_MAX,
10185 genlmsg_attrdata(gnlh, 0),
10186 genlmsg_attrlen(gnlh, 0),
10187 NULL);
10188
10189 if(!tb[NL80211_ATTR_STA_INFO]) {
10190 fprintf(stderr, "sta stats missing!\n");
10191 return NL_SKIP;
10192 }
10193
10194 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10195 fprintf(stderr, "failed to parse nested attributes!\n");
10196 return NL_SKIP;
10197 }
10198
10199 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10200
10201 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10202
10203 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10204 fprintf(stderr, "failed to parse nested rate attributes!");
10205 return NL_SKIP;
10206 }
10207
10208 if(sinfo[NL80211_STA_INFO_TID_STATS])
10209 {
10210 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10211 printf("failed to parse nested stats attributes!");
10212 return NL_SKIP;
10213 }
10214 }
10215 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10216 {
10217 printf("Type is VHT\n");
10218 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10219 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10220
10221 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10222 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10223 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10224 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10225 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10226 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10227 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10228 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10229 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10230 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10231 }
10232 else
10233 {
10234 printf(" OFDM or CCK \n");
10235 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10236 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10237 }
10238
10239 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10240 if(rinfo[NL80211_RATE_INFO_MCS])
10241 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10242 }
10243
10244 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10245 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10246 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10247 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10248
10249 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10250 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10251 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10252
10253 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10254 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10255
10256 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10257 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10258
10259 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10260 ((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]);
10261
10262 return NL_SKIP;
10263}
10264#endif
10265
10266INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10267{
10268#ifdef HAL_NETLINK_IMPL
10269 Netlink nl;
10270 char if_name[10];
developerd946fd62022-12-08 18:03:28 +080010271 char interface_name[16] = {0};
developerac6f1142022-12-20 19:26:35 +080010272 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010273 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010274
10275 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10276
10277 if (*output_array_size <= 0)
10278 return RETURN_OK;
10279
developerd946fd62022-12-08 18:03:28 +080010280 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +080010281
10282 nl.id = initSock80211(&nl);
10283
10284 if(nl.id < 0) {
10285 fprintf(stderr, "Error initializing netlink \n");
10286 return 0;
10287 }
10288
10289 struct nl_msg* msg = nlmsg_alloc();
10290
10291 if(!msg) {
10292 fprintf(stderr, "Failed to allocate netlink message.\n");
10293 nlfree(&nl);
10294 return 0;
10295 }
10296
10297 genlmsg_put(msg,
10298 NL_AUTO_PORT,
10299 NL_AUTO_SEQ,
10300 nl.id,
10301 0,
10302 0,
10303 NL80211_CMD_GET_STATION,
10304 0);
10305
10306 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10307 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10308 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10309 nl_send_auto(nl.socket, msg);
10310 nl_recvmsgs(nl.socket, nl.cb);
10311 nlmsg_free(msg);
10312 nlfree(&nl);
10313 return RETURN_OK;
10314#else
10315 //TODO Implement me
10316 return RETURN_OK;
10317#endif
10318}
10319
10320INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10321{
10322 // TODO Implement me!
10323 char buf[MAX_BUF_SIZE] = {0};
10324 char config_file[MAX_BUF_SIZE] = {0};
10325
10326 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10327 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10328 *activate = (strncmp("1",buf,1) == 0);
10329
10330 return RETURN_OK;
10331}
10332
10333INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10334{
10335 char config_file[MAX_BUF_SIZE] = {0};
10336 struct params list;
10337
10338 list.name = "rrm_neighbor_report";
10339 list.value = activate?"1":"0";
10340 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10341 wifi_hostapdWrite(config_file, &list, 1);
10342
10343 return RETURN_OK;
10344}
10345
10346INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10347{
10348 char buf[32] = {0};
10349 char config_file[MAX_BUF_SIZE] = {0};
10350
10351 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10352 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10353 *activate = (strncmp("1",buf,1) == 0);
10354
10355 return RETURN_OK;
10356}
10357#undef HAL_NETLINK_IMPL
10358#ifdef HAL_NETLINK_IMPL
10359static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10360 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10361 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10362 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10363 char dev[20];
10364 int freq =0 ;
10365 static int i=0;
10366
10367 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10368
10369 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10370 };
10371
10372 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10373
10374 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10375
10376 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10377 fprintf(stderr, "survey data missing!\n");
10378 return NL_SKIP;
10379 }
10380
10381 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10382 {
10383 fprintf(stderr, "failed to parse nested attributes!\n");
10384 return NL_SKIP;
10385 }
10386
10387
10388 if(out[0].array_size == 1 )
10389 {
10390 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10391 {
10392 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10393 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10394 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10395
10396 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10397 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10398 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10399 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10400 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10401 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10402 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10403 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10404 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10405 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10406 if (sinfo[NL80211_SURVEY_INFO_TIME])
10407 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10408 return NL_STOP;
10409 }
10410 }
10411 else
10412 {
10413 if ( i <= out[0].array_size )
10414 {
10415 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10416 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10417 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10418
10419 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10420 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10421 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10422 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10423 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10424 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10425 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10426 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10427 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10428 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10429 if (sinfo[NL80211_SURVEY_INFO_TIME])
10430 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10431 }
10432 }
10433
10434 i++;
10435 return NL_SKIP;
10436}
10437#endif
10438
10439static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10440{
10441 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10442 FILE *fp;
10443
10444 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10445 {
10446 printf("Creating Frequency-Channel Map\n");
10447 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10448 }
10449 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10450 if((fp = popen(command, "r")))
10451 {
10452 fgets(output, sizeof(output), fp);
10453 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010454 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010455 }
10456
10457 return 0;
10458}
10459
10460static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10461{
10462 int freqMHz = -1;
10463 char cmd[MAX_CMD_SIZE] = {'\0'};
developer7930d352022-12-21 17:55:42 +080010464 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080010465
10466 ieee80211_channel_to_frequency(channel, &freqMHz);
10467 if (freqMHz == -1) {
10468 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10469 return -1;
10470 }
10471
developer7930d352022-12-21 17:55:42 +080010472 wifi_GetInterfaceName(radioIndex, interface_name);
10473 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010474 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10475 radioIndex, freqMHz);
10476 return -1;
10477 }
10478
10479 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10480 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10481 return -1;
10482 }
10483
10484 return 0;
10485}
10486
10487static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10488{
10489 const char *ptr = buf;
10490 char *key = NULL;
10491 char *val = NULL;
10492 char line[256] = { '\0' };
10493
10494 while (ptr = get_line_from_str_buf(ptr, line)) {
10495 if (strstr(line, "Frequency")) continue;
10496
10497 key = strtok(line, ":");
10498 val = strtok(NULL, " ");
10499 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10500
10501 if (!strcmp(key, "noise")) {
10502 sscanf(val, "%d", &stats->ch_noise);
10503 if (stats->ch_noise == 0) {
10504 // Workaround for missing noise information.
10505 // Assume -95 for 2.4G and -103 for 5G
10506 if (radioIndex == 0) stats->ch_noise = -95;
10507 if (radioIndex == 1) stats->ch_noise = -103;
10508 }
10509 }
10510 else if (!strcmp(key, "channel active time")) {
10511 sscanf(val, "%llu", &stats->ch_utilization_total);
10512 }
10513 else if (!strcmp(key, "channel busy time")) {
10514 sscanf(val, "%llu", &stats->ch_utilization_busy);
10515 }
10516 else if (!strcmp(key, "channel receive time")) {
10517 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10518 }
10519 else if (!strcmp(key, "channel transmit time")) {
10520 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10521 }
10522 };
10523
10524 return 0;
10525}
10526
10527INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10528{
10529 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10530#ifdef HAL_NETLINK_IMPL
10531 Netlink nl;
10532 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010533 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010534
10535 local[0].array_size = array_size;
10536
developerac6f1142022-12-20 19:26:35 +080010537 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080010538 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010539
10540 nl.id = initSock80211(&nl);
10541
10542 if (nl.id < 0) {
10543 fprintf(stderr, "Error initializing netlink \n");
10544 return -1;
10545 }
10546
10547 struct nl_msg* msg = nlmsg_alloc();
10548
10549 if (!msg) {
10550 fprintf(stderr, "Failed to allocate netlink message.\n");
10551 nlfree(&nl);
10552 return -2;
10553 }
10554
10555 genlmsg_put(msg,
10556 NL_AUTO_PORT,
10557 NL_AUTO_SEQ,
10558 nl.id,
10559 0,
10560 NLM_F_DUMP,
10561 NL80211_CMD_GET_SURVEY,
10562 0);
10563
10564 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10565 nl_send_auto(nl.socket, msg);
10566 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10567 nl_recvmsgs(nl.socket, nl.cb);
10568 nlmsg_free(msg);
10569 nlfree(&nl);
10570 //Copying the Values
10571 for(int i=0;i<array_size;i++)
10572 {
10573 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10574 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10575 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10576 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10577 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10578 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10579 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10580 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10581 }
10582#else
10583 ULONG channel = 0;
10584 int i;
10585 int number_of_channels = array_size;
10586 char buf[512];
10587 INT ret;
10588 wifi_channelStats_t tmp_stats;
10589
10590 if (number_of_channels == 0) {
10591 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10592 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10593 return RETURN_ERR;
10594 }
10595 number_of_channels = 1;
10596 input_output_channelStats_array[0].ch_number = channel;
10597 }
10598
10599 for (i = 0; i < number_of_channels; i++) {
10600
10601 input_output_channelStats_array[i].ch_noise = 0;
10602 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10603 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10604 input_output_channelStats_array[i].ch_utilization_busy = 0;
10605 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10606 input_output_channelStats_array[i].ch_utilization_total = 0;
10607
10608 memset(buf, 0, sizeof(buf));
10609 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10610 return RETURN_ERR;
10611 }
10612 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10613 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10614 return RETURN_ERR;
10615 }
10616
10617 // XXX: fake missing 'self' counter which is not available in iw survey output
10618 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10619 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10620
10621 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10622 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10623 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10624 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10625 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10626
10627 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",
10628 __func__,
10629 input_output_channelStats_array[i].ch_number,
10630 input_output_channelStats_array[i].ch_noise,
10631 input_output_channelStats_array[i].ch_utilization_total,
10632 input_output_channelStats_array[i].ch_utilization_busy,
10633 input_output_channelStats_array[i].ch_utilization_busy_rx,
10634 input_output_channelStats_array[i].ch_utilization_busy_tx,
10635 input_output_channelStats_array[i].ch_utilization_busy_self,
10636 input_output_channelStats_array[i].ch_utilization_busy_ext);
10637 }
10638#endif
10639 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10640 return RETURN_OK;
10641}
10642#define HAL_NETLINK_IMPL
10643
10644/* Hostapd events */
10645
10646#ifndef container_of
10647#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10648#define container_of(ptr, type, member) \
10649 ((type *)((char *)ptr - offset_of(type, member)))
10650#endif /* container_of */
10651
10652struct ctrl {
10653 char sockpath[128];
10654 char sockdir[128];
10655 char bss[IFNAMSIZ];
10656 char reply[4096];
10657 int ssid_index;
10658 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10659 void (*overrun)(struct ctrl *ctrl);
10660 struct wpa_ctrl *wpa;
10661 unsigned int ovfl;
10662 size_t reply_len;
10663 int initialized;
10664 ev_timer retry;
10665 ev_timer watchdog;
10666 ev_stat stat;
10667 ev_io io;
10668};
10669static wifi_newApAssociatedDevice_callback clients_connect_cb;
10670static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10671static struct ctrl wpa_ctrl[MAX_APS];
10672static int initialized;
10673
10674static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10675{
10676 char cbuf[256] = {};
10677 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10678 struct cmsghdr *cmsg;
10679 unsigned int ovfl = ctrl->ovfl;
10680 unsigned int drop;
10681
10682 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10683 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10684 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10685 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10686
10687 drop = ovfl - ctrl->ovfl;
10688 ctrl->ovfl = ovfl;
10689
10690 return drop;
10691}
10692
10693static void ctrl_close(struct ctrl *ctrl)
10694{
10695 if (ctrl->io.cb)
10696 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10697 if (ctrl->retry.cb)
10698 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10699 if (!ctrl->wpa)
10700 return;
10701
10702 wpa_ctrl_detach(ctrl->wpa);
10703 wpa_ctrl_close(ctrl->wpa);
10704 ctrl->wpa = NULL;
10705 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10706}
10707
10708static void ctrl_process(struct ctrl *ctrl)
10709{
10710 const char *str;
10711 int drops;
10712 int level;
10713 int err;
10714
10715 /* Example events:
10716 *
10717 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10718 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10719 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10720 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10721 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10722 */
10723 if (!(str = index(ctrl->reply, '>')))
10724 return;
10725 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10726 return;
10727
10728 str++;
10729
10730 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10731 if (!(str = index(ctrl->reply, ' ')))
10732 return;
10733 wifi_associated_dev_t sta;
10734 memset(&sta, 0, sizeof(sta));
10735
10736 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10737 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10738 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10739
10740 sta.cli_Active=true;
10741
10742 (clients_connect_cb)(ctrl->ssid_index, &sta);
10743 goto handled;
10744 }
10745
10746 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10747 if (!(str = index(ctrl->reply, ' ')))
10748 return;
10749
10750 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10751 goto handled;
10752 }
10753
10754 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10755 printf("CTRL_WPA: handle TERMINATING event\n");
10756 goto retry;
10757 }
10758
10759 if (strncmp("AP-DISABLED", str, 11) == 0) {
10760 printf("CTRL_WPA: handle AP-DISABLED\n");
10761 goto retry;
10762 }
10763
10764 printf("Event not supported!!\n");
10765
10766handled:
10767
10768 if ((drops = ctrl_get_drops(ctrl))) {
10769 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10770 if (ctrl->overrun)
10771 ctrl->overrun(ctrl);
10772 }
10773
10774 return;
10775
10776retry:
10777 printf("WPA_CTRL: closing\n");
10778 ctrl_close(ctrl);
10779 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10780 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10781}
10782
10783static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10784{
10785 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10786 int err;
10787
10788 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10789 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10790 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10791 ctrl->reply[ctrl->reply_len] = 0;
10792 if (err < 0) {
10793 if (errno == EAGAIN || errno == EWOULDBLOCK)
10794 return;
10795 ctrl_close(ctrl);
10796 ev_timer_again(EV_A_ &ctrl->retry);
10797 return;
10798 }
10799
10800 ctrl_process(ctrl);
10801}
10802
10803static int ctrl_open(struct ctrl *ctrl)
10804{
10805 int fd;
10806
10807 if (ctrl->wpa)
10808 return 0;
10809
10810 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10811 if (!ctrl->wpa)
10812 goto err;
10813
10814 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10815 goto err_close;
10816
10817 fd = wpa_ctrl_get_fd(ctrl->wpa);
10818 if (fd < 0)
10819 goto err_detach;
10820
10821 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10822 goto err_detach;
10823
10824 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10825 ev_io_start(EV_DEFAULT_ &ctrl->io);
10826
10827 return 0;
10828
10829err_detach:
10830 wpa_ctrl_detach(ctrl->wpa);
10831err_close:
10832 wpa_ctrl_close(ctrl->wpa);
10833err:
10834 ctrl->wpa = NULL;
10835 return -1;
10836}
10837
10838static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10839{
10840 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10841
10842 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10843 ctrl_open(ctrl);
10844}
10845
10846static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10847{
10848 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10849
10850 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10851 if (ctrl_open(ctrl) == 0) {
10852 printf("WPA_CTRL: retry successful\n");
10853 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10854 }
10855}
10856
10857int ctrl_enable(struct ctrl *ctrl)
10858{
10859 if (ctrl->wpa)
10860 return 0;
10861
10862 if (!ctrl->stat.cb) {
10863 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10864 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10865 }
10866
10867 if (!ctrl->retry.cb) {
10868 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10869 }
10870
10871 return ctrl_open(ctrl);
10872}
10873
10874static void
10875ctrl_msg_cb(char *buf, size_t len)
10876{
10877 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10878
10879 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10880 ctrl_process(ctrl);
10881}
10882
10883static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10884{
10885 int err;
10886
10887 if (!ctrl->wpa)
10888 return -1;
10889 if (*reply_len < 2)
10890 return -1;
10891
10892 (*reply_len)--;
10893 ctrl->reply_len = sizeof(ctrl->reply);
10894 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10895 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10896 if (err < 0)
10897 return err;
10898
10899 if (ctrl->reply_len > *reply_len)
10900 ctrl->reply_len = *reply_len;
10901
10902 *reply_len = ctrl->reply_len;
10903 memcpy(reply, ctrl->reply, *reply_len);
10904 reply[*reply_len - 1] = 0;
10905 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10906 return 0;
10907}
10908
10909static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10910{
10911 const char *pong = "PONG";
10912 const char *ping = "PING";
10913 char reply[1024];
10914 size_t len = sizeof(reply);
10915 int err;
10916 ULONG s, snum;
10917 INT ret;
10918 BOOL status;
10919
10920 printf("WPA_CTRL: watchdog cb\n");
10921
10922 ret = wifi_getSSIDNumberOfEntries(&snum);
10923 if (ret != RETURN_OK) {
10924 printf("%s: failed to get SSID count", __func__);
10925 return;
10926 }
10927
10928 if (snum > MAX_APS) {
10929 printf("more ssid than supported! %lu\n", snum);
10930 return;
10931 }
10932
10933 for (s = 0; s < snum; s++) {
10934 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010935 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010936 continue;
10937 }
10938 if (status == false) continue;
10939
10940 memset(reply, 0, sizeof(reply));
10941 len = sizeof(reply);
10942 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10943 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10944 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10945 continue;
10946
10947 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10948 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010949 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010950 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10951 }
10952}
10953
10954static int init_wpa()
10955{
10956 int ret = 0, i = 0;
10957 ULONG s, snum;
10958
10959 ret = wifi_getSSIDNumberOfEntries(&snum);
10960 if (ret != RETURN_OK) {
10961 printf("%s: failed to get SSID count", __func__);
10962 return RETURN_ERR;
10963 }
10964
10965 if (snum > MAX_APS) {
10966 printf("more ssid than supported! %lu\n", snum);
10967 return RETURN_ERR;
10968 }
10969
10970 for (s = 0; s < snum; s++) {
10971 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10972 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10973 wpa_ctrl[s].ssid_index = s;
10974 ctrl_enable(&wpa_ctrl[s]);
10975 }
10976
10977 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10978 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10979
10980 initialized = 1;
10981 printf("WPA_CTRL: initialized\n");
10982
10983 return RETURN_OK;
10984}
10985
10986void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10987{
10988 clients_connect_cb = callback_proc;
10989 if (!initialized)
10990 init_wpa();
10991}
10992
10993void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10994{
10995 clients_disconnect_cb = callback_proc;
10996 if (!initialized)
10997 init_wpa();
10998}
10999
11000INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11001{
11002 // TODO Implement me!
11003 return RETURN_ERR;
11004}
11005
11006INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11007{
11008 // TODO Implement me!
11009 return RETURN_ERR;
11010}
11011
11012INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11013{
11014 int i;
developer4b102122023-02-15 10:53:03 +080011015 int phyId = -1;
11016 char cmd[256] = {0};
11017 char channel_numbers_buf[256] = {0};
11018 char dfs_state_buf[256] = {0};
11019 char line[256] = {0};
developer06a01d92022-09-07 16:32:39 +080011020 const char *ptr;
developer4b102122023-02-15 10:53:03 +080011021 BOOL dfs_enable = false;
developer06a01d92022-09-07 16:32:39 +080011022
developer4b102122023-02-15 10:53:03 +080011023 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer06a01d92022-09-07 16:32:39 +080011024
developer4b102122023-02-15 10:53:03 +080011025 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11026 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011027
developer4b102122023-02-15 10:53:03 +080011028 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 +080011029
developer4b102122023-02-15 10:53:03 +080011030 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11031 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11032 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011033 }
11034
developer4b102122023-02-15 10:53:03 +080011035 ptr = channel_numbers_buf;
11036 i = 0;
11037 while (ptr = get_line_from_str_buf(ptr, line)) {
11038 if (i >= outputMapSize) {
11039 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11040 return RETURN_ERR;
11041 }
11042 sscanf(line, "%d", &outputMap[i].ch_number);
11043
11044 memset(cmd, 0, sizeof(cmd));
11045 // Below command should fetch string for DFS state (usable, available or unavailable)
11046 // Example line: "DFS state: usable (for 78930 sec)"
11047 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) {
11048 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer06a01d92022-09-07 16:32:39 +080011049 return RETURN_ERR;
11050 }
11051
developer4b102122023-02-15 10:53:03 +080011052 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11053 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer06a01d92022-09-07 16:32:39 +080011054 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11055 return RETURN_ERR;
11056 }
11057
developer4b102122023-02-15 10:53:03 +080011058 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer06a01d92022-09-07 16:32:39 +080011059
developer4b102122023-02-15 10:53:03 +080011060 if (!strcmp(dfs_state_buf, "usable")) {
11061 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11062 } else if (!strcmp(dfs_state_buf, "available")) {
11063 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11064 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11065 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11066 } else {
11067 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer06a01d92022-09-07 16:32:39 +080011068 }
developer4b102122023-02-15 10:53:03 +080011069 i++;
developer06a01d92022-09-07 16:32:39 +080011070 }
11071
developer4b102122023-02-15 10:53:03 +080011072 return RETURN_OK;
11073
developer06a01d92022-09-07 16:32:39 +080011074 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11075 return RETURN_ERR;
11076}
11077
11078INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11079{
11080 // TODO Implement me!
11081 return RETURN_ERR;
11082}
11083
11084INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11085{
11086 return RETURN_OK;
11087}
11088
11089INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11090{
11091 // TODO Implement me!
11092 return RETURN_ERR;
11093}
11094
11095INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11096{
11097 // TODO API refrence Implementaion is present on RPI hal
11098 return RETURN_ERR;
11099}
11100
11101INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11102{
developerd946fd62022-12-08 18:03:28 +080011103 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +080011104 char cmd[128]={'\0'};
11105 char buf[128]={'\0'};
11106 char *support;
11107 int maximum_tx = 0, current_tx = 0;
11108
11109 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11110 if(txpwr_pcntg == NULL)
11111 return RETURN_ERR;
11112
developerac6f1142022-12-20 19:26:35 +080011113 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011114 return RETURN_ERR;
11115
developera5005b62022-09-13 15:43:35 +080011116 // Get the maximum tx power of the device
developerd946fd62022-12-08 18:03:28 +080011117 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developera5005b62022-09-13 15:43:35 +080011118 _syscmd(cmd, buf, sizeof(buf));
11119 maximum_tx = strtol(buf, NULL, 10);
11120
11121 // Get the current tx power
11122 memset(cmd, 0, sizeof(cmd));
11123 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080011124 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
developera5005b62022-09-13 15:43:35 +080011125 _syscmd(cmd, buf, sizeof(buf));
11126 current_tx = strtol(buf, NULL, 10);
11127
11128 // Get the power supported list and find the current power percentage in supported list
11129 memset(buf, 0, sizeof(buf));
11130 wifi_getRadioTransmitPowerSupported(apIndex, buf);
11131 support = strtok(buf, ",");
11132 while(true)
11133 {
11134 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
developer033b37b2022-10-18 11:27:46 +080011135 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080011136 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080011137 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080011138 }
11139 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
11140 if (tmp == current_tx) {
11141 *txpwr_pcntg = strtol(support, NULL, 10);
11142 break;
11143 }
11144 support = strtok(NULL, ",");
11145 }
11146 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080011147 return RETURN_OK;
11148}
11149
11150INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11151{
developer58599c22022-09-13 16:40:34 +080011152 // TODO precac feature.
11153 struct params params = {0};
11154 char config_file[128] = {0};
11155
11156 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11157
11158 params.name = "enable_background_radar";
11159 params.value = enable?"1":"0";
11160 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11161 wifi_hostapdWrite(config_file, &params, 1);
11162 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11163
11164 /* TODO precac feature */
11165
11166 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11167 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011168}
11169
11170INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11171{
developer58599c22022-09-13 16:40:34 +080011172 char config_file[128] = {0};
11173 char buf[64] = {0};
11174
11175 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11176 if (NULL == enable || NULL == precac)
11177 return RETURN_ERR;
11178
11179 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11180 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
11181 if (strncmp(enable, "1", 1) == 0)
11182 *enable = true;
11183 else
11184 *enable = false;
11185
11186 /* TODO precac feature */
11187
11188 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11189 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011190}
11191
11192INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11193{
developer58599c22022-09-13 16:40:34 +080011194 *supported = TRUE;
11195 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011196}
11197
developera7149722023-01-11 11:36:21 +080011198bool check_is_hemu_vendor_new_patch() {
11199 char cmd[128] = {0};
11200 char buf[128] = {0};
11201
11202 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11203 _syscmd(cmd, buf, sizeof(buf));
11204
11205 if (strlen(buf) > 0)
11206 return FALSE;
11207 else
11208 return TRUE;
11209}
11210
developer3e6b1692022-09-30 18:04:05 +080011211INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11212{
11213 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11214 struct params params = {0};
11215 char config_file[64] = {0};
11216 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011217 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011218 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011219 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11221
developera7149722023-01-11 11:36:21 +080011222 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011223
11224 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11225 set_mu_type &= ~0x05; // unset bit 0, 2
11226 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11227 set_mu_type |= 0x01;
11228 set_mu_type &= ~0x04;
11229 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11230 set_mu_type &= ~0x01;
11231 set_mu_type |= 0x04;
11232 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11233 set_mu_type |= 0x05; // set bit 0, 2
11234 }
11235
developera7149722023-01-11 11:36:21 +080011236 new_vendor_patch = check_is_hemu_vendor_new_patch();
11237 if (new_vendor_patch)
11238 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11239 else
11240 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11241
11242 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011243 sprintf(buf, "%u", set_mu_type);
11244 params.value = buf;
11245 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11246 wifi_hostapdWrite(config_file, &params, 1);
11247 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011248 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011249
11250 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11251 return RETURN_OK;
11252}
11253
11254INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11255{
11256 struct params params={0};
11257 char config_file[64] = {0};
11258 char buf[64] = {0};
11259 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011260 bool new_vendor_patch = FALSE;
11261 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011262
11263 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11264
11265 if (mu_type == NULL)
11266 return RETURN_ERR;
11267
developera7149722023-01-11 11:36:21 +080011268 new_vendor_patch = check_is_hemu_vendor_new_patch();
11269
11270 if (new_vendor_patch)
11271 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11272 else
11273 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11274
developer3e6b1692022-09-30 18:04:05 +080011275 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011276 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011277 get_mu_type = strtol(buf, NULL, 10);
11278
11279 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11280 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11281 else if (get_mu_type & 0x04)
11282 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11283 else if (get_mu_type & 0x01)
11284 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11285 else
11286 *mu_type = WIFI_DL_MU_TYPE_NONE;
11287
11288 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11289 return RETURN_OK;
11290}
11291
11292INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11293{
11294 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11295 struct params params={0};
11296 char config_file[64] = {0};
11297 char buf[64] = {0};
11298 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011299 bool new_vendor_patch = FALSE;
11300 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011301 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11302
developera7149722023-01-11 11:36:21 +080011303 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011304
11305 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11306 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11307 set_mu_type &= ~0x0a;
11308 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11309 set_mu_type |= 0x02;
11310 set_mu_type &= ~0x08;
11311 }
11312
developera7149722023-01-11 11:36:21 +080011313 new_vendor_patch = check_is_hemu_vendor_new_patch();
11314
11315 if (new_vendor_patch)
11316 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11317 else
11318 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11319
11320 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011321 sprintf(buf, "%u", set_mu_type);
11322 params.value = buf;
11323 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11324 wifi_hostapdWrite(config_file, &params, 1);
11325 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011326 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011327
11328 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11329 return RETURN_OK;
11330}
11331
11332INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11333{
11334 struct params params={0};
11335 char config_file[64] = {0};
11336 char buf[64] = {0};
11337 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011338 bool new_vendor_patch = FALSE;
11339 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011340
11341 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11342
developera7149722023-01-11 11:36:21 +080011343 new_vendor_patch = check_is_hemu_vendor_new_patch();
11344
11345 if (new_vendor_patch)
11346 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11347 else
11348 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11349
developer3e6b1692022-09-30 18:04:05 +080011350 if (mu_type == NULL)
11351 return RETURN_ERR;
11352
11353 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011354 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011355
11356 get_mu_type = strtol(buf, NULL, 10);
11357 if (get_mu_type & 0x02)
11358 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11359 else
11360 *mu_type = WIFI_DL_MU_TYPE_NONE;
11361
11362 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11363 return RETURN_OK;
11364}
11365
11366
developer454b9462022-09-13 15:29:16 +080011367INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11368{
11369 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011370 char buf[256] = {0};
11371 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011372 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011373 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011374 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011375 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011376
11377 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11378
developer254882b2022-09-30 17:12:31 +080011379 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011380 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11381 return RETURN_ERR;
11382 }
developer454b9462022-09-13 15:29:16 +080011383
developer254882b2022-09-30 17:12:31 +080011384 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011385 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011386
developer254882b2022-09-30 17:12:31 +080011387 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11388 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011389 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011390 _syscmd(cmd, buf, sizeof(buf));
11391 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11392 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11393 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011394 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 +080011395 _syscmd(cmd, buf, sizeof(buf));
11396 }
11397 if (band == band_5) {
11398 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11399 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011400 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 +080011401 _syscmd(cmd, buf, sizeof(buf));
11402 }
11403 }
11404 }
11405 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011406
developer254882b2022-09-30 17:12:31 +080011407 if (guard_interval == wifi_guard_interval_400)
11408 strcpy(GI, "0.4");
11409 else if (guard_interval == wifi_guard_interval_800)
11410 strcpy(GI, "0.8");
11411 else if (guard_interval == wifi_guard_interval_1600)
11412 strcpy(GI, "1.6");
11413 else if (guard_interval == wifi_guard_interval_3200)
11414 strcpy(GI, "3.2");
11415 else if (guard_interval == wifi_guard_interval_auto)
11416 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011417 // Record GI for get GI function
11418 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11419 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011420 if (f == NULL)
11421 return RETURN_ERR;
11422 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011423 fclose(f);
11424 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11425 return RETURN_OK;
11426}
11427
11428INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11429{
11430 char buf[32] = {0};
11431 char cmd[64] = {0};
11432
11433 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11434
11435 if (guard_interval == NULL)
11436 return RETURN_ERR;
11437
developer7c4cd202023-03-01 10:56:29 +080011438 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011439 _syscmd(cmd, buf, sizeof(buf));
11440
11441 if (strncmp(buf, "0.4", 3) == 0)
11442 *guard_interval = wifi_guard_interval_400;
11443 else if (strncmp(buf, "0.8", 3) == 0)
11444 *guard_interval = wifi_guard_interval_800;
11445 else if (strncmp(buf, "1.6", 3) == 0)
11446 *guard_interval = wifi_guard_interval_1600;
11447 else if (strncmp(buf, "3.2", 3) == 0)
11448 *guard_interval = wifi_guard_interval_3200;
11449 else
11450 *guard_interval = wifi_guard_interval_auto;
11451
11452 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11453 return RETURN_OK;
11454}
11455
developer3cc61d12022-09-13 16:36:05 +080011456INT wifi_setBSSColor(INT radio_index, UCHAR color)
11457{
11458 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11459 struct params params = {0};
11460 char config_file[128] = {0};
11461 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011462 UCHAR *color_list;
11463 int color_num = 0;
11464 int maxNumberColors = 64;
11465 BOOL color_is_aval = FALSE;
11466
11467 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11468 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK)
11469 return RETURN_ERR;
11470
11471 if (color > 63)
11472 return RETURN_ERR;
11473
11474 for (int i = 0; i < color_num; i++) {
11475 if (color_list[i] == color) {
11476 color_is_aval = TRUE;
11477 break;
11478 }
11479 }
11480 if (color_is_aval == FALSE) {
11481 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11482 return RETURN_ERR;
11483 }
developer3cc61d12022-09-13 16:36:05 +080011484
11485 params.name = "he_bss_color";
11486 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11487 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011488 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011489 wifi_hostapdWrite(config_file, &params, 1);
11490 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011491 wifi_reloadAp(radio_index);
11492
developer3cc61d12022-09-13 16:36:05 +080011493 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11494 return RETURN_OK;
11495}
11496
11497INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11498{
developer3cc61d12022-09-13 16:36:05 +080011499 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011500 char cmd[128] = {0};
11501 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011502
developer3cc61d12022-09-13 16:36:05 +080011503 if (NULL == color)
11504 return RETURN_ERR;
11505
developer2acb9632023-03-14 14:58:31 +080011506 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11507 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011508
developer2acb9632023-03-14 14:58:31 +080011509 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11510 _syscmd(cmd, buf, sizeof(buf));
11511 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011512
developer2acb9632023-03-14 14:58:31 +080011513 return RETURN_OK;
11514}
11515
11516INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11517{
11518 char buf[64] = {0};
11519 char cmd[128] = {0};
11520 char interface_name[16] = {0};
11521 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011522
developer2acb9632023-03-14 14:58:31 +080011523 if (NULL == colorList || NULL == numColorReturned)
11524 return RETURN_ERR;
11525
11526 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11527 return RETURN_ERR;
11528
11529 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11530 _syscmd(cmd, buf, sizeof(buf));
11531 color_bitmap = strtoull(buf, NULL, 16);
11532
11533 *numColorReturned = 0;
11534 for (int i = 0; i < maxNumberColors; i++) {
11535 if (color_bitmap & 1) {
11536 colorList[*numColorReturned] = i;
11537 (*numColorReturned) += 1;
11538 }
11539 color_bitmap >>= 1;
11540 }
developer3cc61d12022-09-13 16:36:05 +080011541 return RETURN_OK;
11542}
11543
developer06a01d92022-09-07 16:32:39 +080011544/* multi-psk support */
11545INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11546{
11547 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011548 char interface_name[16] = {0};
11549
developerac6f1142022-12-20 19:26:35 +080011550 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011551 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011552
developerd946fd62022-12-08 18:03:28 +080011553 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11554 interface_name,
developer06a01d92022-09-07 16:32:39 +080011555 mac[0],
11556 mac[1],
11557 mac[2],
11558 mac[3],
11559 mac[4],
11560 mac[5]
11561 );
11562 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11563 _syscmd(cmd, key->wifi_keyId, 64);
11564
11565
11566 return RETURN_OK;
11567}
11568
11569INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11570{
developerd946fd62022-12-08 18:03:28 +080011571 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011572 FILE *fd = NULL;
11573 char fname[100];
11574 char cmd[128] = {0};
11575 char out[64] = {0};
11576 wifi_key_multi_psk_t * key = NULL;
11577 if(keysNumber < 0)
11578 return RETURN_ERR;
11579
developer431128d2022-12-16 15:30:41 +080011580 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011581 fd = fopen(fname, "w");
11582 if (!fd) {
11583 return RETURN_ERR;
11584 }
11585 key= (wifi_key_multi_psk_t *) keys;
11586 for(int i=0; i<keysNumber; ++i, key++) {
11587 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11588 }
11589 fclose(fd);
11590
11591 //reload file
developerac6f1142022-12-20 19:26:35 +080011592 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011593 return RETURN_ERR;
11594 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011595 _syscmd(cmd, out, 64);
11596 return RETURN_OK;
11597}
11598
11599INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11600{
11601 FILE *fd = NULL;
11602 char fname[100];
11603 char * line = NULL;
11604 char * pos = NULL;
11605 size_t len = 0;
11606 ssize_t read = 0;
11607 INT ret = RETURN_OK;
11608 wifi_key_multi_psk_t *keys_it = NULL;
11609
11610 if (keysNumber < 1) {
11611 return RETURN_ERR;
11612 }
11613
developer431128d2022-12-16 15:30:41 +080011614 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011615 fd = fopen(fname, "r");
11616 if (!fd) {
11617 return RETURN_ERR;
11618 }
11619
11620 if (keys == NULL) {
11621 ret = RETURN_ERR;
11622 goto close;
11623 }
11624
11625 keys_it = keys;
11626 while ((read = getline(&line, &len, fd)) != -1) {
11627 //Strip trailing new line if present
11628 if (read > 0 && line[read-1] == '\n') {
11629 line[read-1] = '\0';
11630 }
11631
11632 if(strcmp(line,"keyid=")) {
11633 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11634 if (!(pos = index(line, ' '))) {
11635 ret = RETURN_ERR;
11636 goto close;
11637 }
11638 pos++;
11639 //Here should be 00:00:00:00:00:00
11640 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11641 printf("Not supported MAC: %s\n", pos);
11642 }
11643 if (!(pos = index(pos, ' '))) {
11644 ret = RETURN_ERR;
11645 goto close;
11646 }
11647 pos++;
11648
11649 //The rest is PSK
11650 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11651 keys_it++;
11652
11653 if(--keysNumber <= 0)
11654 break;
11655 }
11656 }
11657
11658close:
11659 free(line);
11660 fclose(fd);
11661 return ret;
11662}
11663/* end of multi-psk support */
11664
11665INT wifi_setNeighborReports(UINT apIndex,
11666 UINT numNeighborReports,
11667 wifi_NeighborReport_t *neighborReports)
11668{
11669 char cmd[256] = { 0 };
11670 char hex_bssid[13] = { 0 };
11671 char bssid[18] = { 0 };
11672 char nr[256] = { 0 };
11673 char ssid[256];
11674 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011675 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011676 INT ret;
11677
11678 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011679 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011680 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011681 return RETURN_ERR;
11682 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 +080011683 system(cmd);
11684
11685 for(unsigned int i = 0; i < numNeighborReports; i++)
11686 {
11687 memset(ssid, 0, sizeof(ssid));
11688 ret = wifi_getSSIDName(apIndex, ssid);
11689 if (ret != RETURN_OK)
11690 return RETURN_ERR;
11691
11692 memset(hex_ssid, 0, sizeof(hex_ssid));
11693 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11694 sprintf(hex_ssid + k,"%02x", ssid[j]);
11695
11696 snprintf(hex_bssid, sizeof(hex_bssid),
11697 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11698 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11699 snprintf(bssid, sizeof(bssid),
11700 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11701 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11702
11703 snprintf(nr, sizeof(nr),
11704 "%s" // bssid
11705 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11706 "%02hhx" // operclass
11707 "%02hhx" // channel
11708 "%02hhx", // phy_mode
11709 hex_bssid,
11710 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11711 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11712 neighborReports[i].opClass,
11713 neighborReports[i].channel,
11714 neighborReports[i].phyTable);
11715
11716 snprintf(cmd, sizeof(cmd),
11717 "hostapd_cli set_neighbor "
11718 "%s " // bssid
11719 "ssid=%s " // ssid
11720 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011721 "-i %s",
11722 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011723
11724 if (WEXITSTATUS(system(cmd)) != 0)
11725 {
11726 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11727 }
11728 }
11729
11730 return RETURN_OK;
11731}
11732
11733INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11734{
11735 return RETURN_OK;
11736}
11737
11738#ifdef _WIFI_HAL_TEST_
11739int main(int argc,char **argv)
11740{
11741 int index;
11742 INT ret=0;
11743 char buf[1024]="";
11744
11745 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11746 if(argc<3)
11747 {
11748 if(argc==2)
11749 {
11750 if(!strcmp(argv[1], "init"))
11751 return wifi_init();
11752 if(!strcmp(argv[1], "reset"))
11753 return wifi_reset();
11754 if(!strcmp(argv[1], "wifi_getHalVersion"))
11755 {
11756 char buffer[64];
11757 if(wifi_getHalVersion(buffer)==RETURN_OK)
11758 printf("Version: %s\n", buffer);
11759 else
11760 printf("Error in wifi_getHalVersion\n");
11761 return RETURN_OK;
11762 }
11763 }
11764 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11765 exit(-1);
11766 }
11767
11768 index = atoi(argv[2]);
11769 if(strstr(argv[1], "wifi_getApName")!=NULL)
11770 {
11771 wifi_getApName(index,buf);
11772 printf("Ap name is %s \n",buf);
11773 return 0;
11774 }
11775 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11776 {
11777 BOOL b = FALSE;
11778 BOOL *output_bool = &b;
11779 wifi_getRadioAutoChannelEnable(index,output_bool);
11780 printf("Channel enabled = %d \n",b);
11781 return 0;
11782 }
11783 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11784 {
11785 wifi_getApWpaEncryptionMode(index,buf);
11786 printf("encryption enabled = %s\n",buf);
11787 return 0;
11788 }
11789 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11790 {
11791 BOOL b = FALSE;
11792 BOOL *output_bool = &b;
11793 wifi_getApSsidAdvertisementEnable(index,output_bool);
11794 printf("advertisment enabled = %d\n",b);
11795 return 0;
11796 }
11797 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11798 {
11799 if(argc <= 3 )
11800 {
11801 printf("Insufficient arguments \n");
11802 exit(-1);
11803 }
11804
11805 char sta[20] = {'\0'};
11806 ULLONG handle= 0;
11807 strcpy(sta,argv[3]);
11808 mac_address_t st;
11809 mac_addr_aton(st,sta);
11810
11811 wifi_associated_dev_tid_stats_t tid_stats;
11812 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11813 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11814 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);
11815 }
11816
11817 if(strstr(argv[1], "getApEnable")!=NULL) {
11818 BOOL enable;
11819 ret=wifi_getApEnable(index, &enable);
11820 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11821 }
11822 else if(strstr(argv[1], "setApEnable")!=NULL) {
11823 BOOL enable = atoi(argv[3]);
11824 ret=wifi_setApEnable(index, enable);
11825 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11826 }
11827 else if(strstr(argv[1], "getApStatus")!=NULL) {
11828 char status[64];
11829 ret=wifi_getApStatus(index, status);
11830 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11831 }
11832 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11833 {
11834 wifi_getSSIDNameStatus(index,buf);
11835 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11836 return 0;
11837 }
11838 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11839 wifi_ssidTrafficStats2_t stats={0};
11840 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11841 printf("%s %d: returns %d\n", argv[1], index, ret);
11842 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11843 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11844 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11845 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11846 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11847 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11848 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11849 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11850 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11851 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11852 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11853 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11854 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11855 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11856 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11857 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11858 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11859 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11860 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11861 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11862 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11863 }
11864 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11865 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11866 UINT array_size=0;
11867 UINT i=0;
11868 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11869 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11870 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11871 printf(" neighbor %d:\n", i);
11872 printf(" ap_SSID =%s\n", pt->ap_SSID);
11873 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11874 printf(" ap_Mode =%s\n", pt->ap_Mode);
11875 printf(" ap_Channel =%d\n", pt->ap_Channel);
11876 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11877 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11878 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11879 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11880 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11881 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11882 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11883 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11884 printf(" ap_Noise =%d\n", pt->ap_Noise);
11885 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11886 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11887 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11888 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11889 }
11890 if(neighbor_ap_array)
11891 free(neighbor_ap_array); //make sure to free the list
11892 }
11893 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11894 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11895 UINT array_size=0;
11896 UINT i=0;
11897 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11898 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11899 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11900 printf(" associated_dev %d:\n", i);
11901 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11902 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11903 printf(" cli_SNR =%d\n", pt->cli_SNR);
11904 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11905 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11906 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11907 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11908 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11909 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11910 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11911 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11912 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11913 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11914 }
11915 if(associated_dev_array)
11916 free(associated_dev_array); //make sure to free the list
11917 }
11918
11919 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11920 {
11921#define MAX_ARRAY_SIZE 64
11922 int i, array_size;
11923 char *p, *ch_str;
11924 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11925
11926 if(argc != 5)
11927 {
11928 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11929 exit(-1);
11930 }
11931 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11932
11933 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11934 {
11935 strtok_r(ch_str, ",", &p);
11936 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11937 }
11938 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11939 if(!array_size)
11940 array_size=1;//Need to print current channel statistics
11941 for(i=0; i<array_size; i++)
11942 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11943 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11944 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11945 input_output_channelStats_array[i].ch_number,\
11946 input_output_channelStats_array[i].ch_noise,\
11947 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11948 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11949 input_output_channelStats_array[i].ch_utilization_busy,\
11950 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11951 input_output_channelStats_array[i].ch_utilization_total);
11952 }
11953
11954 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11955 {
11956 if(argc <= 3 )
11957 {
11958 printf("Insufficient arguments \n");
11959 exit(-1);
11960 }
11961 char mac_addr[20] = {'\0'};
11962 wifi_device_t output_struct;
11963 int dev_index = atoi(argv[3]);
11964
11965 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11966 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11967 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);
11968 }
11969
11970 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11971 {
11972 if (argc <= 3)
11973 {
11974 printf("Insufficient arguments\n");
11975 exit(-1);
11976 }
11977 char args[256];
11978 wifi_NeighborReport_t *neighborReports;
11979
11980 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11981 if (!neighborReports)
11982 {
11983 printf("Failed to allocate memory");
11984 exit(-1);
11985 }
11986
11987 for (int i = 3; i < argc; ++i)
11988 {
11989 char *val;
11990 int j = 0;
11991 memset(args, 0, sizeof(args));
11992 strncpy(args, argv[i], sizeof(args));
11993 val = strtok(args, ";");
11994 while (val != NULL)
11995 {
11996 if (j == 0)
11997 {
11998 mac_addr_aton(neighborReports[i - 3].bssid, val);
11999 } else if (j == 1)
12000 {
12001 neighborReports[i - 3].info = strtol(val, NULL, 16);
12002 } else if (j == 2)
12003 {
12004 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12005 } else if (j == 3)
12006 {
12007 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12008 } else if (j == 4)
12009 {
12010 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12011 } else {
12012 printf("Insufficient arguments]n\n");
12013 exit(-1);
12014 }
12015 val = strtok(NULL, ";");
12016 j++;
12017 }
12018 }
12019
12020 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12021 if (ret != RETURN_OK)
12022 {
12023 printf("wifi_setNeighborReports ret = %d", ret);
12024 exit(-1);
12025 }
12026 }
12027 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12028 {
12029 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12030 printf("%s.\n", buf);
12031 else
12032 printf("Error returned\n");
12033 }
12034 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12035 {
12036 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12037 printf("%s.\n", buf);
12038 else
12039 printf("Error returned\n");
12040 }
12041 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12042 {
12043 if (argc <= 2)
12044 {
12045 printf("Insufficient arguments\n");
12046 exit(-1);
12047 }
12048 char buf[64]= {'\0'};
12049 wifi_getRadioOperatingChannelBandwidth(index,buf);
12050 printf("Current bandwidth is %s \n",buf);
12051 return 0;
12052 }
12053 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12054 {
12055 if (argc <= 5)
12056 {
12057 printf("Insufficient arguments\n");
12058 exit(-1);
12059 }
12060 UINT channel = atoi(argv[3]);
12061 UINT width = atoi(argv[4]);
12062 UINT beacon = atoi(argv[5]);
12063 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12064 printf("Result = %d", ret);
12065 }
12066
12067 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12068 return 0;
12069}
12070
12071#endif
12072
12073#ifdef WIFI_HAL_VERSION_3
12074
developer1e5aa162022-09-13 16:06:24 +080012075INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12076{
12077 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12078 if (bitMap & WIFI_BITRATE_1MBPS)
12079 strcat(BasicRate, "1,");
12080 if (bitMap & WIFI_BITRATE_2MBPS)
12081 strcat(BasicRate, "2,");
12082 if (bitMap & WIFI_BITRATE_5_5MBPS)
12083 strcat(BasicRate, "5.5,");
12084 if (bitMap & WIFI_BITRATE_6MBPS)
12085 strcat(BasicRate, "6,");
12086 if (bitMap & WIFI_BITRATE_9MBPS)
12087 strcat(BasicRate, "9,");
12088 if (bitMap & WIFI_BITRATE_11MBPS)
12089 strcat(BasicRate, "11,");
12090 if (bitMap & WIFI_BITRATE_12MBPS)
12091 strcat(BasicRate, "12,");
12092 if (bitMap & WIFI_BITRATE_18MBPS)
12093 strcat(BasicRate, "18,");
12094 if (bitMap & WIFI_BITRATE_24MBPS)
12095 strcat(BasicRate, "24,");
12096 if (bitMap & WIFI_BITRATE_36MBPS)
12097 strcat(BasicRate, "36,");
12098 if (bitMap & WIFI_BITRATE_48MBPS)
12099 strcat(BasicRate, "48,");
12100 if (bitMap & WIFI_BITRATE_54MBPS)
12101 strcat(BasicRate, "54,");
12102 if (strlen(BasicRate) != 0) // remove last comma
12103 BasicRate[strlen(BasicRate) - 1] = '\0';
12104 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12105 return RETURN_OK;
12106}
12107
12108INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12109{
12110 UINT BitMap = 0;
12111 char *rate;
12112
12113 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12114 rate = strtok(BasicRatesList, ",");
12115 while(rate != NULL)
12116 {
12117 if (strcmp(rate, "1") == 0)
12118 BitMap |= WIFI_BITRATE_1MBPS;
12119 else if (strcmp(rate, "2") == 0)
12120 BitMap |= WIFI_BITRATE_2MBPS;
12121 else if (strcmp(rate, "5.5") == 0)
12122 BitMap |= WIFI_BITRATE_5_5MBPS;
12123 else if (strcmp(rate, "6") == 0)
12124 BitMap |= WIFI_BITRATE_6MBPS;
12125 else if (strcmp(rate, "9") == 0)
12126 BitMap |= WIFI_BITRATE_9MBPS;
12127 else if (strcmp(rate, "11") == 0)
12128 BitMap |= WIFI_BITRATE_11MBPS;
12129 else if (strcmp(rate, "12") == 0)
12130 BitMap |= WIFI_BITRATE_12MBPS;
12131 else if (strcmp(rate, "18") == 0)
12132 BitMap |= WIFI_BITRATE_18MBPS;
12133 else if (strcmp(rate, "24") == 0)
12134 BitMap |= WIFI_BITRATE_24MBPS;
12135 else if (strcmp(rate, "36") == 0)
12136 BitMap |= WIFI_BITRATE_36MBPS;
12137 else if (strcmp(rate, "48") == 0)
12138 BitMap |= WIFI_BITRATE_48MBPS;
12139 else if (strcmp(rate, "54") == 0)
12140 BitMap |= WIFI_BITRATE_54MBPS;
12141 rate = strtok(NULL, ",");
12142 }
12143 *basicRateBitMap = BitMap;
12144 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12145 return RETURN_OK;
12146}
12147
developer7c4cd202023-03-01 10:56:29 +080012148INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12149{
12150 int center_channel = 0;
12151 char central_channel_str[16] = {0};
12152 char config_file[32] = {0};
12153 struct params param = {0};
12154
12155 center_channel = util_unii_6g_centerfreq("HT320", channel);
12156 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12157 if (channel >= 193)
12158 return RETURN_ERR;
12159 if (channel >= 33) {
12160 if (channel > center_channel)
12161 center_channel += 32;
12162 else
12163 center_channel -= 32;
12164 }
12165 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12166 if (channel <= 29)
12167 return RETURN_ERR;
12168 }
12169 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12170 param.name = "eht_oper_centr_freq_seg0_idx";
12171 param.value = central_channel_str;
12172 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12173 wifi_hostapdWrite(config_file, &param, 1);
12174
12175 return RETURN_OK;
12176}
12177
12178INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12179{
12180 int op_class = 0;
12181 char config_file[32] = {0};
12182 char op_class_str[8] = {0};
12183 struct params param = {0};
12184
12185 if (bandwidth == 20)
12186 op_class = 131;
12187 else if (bandwidth == 40)
12188 op_class = 132;
12189 else if (bandwidth == 80)
12190 op_class = 133;
12191 else if (bandwidth == 160)
12192 op_class = 134;
12193 else if (bandwidth == 320)
12194 op_class = 137;
12195 else
12196 return RETURN_ERR;
12197 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12198 param.name = "op_class";
12199 param.value = op_class_str;
12200 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12201 wifi_hostapdWrite(config_file, &param, 1);
12202 return RETURN_OK;
12203}
12204
12205INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12206{
12207 char config_file[32] = {0};
12208 char buf [16] = {0};
12209
12210 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12211 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12212 return RETURN_ERR; // 6g band should set op_class
12213 *class = (UINT)strtoul(buf, NULL, 10);
12214
12215 return RETURN_OK;
12216}
12217
developer1e5aa162022-09-13 16:06:24 +080012218// 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 +080012219INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12220{
developer1e5aa162022-09-13 16:06:24 +080012221 char buf[128] = {0};
12222 char cmd[128] = {0};
12223 char config_file[64] = {0};
12224 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012225 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012226 wifi_radio_operationParam_t current_param;
12227
12228 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12229
12230 multiple_set = TRUE;
12231 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12232 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12233 return RETURN_ERR;
12234 }
12235 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12236 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12237 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12238 return RETURN_ERR;
12239 }
12240 }
developer5884e982022-10-06 10:52:50 +080012241
12242 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12243 bandwidth = 20;
12244 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12245 bandwidth = 40;
12246 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12247 bandwidth = 80;
12248 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12249 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012250 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12251 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012252 if (operationParam->autoChannelEnabled){
12253 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12254 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12255 return RETURN_ERR;
12256 }
12257 }else{
developer1e5aa162022-09-13 16:06:24 +080012258 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12259 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12260 return RETURN_ERR;
12261 }
12262 }
developer5884e982022-10-06 10:52:50 +080012263
developer7c4cd202023-03-01 10:56:29 +080012264 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12265 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12266 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12267 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12268 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12269 return RETURN_ERR;
12270 }
12271 }
12272
12273 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12274 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12275 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12276 return RETURN_ERR;
12277 }
12278 }
12279
developer1e5aa162022-09-13 16:06:24 +080012280 if (current_param.variant != operationParam->variant) {
12281 // Two different definition bit map, so need to check every bit.
12282 if (operationParam->variant & WIFI_80211_VARIANT_A)
12283 set_mode |= WIFI_MODE_A;
12284 if (operationParam->variant & WIFI_80211_VARIANT_B)
12285 set_mode |= WIFI_MODE_B;
12286 if (operationParam->variant & WIFI_80211_VARIANT_G)
12287 set_mode |= WIFI_MODE_G;
12288 if (operationParam->variant & WIFI_80211_VARIANT_N)
12289 set_mode |= WIFI_MODE_N;
12290 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12291 set_mode |= WIFI_MODE_AC;
12292 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12293 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012294 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12295 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012296 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12297 memset(buf, 0, sizeof(buf));
12298 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12299 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12300 return RETURN_ERR;
12301 }
12302 }
12303 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12304 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12305 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12306 return RETURN_ERR;
12307 }
12308 }
12309 if (current_param.beaconInterval != operationParam->beaconInterval) {
12310 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12311 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12312 return RETURN_ERR;
12313 }
12314 }
12315 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12316 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12317 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12318 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12319 return RETURN_ERR;
12320 }
12321 }
12322 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12323 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12324 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12325 return RETURN_ERR;
12326 }
12327 }
12328 if (current_param.guardInterval != operationParam->guardInterval) {
12329 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12330 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12331 return RETURN_ERR;
12332 }
12333 }
12334 if (current_param.transmitPower != operationParam->transmitPower) {
12335 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12336 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12337 return RETURN_ERR;
12338 }
12339 }
12340 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12341 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12342 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12343 return RETURN_ERR;
12344 }
12345 }
12346 if (current_param.obssCoex != operationParam->obssCoex) {
12347 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12348 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12349 return RETURN_ERR;
12350 }
12351 }
12352 if (current_param.stbcEnable != operationParam->stbcEnable) {
12353 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12354 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12355 return RETURN_ERR;
12356 }
12357 }
12358 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12359 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12360 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12361 return RETURN_ERR;
12362 }
12363 }
12364
12365 // if enable is true, then restart the radio
12366 wifi_setRadioEnable(index, FALSE);
12367 if (operationParam->enable == TRUE)
12368 wifi_setRadioEnable(index, TRUE);
12369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12370
developer06a01d92022-09-07 16:32:39 +080012371 return RETURN_OK;
12372}
12373
12374INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12375{
developer1e5aa162022-09-13 16:06:24 +080012376 char band[64] = {0};
12377 char buf[256] = {0};
12378 char config_file[64] = {0};
12379 char cmd[128] = {0};
12380 int ret = RETURN_ERR;
12381 int mode = 0;
12382 ULONG channel = 0;
12383 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012384
12385 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12386 printf("Entering %s index = %d\n", __func__, (int)index);
12387
developer1e5aa162022-09-13 16:06:24 +080012388 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12389 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12390 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012391 {
developer1e5aa162022-09-13 16:06:24 +080012392 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012393 return RETURN_ERR;
12394 }
12395 operationParam->enable = enabled;
12396
12397 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012398 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012399 {
developer1e5aa162022-09-13 16:06:24 +080012400 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012401 return RETURN_ERR;
12402 }
12403
12404 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012405 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012406 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012407 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012408 else if (!strcmp(band, "6GHz"))
12409 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012410 else
12411 {
developer1e5aa162022-09-13 16:06:24 +080012412 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012413 band);
12414 }
12415
developer1e5aa162022-09-13 16:06:24 +080012416 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12417 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12418 operationParam->channel = 0;
12419 operationParam->autoChannelEnabled = TRUE;
12420 } else {
12421 operationParam->channel = strtol(buf, NULL, 10);
12422 operationParam->autoChannelEnabled = FALSE;
12423 }
12424
developer06a01d92022-09-07 16:32:39 +080012425 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012426 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12427 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12428 return RETURN_ERR;
12429 }
developer06a01d92022-09-07 16:32:39 +080012430 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12431 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12432 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012433 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012434 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12435 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012436 else
12437 {
developer1e5aa162022-09-13 16:06:24 +080012438 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12439 return false;
developer06a01d92022-09-07 16:32:39 +080012440 }
12441
developer7c4cd202023-03-01 10:56:29 +080012442 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12443 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12444 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12445 return RETURN_ERR;
12446 }
12447 }
12448
developer1e5aa162022-09-13 16:06:24 +080012449 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12450 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12451 return RETURN_ERR;
12452 }
12453 // Two different definition bit map, so need to check every bit.
12454 if (mode & WIFI_MODE_A)
12455 operationParam->variant |= WIFI_80211_VARIANT_A;
12456 if (mode & WIFI_MODE_B)
12457 operationParam->variant |= WIFI_80211_VARIANT_B;
12458 if (mode & WIFI_MODE_G)
12459 operationParam->variant |= WIFI_80211_VARIANT_G;
12460 if (mode & WIFI_MODE_N)
12461 operationParam->variant |= WIFI_80211_VARIANT_N;
12462 if (mode & WIFI_MODE_AC)
12463 operationParam->variant |= WIFI_80211_VARIANT_AC;
12464 if (mode & WIFI_MODE_AX)
12465 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012466 if (mode & WIFI_MODE_BE)
12467 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012468 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12469 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12470 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012471 }
developer1e5aa162022-09-13 16:06:24 +080012472 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12473 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12474 return RETURN_ERR;
12475 }
12476 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12477 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12478 return RETURN_ERR;
12479 }
developer06a01d92022-09-07 16:32:39 +080012480
developer1e5aa162022-09-13 16:06:24 +080012481 memset(buf, 0, sizeof(buf));
12482 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12483 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12484 return RETURN_ERR;
12485 }
12486 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12487
12488 memset(buf, 0, sizeof(buf));
12489 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12490 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12491 return RETURN_ERR;
12492 }
12493 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12494
12495 memset(buf, 0, sizeof(buf));
12496 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12497 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12498
12499 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12500 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12501 return RETURN_ERR;
12502 }
12503 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12504 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12505 return RETURN_ERR;
12506 }
12507
12508 memset(buf, 0, sizeof(buf));
12509 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12510 if (strcmp(buf, "-1") == 0) {
12511 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12512 operationParam->ctsProtection = FALSE;
12513 } else {
12514 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12515 operationParam->ctsProtection = TRUE;
12516 }
12517
12518 memset(buf, 0, sizeof(buf));
12519 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12520 if (strcmp(buf, "0") == 0)
12521 operationParam->obssCoex = FALSE;
12522 else
12523 operationParam->obssCoex = TRUE;
12524
12525 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12526 _syscmd(cmd, buf, sizeof(buf));
12527 if (strlen(buf) != 0)
12528 operationParam->stbcEnable = TRUE;
12529 else
12530 operationParam->stbcEnable = FALSE;
12531
12532 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12533 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12534 return RETURN_ERR;
12535 }
12536
12537 // Below value is hardcoded
12538
12539 operationParam->numSecondaryChannels = 0;
12540 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12541 operationParam->channelSecondary[i] = 0;
12542 }
12543 operationParam->csa_beacon_count = 15;
12544 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012545
12546 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12547 return RETURN_OK;
12548}
12549
12550static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12551{
developerc086fb72022-10-04 10:18:22 +080012552 int max_radio_num = 0;
12553
12554 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012555 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012556 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12557 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012558 }
12559
developerc086fb72022-10-04 10:18:22 +080012560 return (arrayIndex * max_radio_num) + radioIndex;
12561}
developer06a01d92022-09-07 16:32:39 +080012562
developerc086fb72022-10-04 10:18:22 +080012563wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12564 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12565 return WIFI_BITRATE_1MBPS;
12566 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12567 return WIFI_BITRATE_2MBPS;
12568 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12569 return WIFI_BITRATE_5_5MBPS;
12570 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12571 return WIFI_BITRATE_6MBPS;
12572 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12573 return WIFI_BITRATE_9MBPS;
12574 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12575 return WIFI_BITRATE_11MBPS;
12576 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12577 return WIFI_BITRATE_12MBPS;
12578 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12579 return WIFI_BITRATE_18MBPS;
12580 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12581 return WIFI_BITRATE_24MBPS;
12582 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12583 return WIFI_BITRATE_36MBPS;
12584 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12585 return WIFI_BITRATE_48MBPS;
12586 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12587 return WIFI_BITRATE_54MBPS;
12588 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012589}
12590
developer1d57d002022-10-12 18:03:15 +080012591INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12592{
12593 if (beacon == WIFI_BITRATE_1MBPS)
12594 strcpy(beacon_str, "1Mbps");
12595 else if (beacon == WIFI_BITRATE_2MBPS)
12596 strcpy(beacon_str, "2Mbps");
12597 else if (beacon == WIFI_BITRATE_5_5MBPS)
12598 strcpy(beacon_str, "5.5Mbps");
12599 else if (beacon == WIFI_BITRATE_6MBPS)
12600 strcpy(beacon_str, "6Mbps");
12601 else if (beacon == WIFI_BITRATE_9MBPS)
12602 strcpy(beacon_str, "9Mbps");
12603 else if (beacon == WIFI_BITRATE_11MBPS)
12604 strcpy(beacon_str, "11Mbps");
12605 else if (beacon == WIFI_BITRATE_12MBPS)
12606 strcpy(beacon_str, "12Mbps");
12607 else if (beacon == WIFI_BITRATE_18MBPS)
12608 strcpy(beacon_str, "18Mbps");
12609 else if (beacon == WIFI_BITRATE_24MBPS)
12610 strcpy(beacon_str, "24Mbps");
12611 else if (beacon == WIFI_BITRATE_36MBPS)
12612 strcpy(beacon_str, "36Mbps");
12613 else if (beacon == WIFI_BITRATE_48MBPS)
12614 strcpy(beacon_str, "48Mbps");
12615 else if (beacon == WIFI_BITRATE_54MBPS)
12616 strcpy(beacon_str, "54Mbps");
12617 return RETURN_OK;
12618}
12619
developer06a01d92022-09-07 16:32:39 +080012620INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12621{
developerc086fb72022-10-04 10:18:22 +080012622 INT mode = 0;
12623 INT ret = -1;
12624 INT output = 0;
12625 int i = 0;
12626 int vap_index = 0;
12627 BOOL enabled = FALSE;
12628 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012629 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012630
developer06a01d92022-09-07 16:32:39 +080012631
12632 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12633 printf("Entering %s index = %d\n", __func__, (int)index);
12634
developera77d84b2023-02-22 16:10:50 +080012635 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012636 {
developerc086fb72022-10-04 10:18:22 +080012637 map->vap_array[i].radio_index = index;
12638
developer06a01d92022-09-07 16:32:39 +080012639 vap_index = array_index_to_vap_index(index, i);
12640 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012641 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012642
developerc086fb72022-10-04 10:18:22 +080012643 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012644
12645 map->vap_array[i].vap_index = vap_index;
12646
12647 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012648 ret = wifi_getApName(vap_index, buf);
12649 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012650 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12651
developerc086fb72022-10-04 10:18:22 +080012652 return RETURN_ERR;
12653 }
12654 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12655
12656 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012657 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012658 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012659 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012660 return RETURN_ERR;
12661 }
12662 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 +080012663
12664 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012665 if (ret != RETURN_OK) {
12666 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012667 return RETURN_ERR;
12668 }
12669 map->vap_array[i].u.bss_info.enabled = enabled;
12670
developerc086fb72022-10-04 10:18:22 +080012671 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12672 if (ret != RETURN_OK) {
12673 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12674 return RETURN_ERR;
12675 }
developer06a01d92022-09-07 16:32:39 +080012676 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012677
12678 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12679 if (ret != RETURN_OK) {
12680 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12681 return RETURN_ERR;
12682 }
12683 map->vap_array[i].u.bss_info.isolation = enabled;
12684
12685 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12686 if (ret != RETURN_OK) {
12687 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12688 return RETURN_ERR;
12689 }
12690 map->vap_array[i].u.bss_info.bssMaxSta = output;
12691
12692 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12693 if (ret != RETURN_OK) {
12694 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12695 return RETURN_ERR;
12696 }
12697 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012698
developerc086fb72022-10-04 10:18:22 +080012699 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12700 if (ret != RETURN_OK) {
12701 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12702 return RETURN_ERR;
12703 }
12704 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012705
developerc086fb72022-10-04 10:18:22 +080012706 ret = wifi_getApSecurity(vap_index, &security);
12707 if (ret != RETURN_OK) {
12708 printf("%s: wifi_getApSecurity return error\n", __func__);
12709 return RETURN_ERR;
12710 }
12711 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012712
developerc086fb72022-10-04 10:18:22 +080012713 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12714 if (ret != RETURN_OK) {
12715 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12716 return RETURN_ERR;
12717 }
12718 if (mode == 0)
12719 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12720 else
12721 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12722 if (mode == 1)
12723 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12724 else if (mode == 2)
12725 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012726
developerc086fb72022-10-04 10:18:22 +080012727 ret = wifi_getApWmmEnable(vap_index, &enabled);
12728 if (ret != RETURN_OK) {
12729 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12730 return RETURN_ERR;
12731 }
12732 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012733
developerc086fb72022-10-04 10:18:22 +080012734 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12735 if (ret != RETURN_OK) {
12736 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012737 return RETURN_ERR;
12738 }
developerc086fb72022-10-04 10:18:22 +080012739 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012740
12741 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012742 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012743 if (ret != RETURN_OK) {
12744 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12745 return RETURN_ERR;
12746 }
12747 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012748
developerc086fb72022-10-04 10:18:22 +080012749 memset(buf, 0, sizeof(buf));
12750 ret = wifi_getBaseBSSID(vap_index, buf);
12751 if (ret != RETURN_OK) {
12752 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12753 return RETURN_ERR;
12754 }
12755 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12756 &map->vap_array[i].u.bss_info.bssid[0],
12757 &map->vap_array[i].u.bss_info.bssid[1],
12758 &map->vap_array[i].u.bss_info.bssid[2],
12759 &map->vap_array[i].u.bss_info.bssid[3],
12760 &map->vap_array[i].u.bss_info.bssid[4],
12761 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012762 // 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]);
12763
12764 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12765 if (ret != RETURN_OK) {
12766 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12767 return RETURN_ERR;
12768 }
12769 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developera77d84b2023-02-22 16:10:50 +080012770 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080012771 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012772 }
12773 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12774 return RETURN_OK;
12775}
12776
developer431128d2022-12-16 15:30:41 +080012777void checkVapStatus(int apIndex, bool *enable)
12778{
12779 char if_name[16] = {0};
12780 char cmd[128] = {0};
12781 char buf[128] = {0};
12782
12783 *enable = FALSE;
developerac6f1142022-12-20 19:26:35 +080012784 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
developer431128d2022-12-16 15:30:41 +080012785 return;
12786
12787 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12788 _syscmd(cmd, buf, sizeof(buf));
12789 if (strlen(buf) > 0)
12790 *enable = TRUE;
12791 return;
12792}
12793
developerd946fd62022-12-08 18:03:28 +080012794static int prepareInterface(UINT apIndex, char *new_interface)
12795{
12796 char cur_interface[16] = {0};
12797 char config_file[128] = {0};
12798 char cmd[128] = {0};
12799 char buf[16] = {0};
12800 int max_radio_num = 0;
12801 int radioIndex = -1;
12802 int phyIndex = -1;
12803
12804 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12805 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12806
12807 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12808 wifi_getMaxRadioNumber(&max_radio_num);
12809 radioIndex = apIndex % max_radio_num;
12810 phyIndex = radio_index_to_phy(radioIndex);
12811 // disable and del old interface, then add new interface
12812 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080012813 if (!(apIndex/max_radio_num)) {
12814 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
12815 _syscmd(cmd, buf, sizeof(buf));
12816 }
developerd946fd62022-12-08 18:03:28 +080012817 }
developer431128d2022-12-16 15:30:41 +080012818 // update the vap status file
12819 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12820 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012821 return RETURN_OK;
12822}
12823
developer06a01d92022-09-07 16:32:39 +080012824INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12825{
developerd946fd62022-12-08 18:03:28 +080012826 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012827 unsigned int i;
12828 wifi_vap_info_t *vap_info = NULL;
12829 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012830 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012831 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012832 char buf[256] = {0};
12833 char cmd[128] = {0};
12834 char config_file[64] = {0};
12835 char bssid[32] = {0};
12836 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012837 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012838
12839 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12840 printf("Entering %s index = %d\n", __func__, (int)index);
12841 for (i = 0; i < map->num_vaps; i++)
12842 {
developer1d57d002022-10-12 18:03:15 +080012843 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012844 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012845
12846 // Check vap status file to enable multiple ap if the system boot.
12847 checkVapStatus(vap_info->vap_index, &enable);
12848 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012849 continue;
developer06a01d92022-09-07 16:32:39 +080012850
developer1d57d002022-10-12 18:03:15 +080012851 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12852
developer431128d2022-12-16 15:30:41 +080012853 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12854 enable = FALSE;
12855
12856 // multi-ap first up need to copy current radio config
12857 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012858 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12859 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012860 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12861 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12862 } else {
12863 // Check whether the interface name is valid or this ap change it.
12864 int apIndex = -1;
12865 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12866 if (apIndex != -1 && apIndex != vap_info->vap_index)
12867 continue;
12868 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012869 }
developer06a01d92022-09-07 16:32:39 +080012870
developer1d57d002022-10-12 18:03:15 +080012871 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012872 params[0].name = "interface";
12873 params[0].value = vap_info->vap_name;
12874 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12875 params[1].name = "bssid";
12876 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012877 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012878 params[2].name = "wpa_psk_file";
12879 params[2].value = psk_file;
12880
12881 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12882 wifi_hostapdWrite(config_file, params, 3);
12883
12884 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12885 _syscmd(cmd, buf, sizeof(buf));
12886
12887 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12888 if (ret != RETURN_OK) {
12889 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12890 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012891 }
developer1d57d002022-10-12 18:03:15 +080012892
12893 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12894 if (ret != RETURN_OK) {
12895 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12896 return RETURN_ERR;
12897 }
12898
12899 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12900 if (ret != RETURN_OK) {
12901 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12902 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012903 }
12904
developer1d57d002022-10-12 18:03:15 +080012905 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12906 if (ret != RETURN_OK) {
12907 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12908 return RETURN_ERR;
12909 }
developer06a01d92022-09-07 16:32:39 +080012910
developer1d57d002022-10-12 18:03:15 +080012911 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12912 if (ret != RETURN_OK) {
12913 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12914 return RETURN_ERR;
12915 }
developer06a01d92022-09-07 16:32:39 +080012916
developer1d57d002022-10-12 18:03:15 +080012917 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12918 if (ret != RETURN_OK) {
12919 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12920 return RETURN_ERR;
12921 }
12922
developer804c64f2022-10-19 13:54:40 +080012923 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012924 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012925 }else {
12926 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012927 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012928 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12929 _syscmd(cmd, buf, sizeof(buf));
12930 }else{
developer1d57d002022-10-12 18:03:15 +080012931 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012932 }
developer1d57d002022-10-12 18:03:15 +080012933 }
12934
12935 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12936 if (ret != RETURN_OK) {
12937 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12938 return RETURN_ERR;
12939 }
12940
12941 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12942 if (ret != RETURN_OK) {
12943 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12944 return RETURN_ERR;
12945 }
12946
12947 memset(buf, 0, sizeof(buf));
12948 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12949 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12950 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12951 if (ret != RETURN_OK) {
12952 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12953 return RETURN_ERR;
12954 }
12955
12956 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12957 if (ret != RETURN_OK) {
12958 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12959 return RETURN_ERR;
12960 }
12961
developer1d57d002022-10-12 18:03:15 +080012962 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12963 if (ret != RETURN_OK) {
12964 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12965 return RETURN_ERR;
12966 }
12967
12968 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12969 if (ret != RETURN_OK) {
12970 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12971 return RETURN_ERR;
12972 }
developer06a01d92022-09-07 16:32:39 +080012973
developer2f995fb2023-02-24 10:40:44 +080012974 wifi_setApEnable(vap_info->vap_index, FALSE);
12975 wifi_setApEnable(vap_info->vap_index, TRUE);
12976 multiple_set = FALSE;
12977
12978 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12979
developer1d57d002022-10-12 18:03:15 +080012980 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012981 }
12982 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12983 return RETURN_OK;
12984}
12985
12986int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12987{
12988 char *token, *next;
12989 const char s[2] = ",";
12990 int count =0;
12991
12992 /* get the first token */
12993 token = strtok_r(pchannels, s, &next);
12994
12995 /* walk through other tokens */
12996 while( token != NULL && count < MAX_CHANNELS) {
12997 chlistptr->channels_list[count++] = atoi(token);
12998 token = strtok_r(NULL, s, &next);
12999 }
13000
13001 return count;
13002}
13003
13004static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13005{
13006 INT status;
13007 wifi_channels_list_t *chlistp;
13008 CHAR output_string[64];
13009 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013010 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013011 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013012
13013 if(rcap == NULL)
13014 {
13015 return RETURN_ERR;
13016 }
13017
13018 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013019 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013020
developer1e5aa162022-09-13 16:06:24 +080013021 if (band == band_2_4)
13022 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13023 else if (band == band_5)
13024 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13025 else if (band == band_6)
13026 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013027
13028 chlistp = &(rcap->channel_list[0]);
13029 memset(pchannels, 0, sizeof(pchannels));
13030
13031 /* possible number of radio channels */
13032 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13033 {
13034 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13035 }
13036 /* Number of channels and list*/
13037 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13038
13039 /* autoChannelSupported */
13040 /* always ON with wifi_getRadioAutoChannelSupported */
13041 rcap->autoChannelSupported = TRUE;
13042
13043 /* DCSSupported */
13044 /* always ON with wifi_getRadioDCSSupported */
13045 rcap->DCSSupported = TRUE;
13046
13047 /* zeroDFSSupported - TBD */
13048 rcap->zeroDFSSupported = FALSE;
13049
13050 /* Supported Country List*/
13051 memset(output_string, 0, sizeof(output_string));
13052 status = wifi_getRadioCountryCode(radioIndex, output_string);
13053 if( status != 0 ) {
13054 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13055 return RETURN_ERR;
13056 } else {
13057 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13058 }
13059 if(!strcmp(output_string,"US")){
13060 rcap->countrySupported[0] = wifi_countrycode_US;
13061 rcap->countrySupported[1] = wifi_countrycode_CA;
13062 } else if (!strcmp(output_string,"CA")) {
13063 rcap->countrySupported[0] = wifi_countrycode_CA;
13064 rcap->countrySupported[1] = wifi_countrycode_US;
13065 } else {
13066 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13067 }
13068
13069 rcap->numcountrySupported = 2;
13070
13071 /* csi */
13072 rcap->csi.maxDevices = 8;
13073 rcap->csi.soudingFrameSupported = TRUE;
13074
developer7930d352022-12-21 17:55:42 +080013075 wifi_GetInterfaceName(radioIndex, interface_name);
13076 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013077
13078 /* channelWidth - all supported bandwidths */
13079 int i=0;
13080 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013081
13082 /* mode - all supported variants */
13083 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13084 wifi_getRadioSupportedStandards(radioIndex, output_string);
13085
developer06a01d92022-09-07 16:32:39 +080013086 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13087 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13088 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013089 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013090
developer7c4cd202023-03-01 10:56:29 +080013091 if (strstr(output_string, "n") != NULL)
13092 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13093 if (strstr(output_string, "ax") != NULL)
13094 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13095 if (strstr(output_string, "be") != NULL)
13096 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13097 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013098 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13099 WIFI_CHANNELBANDWIDTH_40MHZ |
13100 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013101 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013102
developer7c4cd202023-03-01 10:56:29 +080013103 if (strstr(output_string, "n") != NULL)
13104 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13105 if (strstr(output_string, "ac") != NULL)
13106 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13107 if (strstr(output_string, "ax") != NULL)
13108 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13109 if (strstr(output_string, "be") != NULL)
13110 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13111 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13112 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13113 WIFI_CHANNELBANDWIDTH_40MHZ |
13114 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013115 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013116
13117 if (strstr(output_string, "be") != NULL) {
13118 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13119 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13120 }
developer06a01d92022-09-07 16:32:39 +080013121 }
developer7c4cd202023-03-01 10:56:29 +080013122
developer06a01d92022-09-07 16:32:39 +080013123 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13124 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13125
13126 /* supportedBitRate - all supported bitrates */
13127 rcap->supportedBitRate[i] = 0;
13128 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13129 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13130 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13131 }
developer1e5aa162022-09-13 16:06:24 +080013132 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013133 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13134 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13135 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13136 }
13137
13138
13139 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13140 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13141 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13142 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13143 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13144 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13145 rcap->cipherSupported = 0;
13146 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13147 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13148
13149 return RETURN_OK;
13150}
13151
13152INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13153{
developer30423732022-12-01 16:17:49 +080013154 INT status = 0, radioIndex = 0;
13155 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013156 int iter = 0;
developer30423732022-12-01 16:17:49 +080013157 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013158 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013159 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013160
13161 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13162
13163 memset(cap, 0, sizeof(wifi_hal_capability_t));
13164
13165 /* version */
13166 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13167 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13168
13169 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013170 wifi_getMaxRadioNumber(&max_num_radios);
13171 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013172
13173 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13174 {
13175 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13176 if (status != 0) {
13177 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13178 return RETURN_ERR;
13179 }
13180
13181 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13182 {
developer804c64f2022-10-19 13:54:40 +080013183 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013184 {
13185 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13186 return RETURN_ERR;
13187 }
13188 iface_info = &cap->wifi_prop.interface_map[iter];
13189 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13190 iface_info->rdk_radio_index = radioIndex;
13191 memset(output, 0, sizeof(output));
13192 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13193 {
13194 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13195 }
13196 // TODO: bridge name
13197 // TODO: vlan id
13198 // TODO: primary
13199 iface_info->index = array_index_to_vap_index(radioIndex, j);
13200 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013201 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013202 {
13203 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13204 }
13205 iter++;
13206 }
13207 }
13208
13209 cap->BandSteeringSupported = FALSE;
13210 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13211 return RETURN_OK;
13212}
13213
developer9df4e652022-10-11 11:27:38 +080013214INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13215{
13216 struct params h_config={0};
13217 char config_file[64] = {0};
13218
13219 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13220
13221 h_config.name = "okc";
13222 h_config.value = okc_enable?"1":"0";
13223
13224 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13225 wifi_hostapdWrite(config_file, &h_config, 1);
13226 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13227
13228 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13229 return RETURN_OK;
13230}
13231
13232INT wifi_setSAEMFP(int ap_index, BOOL enable)
13233{
13234 struct params h_config={0};
13235 char config_file[64] = {0};
13236 char buf[128] = {0};
13237
13238 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13239
13240 h_config.name = "sae_require_mfp";
13241 h_config.value = enable?"1":"0";
13242
13243 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13244 wifi_hostapdWrite(config_file, &h_config, 1);
13245 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13246
13247 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13248 return RETURN_OK;
13249}
13250
13251INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13252{
13253 struct params h_config={0};
13254 char config_file[64] = {0};
13255 char buf[128] = {0};
13256
13257 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13258
13259 h_config.name = "sae_pwe";
13260 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13261 h_config.value = buf;
13262
13263 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13264 wifi_hostapdWrite(config_file, &h_config, 1);
13265 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13266
13267 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13268 return RETURN_OK;
13269}
13270
13271INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13272{
13273 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13274 struct params h_config={0};
13275 char config_file[64] = {0};
13276
13277 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13278
13279 h_config.name = "wpa_disable_eapol_key_retries";
13280 h_config.value = disable_EAPOL_retries?"1":"0";
13281
13282 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13283 wifi_hostapdWrite(config_file, &h_config, 1);
13284 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13285
13286 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13287 return RETURN_OK;
13288}
13289
developer06a01d92022-09-07 16:32:39 +080013290INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13291{
developer587c1b62022-09-27 15:58:59 +080013292 char buf[128] = {0};
13293 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013294 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013295 char password[64] = {0};
13296 char mfp[32] = {0};
13297 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013298 BOOL okc_enable = FALSE;
13299 BOOL sae_MFP = FALSE;
13300 BOOL disable_EAPOL_retries = TRUE;
13301 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013302 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013303 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013304
13305 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13306
13307 multiple_set = TRUE;
13308 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13309 if (security->mode == wifi_security_mode_none) {
13310 strcpy(wpa_mode, "None");
13311 } else if (security->mode == wifi_security_mode_wpa_personal)
13312 strcpy(wpa_mode, "WPA-Personal");
13313 else if (security->mode == wifi_security_mode_wpa2_personal)
13314 strcpy(wpa_mode, "WPA2-Personal");
13315 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13316 strcpy(wpa_mode, "WPA-WPA2-Personal");
13317 else if (security->mode == wifi_security_mode_wpa_enterprise)
13318 strcpy(wpa_mode, "WPA-Enterprise");
13319 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13320 strcpy(wpa_mode, "WPA2-Enterprise");
13321 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13322 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013323 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013324 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013325 okc_enable = TRUE;
13326 sae_MFP = TRUE;
13327 sae_pwe = 2;
13328 disable_EAPOL_retries = FALSE;
13329 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013330 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013331 okc_enable = TRUE;
13332 sae_MFP = TRUE;
13333 sae_pwe = 2;
13334 disable_EAPOL_retries = FALSE;
13335 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013336 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013337 sae_MFP = TRUE;
13338 sae_pwe = 2;
13339 disable_EAPOL_retries = FALSE;
developer5c9fee82023-01-13 14:44:16 +080013340 } else if (security->mode == wifi_security_mode_owe) {
13341 strcpy(wpa_mode, "OWE");
13342 sae_MFP = TRUE;
13343 sae_pwe = 2;
13344 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013345 }
13346
13347 band = wifi_index_to_band(ap_index);
13348 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13349 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13350 return RETURN_ERR;
13351 }
developer587c1b62022-09-27 15:58:59 +080013352
13353 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013354 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013355 wifi_setSAEMFP(ap_index, sae_MFP);
13356 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013357 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013358
developer23e71282023-01-18 10:25:19 +080013359 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_owe) {
developer4b102122023-02-15 10:53:03 +080013360 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) {
13361 int key_len = strlen(security->u.key.key);
13362 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13363 if (key_len == 64) { // set wpa_psk
13364 strncpy(password, security->u.key.key, 64); // 64 characters
13365 password[64] = '\0';
13366 wifi_setApSecurityPreSharedKey(ap_index, password);
13367 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13368 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13369 strncpy(password, security->u.key.key, 63);
13370 password[63] = '\0';
13371 wifi_setApSecurityKeyPassphrase(ap_index, password);
13372 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13373 } else
13374 return RETURN_ERR;
13375 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013376 }
13377 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13378 params.name = "sae_password";
13379 params.value = security->u.key.key;
13380 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013381 } else { // remove sae_password
13382 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13383 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013384 }
13385 }
developer587c1b62022-09-27 15:58:59 +080013386
13387 if (security->mode != wifi_security_mode_none) {
13388 memset(&params, 0, sizeof(params));
13389 params.name = "wpa_pairwise";
13390 if (security->encr == wifi_encryption_tkip)
13391 params.value = "TKIP";
13392 else if (security->encr == wifi_encryption_aes)
13393 params.value = "CCMP";
13394 else if (security->encr == wifi_encryption_aes_tkip)
13395 params.value = "TKIP CCMP";
13396 wifi_hostapdWrite(config_file, &params, 1);
13397 }
13398
13399 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013400 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013401 else if (security->mfp == wifi_mfp_cfg_optional)
13402 strcpy(mfp, "Optional");
13403 else if (security->mfp == wifi_mfp_cfg_required)
13404 strcpy(mfp, "Required");
13405 wifi_setApSecurityMFPConfig(ap_index, mfp);
13406
13407 memset(&params, 0, sizeof(params));
13408 params.name = "transition_disable";
13409 if (security->wpa3_transition_disable == TRUE)
13410 params.value = "0x01";
13411 else
13412 params.value = "0x00";
13413 wifi_hostapdWrite(config_file, &params, 1);
13414
13415 memset(&params, 0, sizeof(params));
13416 params.name = "wpa_group_rekey";
13417 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13418 params.value = buf;
13419 wifi_hostapdWrite(config_file, &params, 1);
13420
13421 memset(&params, 0, sizeof(params));
13422 params.name = "wpa_strict_rekey";
13423 params.value = security->strict_rekey?"1":"0";
13424 wifi_hostapdWrite(config_file, &params, 1);
13425
13426 memset(&params, 0, sizeof(params));
13427 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013428 if (security->eapol_key_retries == 0)
13429 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013430 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13431 params.value = buf;
13432 wifi_hostapdWrite(config_file, &params, 1);
13433
13434 memset(&params, 0, sizeof(params));
13435 params.name = "disable_pmksa_caching";
13436 params.value = security->disable_pmksa_caching?"1":"0";
13437 wifi_hostapdWrite(config_file, &params, 1);
13438
developer23e71282023-01-18 10:25:19 +080013439 if (multiple_set == FALSE) {
13440 wifi_setApEnable(ap_index, FALSE);
13441 wifi_setApEnable(ap_index, TRUE);
13442 }
developer587c1b62022-09-27 15:58:59 +080013443
13444 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13445
developer06a01d92022-09-07 16:32:39 +080013446 return RETURN_OK;
13447}
13448
13449INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13450{
developer9df4e652022-10-11 11:27:38 +080013451 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013452 char config_file[128] = {0};
13453 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013454 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013455
13456 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13457 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13458 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13459 security->mode = wifi_security_mode_none;
13460 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013461 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013462 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013463 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013464 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013465 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013466 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013467 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013468 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013469 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013470 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013471 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013472 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013473 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013474 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013475 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013476 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013477 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013478 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013479 else if (!strcmp(buf, "OWE"))
13480 security->mode = wifi_security_mode_owe;
developer587c1b62022-09-27 15:58:59 +080013481 }
13482
13483 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13484 if (security->mode == wifi_security_mode_none)
13485 security->encr = wifi_encryption_none;
13486 else {
13487 if (strcmp(buf, "TKIP") == 0)
13488 security->encr = wifi_encryption_tkip;
13489 else if (strcmp(buf, "CCMP") == 0)
13490 security->encr = wifi_encryption_aes;
13491 else
13492 security->encr = wifi_encryption_aes_tkip;
13493 }
13494
developer9df4e652022-10-11 11:27:38 +080013495 if (security->mode != wifi_encryption_none) {
13496 memset(buf, 0, sizeof(buf));
13497 // wpa3 can use one or both configs as password, so we check sae_password first.
13498 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013499 if (strlen(buf) != 0) {
13500 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13501 security->u.key.type = wifi_security_key_type_sae;
13502 set_sae = TRUE;
13503 strncpy(security->u.key.key, buf, sizeof(buf));
13504 }
13505 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13506 if (strlen(buf) != 0){
13507 if (set_sae == TRUE)
13508 security->u.key.type = wifi_security_key_type_psk_sae;
13509 else if (strlen(buf) == 64)
13510 security->u.key.type = wifi_security_key_type_psk;
13511 else
13512 security->u.key.type = wifi_security_key_type_pass;
13513 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013514 }
developer9df4e652022-10-11 11:27:38 +080013515 security->u.key.key[255] = '\0';
13516 }
13517
developer587c1b62022-09-27 15:58:59 +080013518 memset(buf, 0, sizeof(buf));
13519 wifi_getApSecurityMFPConfig(ap_index, buf);
13520 if (strcmp(buf, "Disabled") == 0)
13521 security->mfp = wifi_mfp_cfg_disabled;
13522 else if (strcmp(buf, "Optional") == 0)
13523 security->mfp = wifi_mfp_cfg_optional;
13524 else if (strcmp(buf, "Required") == 0)
13525 security->mfp = wifi_mfp_cfg_required;
13526
13527 memset(buf, 0, sizeof(buf));
13528 security->wpa3_transition_disable = FALSE;
13529 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13530 disable = strtol(buf, NULL, 16);
13531 if (disable != 0)
13532 security->wpa3_transition_disable = TRUE;
13533
13534 memset(buf, 0, sizeof(buf));
13535 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13536 if (strlen(buf) == 0)
13537 security->rekey_interval = 86400;
13538 else
13539 security->rekey_interval = strtol(buf, NULL, 10);
13540
13541 memset(buf, 0, sizeof(buf));
13542 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13543 if (strlen(buf) == 0)
13544 security->strict_rekey = 1;
13545 else
13546 security->strict_rekey = strtol(buf, NULL, 10);
13547
13548 memset(buf, 0, sizeof(buf));
13549 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13550 if (strlen(buf) == 0)
13551 security->eapol_key_retries = 4;
13552 else
13553 security->eapol_key_retries = strtol(buf, NULL, 10);
13554
13555 memset(buf, 0, sizeof(buf));
13556 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13557 if (strlen(buf) == 0)
13558 security->disable_pmksa_caching = FALSE;
13559 else
13560 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13561
13562 /* TODO
13563 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13564 */
13565 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13566 security->eap_identity_req_timeout = 0;
13567 security->eap_identity_req_retries = 0;
13568 security->eap_req_timeout = 0;
13569 security->eap_req_retries = 0;
13570 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013571 return RETURN_OK;
13572}
13573
13574#endif /* WIFI_HAL_VERSION_3 */
13575
13576#ifdef WIFI_HAL_VERSION_3_PHASE2
13577INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13578{
developerd946fd62022-12-08 18:03:28 +080013579 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013580 char cmd[128] = {0};
13581 char buf[128] = {0};
13582 char *mac_addr = NULL;
13583 BOOL status = FALSE;
13584 size_t len = 0;
13585
13586 if(ap_index > MAX_APS)
13587 return RETURN_ERR;
13588
13589 *output_numDevices = 0;
13590 wifi_getApEnable(ap_index, &status);
13591 if (status == FALSE)
13592 return RETURN_OK;
13593
developerac6f1142022-12-20 19:26:35 +080013594 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013595 return RETURN_ERR;
13596 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013597 _syscmd(cmd, buf, sizeof(buf));
13598
13599 mac_addr = strtok(buf, "\n");
13600 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13601 *output_numDevices = i + 1;
13602 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13603 addr_ptr = output_deviceMacAddressArray[i];
13604 mac_addr_aton(addr_ptr, mac_addr);
13605 mac_addr = strtok(NULL, "\n");
13606 }
13607
13608 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013609}
13610#else
13611INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13612{
developerd946fd62022-12-08 18:03:28 +080013613 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013614 char cmd[128];
13615 BOOL status = false;
13616
13617 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13618 return RETURN_ERR;
13619
13620 output_buf[0] = '\0';
13621
13622 wifi_getApEnable(ap_index,&status);
13623 if (!status)
13624 return RETURN_OK;
13625
developerac6f1142022-12-20 19:26:35 +080013626 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013627 return RETURN_ERR;
13628 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013629 _syscmd(cmd, output_buf, output_buf_size);
13630
13631 return RETURN_OK;
13632}
13633#endif
developer2f513ab2022-09-13 14:26:06 +080013634
13635INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13636{
13637 char output[16]={'\0'};
13638 char config_file[MAX_BUF_SIZE] = {0};
13639
13640 if (!enable)
13641 return RETURN_ERR;
13642
13643 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13644 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13645
13646 if (strlen(output) == 0)
13647 *enable = FALSE;
13648 else if (strncmp(output, "1", 1) == 0)
13649 *enable = TRUE;
13650 else
13651 *enable = FALSE;
13652
13653 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13654 return RETURN_OK;
13655}
developer2d9c30f2022-09-13 15:06:14 +080013656
13657INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13658{
developer804c64f2022-10-19 13:54:40 +080013659 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013660 return RETURN_ERR;
13661 *output_enable=TRUE;
13662 return RETURN_OK;
13663}
developerfd7d2892022-09-13 16:44:53 +080013664
13665INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13666{
13667 char cmd[128] = {0};
13668 char buf[128] = {0};
13669 char line[128] = {0};
13670 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013671 FILE *f = NULL;
13672 int index = 0;
13673 int exp = 0;
13674 int mantissa = 0;
13675 int duration = 0;
13676 int radio_index = 0;
13677 int max_radio_num = 0;
13678 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013679 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013680 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13681
13682 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013683
developerfd7d2892022-09-13 16:44:53 +080013684 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013685
13686 phyId = radio_index_to_phy(radio_index);
13687 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013688 _syscmd(cmd, buf, sizeof(buf));
13689 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13690 if (*numSessionReturned > maxNumberSessions)
13691 *numSessionReturned = maxNumberSessions;
13692 else if (*numSessionReturned < 1) {
13693 *numSessionReturned = 0;
13694 return RETURN_OK;
13695 }
13696
developer033b37b2022-10-18 11:27:46 +080013697 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 +080013698 if ((f = popen(cmd, "r")) == NULL) {
13699 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13700 return RETURN_ERR;
13701 }
13702
13703 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013704 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013705 char *tmp = NULL;
13706 strcpy(buf, line);
13707 tmp = strtok(buf, " ");
13708 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13709 tmp = strtok(NULL, " ");
13710 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13711 tmp = strtok(NULL, " ");
13712 if (strstr(tmp, "t")) {
13713 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13714 }
13715 if (strstr(tmp, "a")) {
13716 twtSessions[index].twtParameters.operation.announced = TRUE;
13717 }
13718 tmp = strtok(NULL, " ");
13719 exp = strtol(tmp, NULL, 10);
13720 tmp = strtok(NULL, " ");
13721 mantissa = strtol(tmp, NULL, 10);
13722 tmp = strtok(NULL, " ");
13723 duration = strtol(tmp, NULL, 10);
13724
13725 // only implicit supported
13726 twtSessions[index].twtParameters.operation.implicit = TRUE;
13727 // only individual agreement supported
13728 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13729
13730 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13731 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013732 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013733 // Overflow handling
13734 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13735 } else {
13736 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13737 }
13738 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13739 index++;
13740 }
13741
13742 pclose(f);
13743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13744 return RETURN_OK;
13745}