blob: 3ca99b9111cd6e0b759d863765b3891ad93bcb1b [file] [log] [blame]
developer06a01d92022-09-07 16:32:39 +08001/*
2 * If not stated otherwise in this file or this component's LICENSE file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2019 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18*/
19
20/*
21* Material from the TR181 data model is Copyright (c) 2010-2017, Broadband Forum
22* Licensed under the BSD-3 license
23*/
24
25/*
26* This file includes material that is Copyright (c) 2020, Plume Design Inc.
27* Licensed under the BSD-3 license
28*/
29
30/* Code in rxStatsInfo_callback and other callbacks is credited as follows:
31Copyright (c) 2007, 2008 Johannes Berg
32Copyright (c) 2007 Andy Lutomirski
33Copyright (c) 2007 Mike Kershaw
34Copyright (c) 2008-2009 Luis R. Rodriguez
35Licensed under the ISC license
36*/
developerda1ed692022-09-13 13:59:20 +080037#define MTK_IMPL
developer06a01d92022-09-07 16:32:39 +080038#define HAL_NETLINK_IMPL
39#define _GNU_SOURCE /* needed for strcasestr */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <string.h>
45#include <fcntl.h>
46#include <stdbool.h>
47#include "wifi_hal.h"
48
49#ifdef HAL_NETLINK_IMPL
50#include <errno.h>
51#include <netlink/attr.h>
52#include <netlink/netlink.h>
53#include <netlink/genl/genl.h>
54#include <netlink/genl/family.h>
55#include <netlink/genl/ctrl.h>
56#include <linux/nl80211.h>
57#include<net/if.h>
58#endif
59
60#include <ev.h>
61#include <wpa_ctrl.h>
62#include <errno.h>
63#include <time.h>
64#define MAC_ALEN 6
65
developer7930d352022-12-21 17:55:42 +080066#define MAX_BUF_SIZE 256
67#define MAX_CMD_SIZE 256
68#define IF_NAME_SIZE 16
developer06a01d92022-09-07 16:32:39 +080069#define CONFIG_PREFIX "/nvram/hostapd"
developer431128d2022-12-16 15:30:41 +080070#define ACL_PREFIX "/nvram/hostapd-acl"
71#define DENY_PREFIX "/nvram/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080072//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
73#define SOCK_PREFIX "/var/run/hostapd/wifi"
developer431128d2022-12-16 15:30:41 +080074#define VAP_STATUS_FILE "/nvram/vap-status"
developera3c68b92022-09-13 15:27:29 +080075#define ESSID_FILE "/tmp/essid"
developer247302b2022-10-06 15:03:00 +080076#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080077#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080078#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080079#define VLAN_FILE "/nvram/hostapd.vlan"
developer431128d2022-12-16 15:30:41 +080080#define PSK_FILE "/nvram/hostapd"
developerf49437e2022-09-29 19:58:21 +080081#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080082#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080083
developer81bf2ed2022-09-13 15:31:14 +080084#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080085
86/*
87 MAX_APS - Number of all AP available in system
88 2x Home AP
89 2x Backhaul AP
90 2x Guest AP
91 2x Secure Onboard AP
92 2x Service AP
93
94*/
developer06a01d92022-09-07 16:32:39 +080095
developer033b37b2022-10-18 11:27:46 +080096
developera77d84b2023-02-22 16:10:50 +080097#define MAX_APS ((MAX_NUM_RADIOS)*(MAX_NUM_VAP_PER_RADIO))
developer06a01d92022-09-07 16:32:39 +080098#ifndef AP_PREFIX
99#define AP_PREFIX "wifi"
100#endif
101
102#ifndef RADIO_PREFIX
103#define RADIO_PREFIX "wlan"
104#endif
105
developer89df4502023-02-16 20:45:02 +0800106#define MAX_ASSOCIATED_STA_NUM 2007 // hostapd default
developer06a01d92022-09-07 16:32:39 +0800107
108//Uncomment to enable debug logs
109//#define WIFI_DEBUG
110
111#ifdef WIFI_DEBUG
112#define wifi_dbg_printf printf
113#define WIFI_ENTRY_EXIT_DEBUG printf
114#else
115#define wifi_dbg_printf(format, args...) printf("")
116#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
117#endif
118
119#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
120#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
121#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
122#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
123#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
124#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
125#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
126#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
127#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
128#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
129
developer4fb0b922022-09-30 14:29:09 +0800130#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800131
132#define BW_FNAME "/nvram/bw_file.txt"
133
134#define PS_MAX_TID 16
135
136static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
137 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
138 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
139 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
140 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
141 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
142 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
143 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
144 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
145 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
147 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
148 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
150 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
152 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
153};
154
155typedef unsigned long long u64;
156
157/* Enum to define WiFi Bands */
158typedef enum
159{
160 band_invalid = -1,
161 band_2_4 = 0,
162 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800163 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800164} wifi_band;
165
developerdb744382022-09-13 15:34:54 +0800166typedef enum {
167 WIFI_MODE_A = 0x01,
168 WIFI_MODE_B = 0x02,
169 WIFI_MODE_G = 0x04,
170 WIFI_MODE_N = 0x08,
171 WIFI_MODE_AC = 0x10,
172 WIFI_MODE_AX = 0x20,
developer7c4cd202023-03-01 10:56:29 +0800173 WIFI_MODE_BE = 0x40,
developerdb744382022-09-13 15:34:54 +0800174} wifi_ieee80211_Mode;
175
developer06a01d92022-09-07 16:32:39 +0800176#ifdef WIFI_HAL_VERSION_3
177
178// Return number of elements in array
179#ifndef ARRAY_SIZE
180#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
181#endif /* ARRAY_SIZE */
182
183#ifndef ARRAY_AND_SIZE
184#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
185#endif /* ARRAY_AND_SIZE */
186
187#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
188
189typedef struct {
190 int32_t value;
191 int32_t param;
192 intptr_t key;
193 intptr_t data;
194} wifi_secur_list;
195
developerfa41b1f2023-01-06 10:25:51 +0800196static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
197static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
developer72ec5572023-01-05 16:27:13 +0800198static int util_get_sec_chan_offset(int channel, const char* ht_mode);
developer06a01d92022-09-07 16:32:39 +0800199wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
200wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
201char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800202static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800203
204static wifi_secur_list map_security[] =
205{
206 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
207 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
208 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
209 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
210 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800214 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800216 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800217 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800218};
219
220wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
221{
222 wifi_secur_list *item;
223 int i;
224
225 for (item = list,i = 0;i < list_sz; item++, i++) {
226 if ((int)(item->key) == key) {
227 return item;
228 }
229 }
230
231 return NULL;
232}
233
234char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
235{
236 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
237
238 if (!item) {
239 return "";
240 }
241
242 return (char *)(item->data);
243}
244
245wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
246{
247 wifi_secur_list *item;
248 int i;
249
250 for (item = list,i = 0;i < list_sz; item++, i++) {
251 if (strcmp((char *)(item->data), str) == 0) {
252 return item;
253 }
254 }
255
256 return NULL;
257}
258#endif /* WIFI_HAL_VERSION_3 */
259
260#ifdef HAL_NETLINK_IMPL
261typedef struct {
262 int id;
263 struct nl_sock* socket;
264 struct nl_cb* cb;
265} Netlink;
266
267static int mac_addr_aton(unsigned char *mac_addr, char *arg)
268{
269 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800270 sscanf(arg, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
developer06a01d92022-09-07 16:32:39 +0800271 mac_addr[0] = mac_addr_int[0];
272 mac_addr[1] = mac_addr_int[1];
273 mac_addr[2] = mac_addr_int[2];
274 mac_addr[3] = mac_addr_int[3];
275 mac_addr[4] = mac_addr_int[4];
276 mac_addr[5] = mac_addr_int[5];
277 return 0;
278}
279
280static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
281{
282 unsigned int mac_addr_int[6]={};
283 mac_addr_int[0] = arg[0];
284 mac_addr_int[1] = arg[1];
285 mac_addr_int[2] = arg[2];
286 mac_addr_int[3] = arg[3];
287 mac_addr_int[4] = arg[4];
288 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800289 snprintf(mac_addr, 20, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
developer06a01d92022-09-07 16:32:39 +0800290 return;
291}
292
293static int ieee80211_frequency_to_channel(int freq)
294{
developerf5745ee2022-10-05 16:09:53 +0800295 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800296 if (freq == 2484)
297 return 14;
developerf5745ee2022-10-05 16:09:53 +0800298 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
299 else if (freq == 5935)
300 return 2;
developer06a01d92022-09-07 16:32:39 +0800301 else if (freq < 2484)
302 return (freq - 2407) / 5;
303 else if (freq >= 4910 && freq <= 4980)
304 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800305 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800306 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800307 else if (freq <= 45000) /* DMG band lower limit */
308 /* see 802.11ax D6.1 27.3.23.2 */
309 return (freq - 5950) / 5;
310 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800311 return (freq - 56160) / 2160;
312 else
313 return 0;
314}
315
316static int initSock80211(Netlink* nl) {
317 nl->socket = nl_socket_alloc();
318 if (!nl->socket) {
319 fprintf(stderr, "Failing to allocate the sock\n");
320 return -ENOMEM;
321 }
322
323 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
324
325 if (genl_connect(nl->socket)) {
326 fprintf(stderr, "Failed to connect\n");
327 nl_close(nl->socket);
328 nl_socket_free(nl->socket);
329 return -ENOLINK;
330 }
331
332 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
333 if (nl->id< 0) {
334 fprintf(stderr, "interface not found.\n");
335 nl_close(nl->socket);
336 nl_socket_free(nl->socket);
337 return -ENOENT;
338 }
339
340 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
341 if ((!nl->cb)) {
342 fprintf(stderr, "Failed to allocate netlink callback.\n");
343 nl_close(nl->socket);
344 nl_socket_free(nl->socket);
345 return ENOMEM;
346 }
347
348 return nl->id;
349}
350
351static int nlfree(Netlink *nl)
352{
353 nl_cb_put(nl->cb);
354 nl_close(nl->socket);
355 nl_socket_free(nl->socket);
356 return 0;
357}
358
359static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
360 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
361 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
362 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
363};
364
365static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
366};
367
368static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
369};
370
371typedef struct _wifi_channelStats_loc {
372 INT array_size;
373 INT ch_number;
374 BOOL ch_in_pool;
375 INT ch_noise;
376 BOOL ch_radar_noise;
377 INT ch_max_80211_rssi;
378 INT ch_non_80211_noise;
379 INT ch_utilization;
380 ULLONG ch_utilization_total;
381 ULLONG ch_utilization_busy;
382 ULLONG ch_utilization_busy_tx;
383 ULLONG ch_utilization_busy_rx;
384 ULLONG ch_utilization_busy_self;
385 ULLONG ch_utilization_busy_ext;
386} wifi_channelStats_t_loc;
387
388typedef struct wifi_device_info {
389 INT wifi_devIndex;
390 UCHAR wifi_devMacAddress[6];
391 CHAR wifi_devIPAddress[64];
392 BOOL wifi_devAssociatedDeviceAuthentiationState;
393 INT wifi_devSignalStrength;
394 INT wifi_devTxRate;
395 INT wifi_devRxRate;
396} wifi_device_info_t;
397
398#endif
399
400//For 5g Alias Interfaces
401static BOOL priv_flag = TRUE;
402static BOOL pub_flag = TRUE;
403static BOOL Radio_flag = TRUE;
404//wifi_setApBeaconRate(1, beaconRate);
405
developer1e5aa162022-09-13 16:06:24 +0800406BOOL multiple_set = FALSE;
407
developer06a01d92022-09-07 16:32:39 +0800408struct params
409{
410 char * name;
411 char * value;
412};
413
414static int _syscmd(char *cmd, char *retBuf, int retBufSize)
415{
416 FILE *f;
417 char *ptr = retBuf;
418 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
419
420 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
421 if((f = popen(cmd, "r")) == NULL) {
422 fprintf(stderr,"\npopen %s error\n", cmd);
423 return RETURN_ERR;
424 }
425
426 while(!feof(f))
427 {
428 *ptr = 0;
429 if(bufSize>=128) {
430 bufbytes=128;
431 } else {
432 bufbytes=bufSize-1;
433 }
434
435 fgets(ptr,bufbytes,f);
436 readbytes=strlen(ptr);
437
438 if(!readbytes)
439 break;
440
441 bufSize-=readbytes;
442 ptr += readbytes;
443 }
444 cmd_ret = pclose(f);
445 retBuf[retBufSize-1]=0;
446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
447
448 return cmd_ret >> 8;
449}
450
developer033b37b2022-10-18 11:27:46 +0800451INT radio_index_to_phy(int radioIndex)
452{
453 char cmd[128] = {0};
454 char buf[64] = {0};
455 int phyIndex = 0;
456 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
457 _syscmd(cmd, buf, sizeof(buf));
458
459 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
developer431128d2022-12-16 15:30:41 +0800460 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800461 return RETURN_ERR;
462 }
463 sscanf(buf, "phy%d", &phyIndex);
464
465 return phyIndex;
466}
developer026ac9e2022-11-07 13:46:24 +0800467
developer431128d2022-12-16 15:30:41 +0800468INT wifi_getMaxRadioNumber(INT *max_radio_num)
469{
470 char cmd[64] = {0};
471 char buf[4] = {0};
472
473 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
474
475 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
476 _syscmd(cmd, buf, sizeof(buf));
477 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
478
479 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
480
481 return RETURN_OK;
482}
483
developer59ff6de2023-02-08 17:58:14 +0800484static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
485{
486 char cmd[MAX_CMD_SIZE]={'\0'};
487 char buf[MAX_BUF_SIZE]={'\0'};
488 int ret = 0;
489
490 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
491 ret = _syscmd(cmd, buf, sizeof(buf));
492 if ((ret != 0) && (strlen(buf) == 0))
493 return -1;
494 snprintf(output, output_size, "%s", buf);
495
496 return 0;
497}
498
499static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
500{
501 char cmd[MAX_CMD_SIZE]={'\0'};
502 char buf[MAX_BUF_SIZE]={'\0'};
503
504 for(int i=0;i<item_count;i++)
505 {
506 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
507 if (strlen(buf) == 0) //Insert
508 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
509 else //Update
510 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
511
512 if(_syscmd(cmd, buf, sizeof(buf)))
513 return -1;
514 }
515
516 return 0;
517}
518
developer431128d2022-12-16 15:30:41 +0800519wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800520{
521 char cmd[128] = {0};
522 char buf[64] = {0};
developer59ff6de2023-02-08 17:58:14 +0800523 char config_file[128] = {0};
developer026ac9e2022-11-07 13:46:24 +0800524 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800525 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800526 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800527 int radioIndex = 0;
528 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800529 wifi_band band = band_invalid;
530
531 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800532
developer431128d2022-12-16 15:30:41 +0800533 wifi_getMaxRadioNumber(&max_radio_num);
534 radioIndex = apIndex % max_radio_num;
developer026ac9e2022-11-07 13:46:24 +0800535 phyIndex = radio_index_to_phy(radioIndex);
developer59ff6de2023-02-08 17:58:14 +0800536 snprintf(cmd, sizeof(cmd), "cat /sys/class/ieee80211/phy%d/device/device 2> /dev/null", phyIndex);
537 _syscmd(cmd, buf, sizeof(buf));
538 if (strncmp(buf, "0x7915", 6) == 0) { // harrier have two bands, consider as a special case.
539 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
540 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
541 if (strncmp(buf, "a", 1) == 0)
542 return band_5;
543 else
544 return band_2_4;
545 }
developer5884e982022-10-06 10:52:50 +0800546 while(i < 10){
developer59ff6de2023-02-08 17:58:14 +0800547 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tr -d ':\\n' | awk '{print $2}'", phyIndex);
developer5884e982022-10-06 10:52:50 +0800548 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800549 nl80211_band = strtol(buf, NULL, 10);
550 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800551 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800552 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800553 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800554 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800555 band = band_6;
556
557 if(band != band_invalid)
558 break;
559
560 i++;
561 sleep(1);
562 }
developerc707e972022-09-13 15:38:02 +0800563
564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
565 return band;
566}
567
developerd946fd62022-12-08 18:03:28 +0800568//For Getting Current Interface Name from corresponding hostapd configuration
developerac6f1142022-12-20 19:26:35 +0800569static int wifi_GetInterfaceName(int apIndex, char *interface_name)
developerd946fd62022-12-08 18:03:28 +0800570{
571 char config_file[128] = {0};
572
573 if (interface_name == NULL)
574 return RETURN_ERR;
575
576 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
577
578 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
579 wifi_hostapdRead(config_file, "interface", interface_name, 16);
580 if (strlen(interface_name) == 0)
581 return RETURN_ERR;
582
583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
584 return RETURN_OK;
585}
586
developerac6f1142022-12-20 19:26:35 +0800587// wifi agent will call this function, do not change the parameter
588void GetInterfaceName(char *interface_name, char *conf_file)
589{
590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
591 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
593}
594
developer06a01d92022-09-07 16:32:39 +0800595static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
596{
developerd946fd62022-12-08 18:03:28 +0800597 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800598 if (multiple_set == TRUE)
599 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800600 char cmd[MAX_CMD_SIZE]="", output[32]="";
601 FILE *fp;
602 int i;
603 //NOTE RELOAD should be done in ApplySSIDSettings
developerac6f1142022-12-20 19:26:35 +0800604 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800605 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800606 for(i=0; i<item_count; i++, list++)
607 {
developerd946fd62022-12-08 18:03:28 +0800608 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800609 if((fp = popen(cmd, "r"))==NULL)
610 {
611 perror("popen failed");
612 return -1;
613 }
614 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
615 {
616 pclose(fp);
617 perror("fgets failed");
618 return -1;
619 }
620 pclose(fp);
621 }
622 return 0;
623}
624
625static int wifi_reloadAp(int apIndex)
626{
developerd946fd62022-12-08 18:03:28 +0800627 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800628 if (multiple_set == TRUE)
629 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800630 char cmd[MAX_CMD_SIZE]="";
631 char buf[MAX_BUF_SIZE]="";
632
developerac6f1142022-12-20 19:26:35 +0800633 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +0800634 return RETURN_ERR;
635 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800636 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
637 return RETURN_ERR;
638
developerd946fd62022-12-08 18:03:28 +0800639 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800640 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
641 return RETURN_ERR;
642
developerd946fd62022-12-08 18:03:28 +0800643 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800644 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
645 return RETURN_ERR;
646
647 return RETURN_OK;
648}
649
developer06a01d92022-09-07 16:32:39 +0800650INT File_Reading(CHAR *file, char *Value)
651{
652 FILE *fp = NULL;
653 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
654 int count = 0;
655
656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
657 fp = popen(file,"r");
658 if(fp == NULL)
659 return RETURN_ERR;
660
661 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
662 {
663 for(count=0;buf[count]!='\n';count++)
664 copy_buf[count]=buf[count];
665 copy_buf[count]='\0';
666 }
667 strcpy(Value,copy_buf);
668 pclose(fp);
669 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
670
671 return RETURN_OK;
672}
673
674void wifi_RestartHostapd_2G()
675{
676 int Public2GApIndex = 4;
677
678 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
679 wifi_setApEnable(Public2GApIndex, FALSE);
680 wifi_setApEnable(Public2GApIndex, TRUE);
681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
682}
683
684void wifi_RestartHostapd_5G()
685{
686 int Public5GApIndex = 5;
687
688 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
689 wifi_setApEnable(Public5GApIndex, FALSE);
690 wifi_setApEnable(Public5GApIndex, TRUE);
691 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
692}
693
694void wifi_RestartPrivateWifi_2G()
695{
696 int PrivateApIndex = 0;
697
698 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
699 wifi_setApEnable(PrivateApIndex, FALSE);
700 wifi_setApEnable(PrivateApIndex, TRUE);
701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
702}
703
704void wifi_RestartPrivateWifi_5G()
705{
706 int Private5GApIndex = 1;
707
708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
709 wifi_setApEnable(Private5GApIndex, FALSE);
710 wifi_setApEnable(Private5GApIndex, TRUE);
711 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
712}
713
714static int writeBandWidth(int radioIndex,char *bw_value)
715{
716 char buf[MAX_BUF_SIZE];
717 char cmd[MAX_CMD_SIZE];
718
719 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
720 if(_syscmd(cmd, buf, sizeof(buf)))
721 {
722 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
723 _syscmd(cmd, buf, sizeof(buf));
724 return RETURN_OK;
725 }
726
727 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
728 _syscmd(cmd,buf,sizeof(buf));
729 return RETURN_OK;
730}
731
732static int readBandWidth(int radioIndex,char *bw_value)
733{
developer30423732022-12-01 16:17:49 +0800734 char buf[MAX_BUF_SIZE] = {0};
735 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800736 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
737 _syscmd(cmd,buf,sizeof(buf));
738 if(NULL!=strstr(buf,"20MHz"))
developer06a01d92022-09-07 16:32:39 +0800739 strcpy(bw_value,"20MHz");
developer06a01d92022-09-07 16:32:39 +0800740 else if(NULL!=strstr(buf,"40MHz"))
developer06a01d92022-09-07 16:32:39 +0800741 strcpy(bw_value,"40MHz");
developer06a01d92022-09-07 16:32:39 +0800742 else if(NULL!=strstr(buf,"80MHz"))
developer06a01d92022-09-07 16:32:39 +0800743 strcpy(bw_value,"80MHz");
developer57fa24a2023-03-15 17:25:07 +0800744 else if(NULL!=strstr(buf,"160MHz"))
745 strcpy(bw_value,"160MHz");
746 else if(NULL!=strstr(buf,"320MHz"))
747 strcpy(bw_value,"320MHz");
developer06a01d92022-09-07 16:32:39 +0800748 else
developer06a01d92022-09-07 16:32:39 +0800749 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800750 return RETURN_OK;
751}
752
developer264159b2022-11-02 09:41:35 +0800753// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800754INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
755{
developer5f222492022-09-13 15:21:52 +0800756 struct params params={'\0'};
757 char config_file[MAX_BUF_SIZE] = {0};
758 char buf[MAX_BUF_SIZE] = {'\0'};
759
760 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800761 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800762 if (strlen (beaconRate) >= 5) {
763 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
764 buf[strlen(beaconRate) - 4] = '\0';
765 } else if (strlen(beaconRate) > 0)
766 strcpy(buf, beaconRate);
767 else
768 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800769
770 params.name = "beacon_rate";
771 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
772 if (strncmp(buf, "5.5", 3) == 0) {
773 snprintf(buf, sizeof(buf), "55");
774 params.value = buf;
775 } else {
776 strcat(buf, "0");
777 params.value = buf;
778 }
779
780 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
781 wifi_hostapdWrite(config_file, &params, 1);
782 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
784
785 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800786}
787
788INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
789{
developer1d57d002022-10-12 18:03:15 +0800790 char config_file[128] = {'\0'};
791 char temp_output[128] = {'\0'};
792 char buf[128] = {'\0'};
793 char cmd[128] = {'\0'};
794 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800795 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800796
797 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
798 if (NULL == beaconRate)
799 return RETURN_ERR;
800
801 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
802 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800803 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800804 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
805 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800806 if (strncmp(buf, "55", 2) == 0)
807 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
808 else {
809 rate = strtol(buf, NULL, 10)/10;
810 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
811 }
developer5f222492022-09-13 15:21:52 +0800812 } else {
developer1d57d002022-10-12 18:03:15 +0800813 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800814 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
developer1d57d002022-10-12 18:03:15 +0800815 _syscmd(cmd, buf, sizeof(buf));
816 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800817 }
818 strncpy(beaconRate, temp_output, sizeof(temp_output));
819 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
820
821 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800822}
823
824INT wifi_setLED(INT radioIndex, BOOL enable)
825{
826 return 0;
827}
828INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
829{
830 return RETURN_OK;
831}
832/**********************************************************************************
833 *
834 * Wifi Subsystem level function prototypes
835 *
836**********************************************************************************/
837//---------------------------------------------------------------------------------------------------
838//Wifi system api
839//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
840INT wifi_getHalVersion(CHAR *output_string) //RDKB
841{
842 if(!output_string)
843 return RETURN_ERR;
844 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
845
846 return RETURN_OK;
847}
848
849
850/* wifi_factoryReset() function */
851/**
852* @description Clears internal variables to implement a factory reset of the Wi-Fi
853* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
854*
855* @param None
856*
857* @return The status of the operation.
858* @retval RETURN_OK if successful.
859* @retval RETURN_ERR if any error is detected
860*
861* @execution Synchronous
862* @sideeffect None
863*
864* @note This function must not suspend and must not invoke any blocking system
865* calls. It should probably just send a message to a driver event handler task.
866*
867*/
868INT wifi_factoryReset()
869{
870 char cmd[128];
871
872 /*delete running hostapd conf files*/
developer72ec5572023-01-05 16:27:13 +0800873 wifi_dbg_printf("\n[%s]: deleting hostapd conf file",__func__);
874 sprintf(cmd, "rm -rf /nvram/hostapd*");
developer06a01d92022-09-07 16:32:39 +0800875 system(cmd);
876 system("systemctl restart hostapd.service");
877
878 return RETURN_OK;
879}
880
881/* wifi_factoryResetRadios() function */
882/**
883* @description Restore all radio parameters without touching access point parameters. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
884*
885* @param None
886* @return The status of the operation
887* @retval RETURN_OK if successful
888* @retval RETURN_ERR if any error is detected
889*
890* @execution Synchronous
891*
892* @sideeffect None
893*
894* @note This function must not suspend and must not invoke any blocking system
895* calls. It should probably just send a message to a driver event handler task.
896*
897*/
898INT wifi_factoryResetRadios()
899{
developer72ec5572023-01-05 16:27:13 +0800900 int max_radio_num = 0;
901 wifi_getMaxRadioNumber(&max_radio_num);
902 for (int radioIndex = 0; radioIndex < max_radio_num; radioIndex++)
903 wifi_factoryResetRadio(radioIndex);
developer06a01d92022-09-07 16:32:39 +0800904
developer72ec5572023-01-05 16:27:13 +0800905 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800906}
907
908
909/* wifi_factoryResetRadio() function */
910/**
911* @description Restore selected radio parameters without touching access point parameters
912*
913* @param radioIndex - Index of Wi-Fi Radio channel
914*
915* @return The status of the operation.
916* @retval RETURN_OK if successful.
917* @retval RETURN_ERR if any error is detected
918*
919* @execution Synchronous.
920* @sideeffect None.
921*
922* @note This function must not suspend and must not invoke any blocking system
923* calls. It should probably just send a message to a driver event handler task.
924*
925*/
926INT wifi_factoryResetRadio(int radioIndex) //RDKB
927{
developer72ec5572023-01-05 16:27:13 +0800928 char cmd[128] = {0};
929 char buf[128] = {0};
930 int max_radio_num = 0;
931
932 wifi_getMaxRadioNumber(&max_radio_num);
933 if (radioIndex < 0 || radioIndex > max_radio_num)
934 return RETURN_ERR;
935
936 snprintf(cmd, sizeof(cmd), "systemctl stop hostapd.service");
937 _syscmd(cmd, buf, sizeof(buf));
developer5ff7f5f2022-09-13 15:12:16 +0800938
developer06a01d92022-09-07 16:32:39 +0800939 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72ec5572023-01-05 16:27:13 +0800940 snprintf(cmd, sizeof(cmd), "rm /nvram/hostapd%d* %s%d.txt", radioIndex, GUARD_INTERVAL_FILE, radioIndex);
941 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800942
developer72ec5572023-01-05 16:27:13 +0800943 snprintf(cmd, sizeof(cmd), "systemctl start hostapd.service");
944 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +0800945 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
946 return RETURN_OK;
947}
948
949/* wifi_initRadio() function */
950/**
951* Description: This function call initializes the specified radio.
952* Implementation specifics may dictate the functionality since
953* different hardware implementations may have different initilization requirements.
954* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
955*
956* @return The status of the operation.
957* @retval RETURN_OK if successful.
958* @retval RETURN_ERR if any error is detected
959*
960* @execution Synchronous.
961* @sideeffect None.
962*
963* @note This function must not suspend and must not invoke any blocking system
964* calls. It should probably just send a message to a driver event handler task.
965*
966*/
967INT wifi_initRadio(INT radioIndex)
968{
969 //TODO: Initializes the wifi subsystem (for specified radio)
970 return RETURN_OK;
971}
972void macfilter_init()
973{
974 char count[4]={'\0'};
975 char buf[253]={'\0'};
976 char tmp[19]={'\0'};
977 int dev_count,block,mac_entry=0;
978 char res[4]={'\0'};
979 char acl_file_path[64] = {'\0'};
980 FILE *fp = NULL;
981 int index=0;
982 char iface[10]={'\0'};
983 char config_file[MAX_BUF_SIZE] = {0};
984
985
986 sprintf(acl_file_path,"/tmp/mac_filter.sh");
987
988 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800989 if (fp == NULL) {
990 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
991 return RETURN_ERR;
992 }
developer06a01d92022-09-07 16:32:39 +0800993 sprintf(buf,"#!/bin/sh \n");
994 fprintf(fp,"%s\n",buf);
995
996 system("chmod 0777 /tmp/mac_filter.sh");
997
998 for(index=0;index<=1;index++)
999 {
1000 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1001 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1002 sprintf(buf,"syscfg get %dcountfilter",index);
1003 _syscmd(buf,count,sizeof(count));
1004 mac_entry=atoi(count);
1005
1006 sprintf(buf,"syscfg get %dblockall",index);
1007 _syscmd(buf,res,sizeof(res));
1008 block = atoi(res);
1009
1010 //Allow only those macs mentioned in ACL
1011 if(block==1)
1012 {
1013 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1014 fprintf(fp,"%s\n",buf);
1015 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1016 {
1017 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1018 _syscmd(buf,tmp,sizeof(tmp));
1019 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1020 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1021 fprintf(fp,"%s\n",buf);
1022 }
1023 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1024 fprintf(fp,"%s\n",buf);
1025 }
1026
1027 //Block all the macs mentioned in ACL
1028 else if(block==2)
1029 {
1030 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1031 fprintf(fp,"%s\n",buf);
1032
1033 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1034 {
1035 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1036 _syscmd(buf,tmp,sizeof(tmp));
1037 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1038 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1039 fprintf(fp,"%s\n",buf);
1040 }
1041 }
1042 }
1043 fclose(fp);
1044}
1045
1046// Initializes the wifi subsystem (all radios)
1047INT wifi_init() //RDKB
1048{
1049 char interface[MAX_BUF_SIZE]={'\0'};
1050 char bridge_name[MAX_BUF_SIZE]={'\0'};
1051 INT len=0;
1052
1053 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1054 //Not intitializing macfilter for Turris-Omnia Platform for now
1055 //macfilter_init();
1056
1057 system("/usr/sbin/iw reg set US");
developerac6f1142022-12-20 19:26:35 +08001058 // system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +08001059 sleep(2);//sleep to wait for hostapd to start
1060
1061 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1062
1063 return RETURN_OK;
1064}
1065
1066/* wifi_reset() function */
1067/**
1068* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1069* Implementation specifics may dictate what is actualy reset since
1070* different hardware implementations may have different requirements.
1071* Parameters : None
1072*
1073* @return The status of the operation.
1074* @retval RETURN_OK if successful.
1075* @retval RETURN_ERR if any error is detected
1076*
1077* @execution Synchronous.
1078* @sideeffect None.
1079*
1080* @note This function must not suspend and must not invoke any blocking system
1081* calls. It should probably just send a message to a driver event handler task.
1082*
1083*/
1084INT wifi_reset()
1085{
1086 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001087 system("systemctl stop hostapd.service");
1088 sleep(2);
1089 system("systemctl start hostapd.service");
1090 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001091 return RETURN_OK;
1092}
1093
1094/* wifi_down() function */
1095/**
1096* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1097* Implementation specifics may dictate some functionality since
1098* different hardware implementations may have different requirements.
1099*
1100* @param None
1101*
1102* @return The status of the operation
1103* @retval RETURN_OK if successful
1104* @retval RETURN_ERR if any error is detected
1105*
1106* @execution Synchronous
1107* @sideeffect None
1108*
1109* @note This function must not suspend and must not invoke any blocking system
1110* calls. It should probably just send a message to a driver event handler task.
1111*
1112*/
1113INT wifi_down()
1114{
1115 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer72ec5572023-01-05 16:27:13 +08001116 int max_num_radios = 0;
1117 wifi_getMaxRadioNumber(&max_num_radios);
1118 for (int radioIndex = 0; radioIndex < max_num_radios; radioIndex++)
1119 wifi_setRadioEnable(radioIndex, FALSE);
1120
developer06a01d92022-09-07 16:32:39 +08001121 return RETURN_OK;
1122}
1123
1124
1125/* wifi_createInitialConfigFiles() function */
1126/**
1127* @description This function creates wifi configuration files. The format
1128* and content of these files are implementation dependent. This function call is
1129* used to trigger this task if necessary. Some implementations may not need this
1130* function. If an implementation does not need to create config files the function call can
1131* do nothing and return RETURN_OK.
1132*
1133* @param None
1134*
1135* @return The status of the operation
1136* @retval RETURN_OK if successful
1137* @retval RETURN_ERR if any error is detected
1138*
1139* @execution Synchronous
1140* @sideeffect None
1141*
1142* @note This function must not suspend and must not invoke any blocking system
1143* calls. It should probably just send a message to a driver event handler task.
1144*
1145*/
1146INT wifi_createInitialConfigFiles()
1147{
1148 //TODO: creates initial implementation dependent configuration files that are later used for variable storage. Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
1149 return RETURN_OK;
1150}
1151
1152// outputs the country code to a max 64 character string
1153INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1154{
developerd946fd62022-12-08 18:03:28 +08001155 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001156 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001157 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001158 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001159
developerac6f1142022-12-20 19:26:35 +08001160 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001161 return RETURN_ERR;
1162 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001163 _syscmd(cmd, buf, sizeof(buf));
1164 if(strlen(buf) > 0)
1165 snprintf(output_string, 64, "%s", buf);
1166 else
1167 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001168
1169 return RETURN_OK;
1170}
1171
1172INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1173{
1174 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001175 char str[MAX_BUF_SIZE]={'\0'};
1176 char cmd[MAX_CMD_SIZE]={'\0'};
1177 struct params params;
1178 char config_file[MAX_BUF_SIZE] = {0};
1179
1180 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1181 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1182 return RETURN_ERR;
1183
developerb86c6f32022-10-07 14:34:58 +08001184 if (strlen(CountryCode) == 0)
1185 strcpy(CountryCode, "US");
1186
developer7543b3b2022-09-13 13:47:17 +08001187 params.name = "country_code";
1188 params.value = CountryCode;
1189 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1190 int ret = wifi_hostapdWrite(config_file, &params, 1);
1191 if (ret) {
1192 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1193 ,__func__, ret);
1194 }
1195
1196 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1197 if (ret) {
1198 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1199 ,__func__, ret);
1200 }
developer7543b3b2022-09-13 13:47:17 +08001201 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1202
developer06a01d92022-09-07 16:32:39 +08001203 return RETURN_OK;
1204}
1205
developera748dcf2022-09-13 15:56:48 +08001206INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1207{
developerd946fd62022-12-08 18:03:28 +08001208 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001209 char channel_util_file[64] = {0};
1210 char cmd[128] = {0};
1211 char buf[128] = {0};
1212 char line[128] = {0};
1213 char *param = NULL, *value = NULL;
1214 int read = 0;
1215 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1216 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1217 size_t len = 0;
1218 FILE *f = NULL;
1219
1220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1221
developerac6f1142022-12-20 19:26:35 +08001222 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08001223 return RETURN_ERR;
1224 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001225 _syscmd(cmd, buf, sizeof(buf));
1226 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1227
1228 memset(cmd, 0, sizeof(cmd));
1229 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001230 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001231 if ((f = popen(cmd, "r")) == NULL) {
1232 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1233 return RETURN_ERR;
1234 }
1235
1236 read = getline(&line, &len, f);
1237 while (read != -1) {
1238 param = strtok(line, ":\t");
1239 value = strtok(NULL, " ");
1240 if(strstr(param, "frequency") != NULL) {
1241 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1242 }
1243 if(strstr(param, "noise") != NULL) {
1244 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1245 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1246 }
1247 if(strstr(param, "channel active time") != NULL) {
1248 ActiveTime = strtol(value, NULL, 10);
1249 }
1250 if(strstr(param, "channel busy time") != NULL) {
1251 BusyTime = strtol(value, NULL, 10);
1252 }
1253 if(strstr(param, "channel transmit time") != NULL) {
1254 TransmitTime = strtol(value, NULL, 10);
1255 }
1256 read = getline(&line, &len, f);
1257 }
1258 pclose(f);
1259
1260 // The file should store the last active, busy and transmit time
1261 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1262 f = fopen(channel_util_file, "r");
1263 if (f != NULL) {
1264 read = getline(&line, &len, f);
1265 preActiveTime = strtol(line, NULL, 10);
1266 read = getline(&line, &len, f);
1267 preBusyTime = strtol(line, NULL, 10);
1268 read = getline(&line, &len, f);
1269 preTransmitTime = strtol(line, NULL, 10);
1270 fclose(f);
1271 }
1272
1273 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1274 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1275
1276 f = fopen(channel_util_file, "w");
1277 if (f != NULL) {
1278 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1279 fclose(f);
1280 }
1281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1282 return RETURN_OK;
1283}
1284
developer06a01d92022-09-07 16:32:39 +08001285/**********************************************************************************
1286 *
1287 * Wifi radio level function prototypes
1288 *
1289**********************************************************************************/
1290
1291//Get the total number of radios in this wifi subsystem
1292INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1293{
1294 if (NULL == output)
1295 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001296 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001297
1298 return RETURN_OK;
1299}
1300
1301//Get the total number of SSID entries in this wifi subsystem
1302INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1303{
1304 if (NULL == output)
1305 return RETURN_ERR;
1306 *output = MAX_APS;
1307
1308 return RETURN_OK;
1309}
1310
1311//Get the Radio enable config parameter
1312INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1313{
developerd946fd62022-12-08 18:03:28 +08001314 char interface_name[16] = {0};
developer7930d352022-12-21 17:55:42 +08001315 char buf[128] = {0}, cmd[128] = {0};
developera77d84b2023-02-22 16:10:50 +08001316 int apIndex;
1317 int max_radio_num = 0;
developer06a01d92022-09-07 16:32:39 +08001318
1319 if (NULL == output_bool)
1320 return RETURN_ERR;
1321
1322 *output_bool = FALSE;
developera77d84b2023-02-22 16:10:50 +08001323
1324 wifi_getMaxRadioNumber(&max_radio_num);
1325
1326 if (radioIndex >= max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001327 return RETURN_ERR;
1328
developera77d84b2023-02-22 16:10:50 +08001329 /* loop all interface in radio, if any is enable, reture true, else return false */
1330 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1331 {
developer643b28f2023-04-04 10:26:01 +08001332 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developera77d84b2023-02-22 16:10:50 +08001333 continue;
1334 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1335 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001336
developera77d84b2023-02-22 16:10:50 +08001337 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 ||
1338 strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0) {
1339 /* return true if any interface is eanble */
1340 *output_bool = TRUE;
1341 break;
1342 }
1343 }
developer06a01d92022-09-07 16:32:39 +08001344 return RETURN_OK;
1345}
1346
1347INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1348{
developerd946fd62022-12-08 18:03:28 +08001349 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001350 char cmd[MAX_CMD_SIZE] = {0};
1351 char buf[MAX_CMD_SIZE] = {0};
1352 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08001353 int max_radio_num = 0;
1354 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001355
1356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001357
1358 phyId = radio_index_to_phy(radioIndex);
1359
1360 wifi_getMaxRadioNumber(&max_radio_num);
1361
developer06a01d92022-09-07 16:32:39 +08001362 if(enable==FALSE)
1363 {
developera77d84b2023-02-22 16:10:50 +08001364 /* disable from max apindex to min, to avoid fail in mbss case */
1365 for(apIndex=(MAX_APS-max_radio_num+radioIndex); apIndex>=0; apIndex-=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001366 {
developer1e125222022-12-29 09:35:25 +08001367 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001368 continue;
developer1e125222022-12-29 09:35:25 +08001369
developer06a01d92022-09-07 16:32:39 +08001370 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001371 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001372 _syscmd(cmd, buf, sizeof(buf));
1373 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001374 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer1e125222022-12-29 09:35:25 +08001375
developer2f18b9f2023-03-17 19:32:57 +08001376 if (!(apIndex/max_radio_num)) {
1377 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
1378 _syscmd(cmd, buf, sizeof(buf));
1379 }
developer06a01d92022-09-07 16:32:39 +08001380 }
developer06a01d92022-09-07 16:32:39 +08001381 }
1382 else
1383 {
developer033b37b2022-10-18 11:27:46 +08001384 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001385 {
developer1e125222022-12-29 09:35:25 +08001386 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72ec5572023-01-05 16:27:13 +08001387 continue;
developer1e125222022-12-29 09:35:25 +08001388
developer643b28f2023-04-04 10:26:01 +08001389 snprintf(cmd, sizeof(cmd), "cat %s | grep %s= | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001390 _syscmd(cmd, buf, sizeof(buf));
developera77d84b2023-02-22 16:10:50 +08001391 if(*buf == '1') {
developer2f18b9f2023-03-17 19:32:57 +08001392 if (!(apIndex/max_radio_num)) {
1393 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1394 ret = _syscmd(cmd, buf, sizeof(buf));
1395 if ( ret == RETURN_ERR) {
1396 fprintf(stderr, "VAP interface creation failed\n");
1397 continue;
1398 }
developera77d84b2023-02-22 16:10:50 +08001399 }
developer06a01d92022-09-07 16:32:39 +08001400 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001401 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001402 _syscmd(cmd, buf, sizeof(buf));
1403 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001404 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001405 }
1406 }
1407 }
1408
1409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1410 return RETURN_OK;
1411}
1412
1413//Get the Radio enable status
1414INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1415{
1416 if (NULL == output_bool)
1417 return RETURN_ERR;
1418
1419 return wifi_getRadioEnable(radioIndex, output_bool);
1420}
1421
1422//Get the Radio Interface name from platform, eg "wlan0"
1423INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1424{
developer804c64f2022-10-19 13:54:40 +08001425 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001426 return RETURN_ERR;
developer7930d352022-12-21 17:55:42 +08001427 return wifi_GetInterfaceName(radioIndex, output_string);
developer06a01d92022-09-07 16:32:39 +08001428}
1429
1430//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1431//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1432INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1433{
developerbcc556a2022-09-22 20:02:45 +08001434 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1435 // For max bit rate, we should always choose the best MCS
1436 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001437 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001438 char *tmp = NULL;
1439 UINT mode_map = 0;
1440 UINT num_subcarrier = 0;
1441 UINT code_bits = 0;
1442 float code_rate = 0; // use max code rate
1443 int NSS = 0;
1444 UINT Symbol_duration = 0;
1445 UINT GI_duration = 0;
1446 wifi_band band = band_invalid;
1447 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1448 BOOL enable = FALSE;
1449 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001450
1451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1452 if (NULL == output_string)
1453 return RETURN_ERR;
1454
developerbcc556a2022-09-22 20:02:45 +08001455 wifi_getRadioEnable(radioIndex, &enable);
1456 if (enable == FALSE) {
1457 snprintf(output_string, 64, "0 Mb/s");
1458 return RETURN_OK;
1459 }
1460
1461 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1462 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1463 return RETURN_ERR;
1464 }
1465
1466 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1467 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1468 return RETURN_ERR;
1469 }
1470
1471 if (gi == wifi_guard_interval_3200)
1472 GI_duration = 32;
1473 else if (gi == wifi_guard_interval_1600)
1474 GI_duration = 16;
1475 else if (gi == wifi_guard_interval_800)
1476 GI_duration = 8;
1477 else // auto, 400
1478 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001479
developerbcc556a2022-09-22 20:02:45 +08001480 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1481 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1482 return RETURN_ERR;
1483 }
1484
1485 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1486 strcpy(channel_bandwidth_str, "160");
1487
1488 if (mode_map & WIFI_MODE_AX) {
1489 if (strstr(channel_bandwidth_str, "160") != NULL)
1490 num_subcarrier = 1960;
1491 else if (strstr(channel_bandwidth_str, "80") != NULL)
1492 num_subcarrier = 980;
1493 else if (strstr(channel_bandwidth_str, "40") != NULL)
1494 num_subcarrier = 468;
1495 else if (strstr(channel_bandwidth_str, "20") != NULL)
1496 num_subcarrier = 234;
1497 code_bits = 10;
1498 code_rate = (float)5/6;
1499 Symbol_duration = 128;
1500 } else if (mode_map & WIFI_MODE_AC) {
1501 if (strstr(channel_bandwidth_str, "160") != NULL)
1502 num_subcarrier = 468;
1503 else if (strstr(channel_bandwidth_str, "80") != NULL)
1504 num_subcarrier = 234;
1505 else if (strstr(channel_bandwidth_str, "40") != NULL)
1506 num_subcarrier = 108;
1507 else if (strstr(channel_bandwidth_str, "20") != NULL)
1508 num_subcarrier = 52;
1509 code_bits = 8;
1510 code_rate = (float)5/6;
1511 Symbol_duration = 32;
1512 } else if (mode_map & WIFI_MODE_N) {
1513 if (strstr(channel_bandwidth_str, "160") != NULL)
1514 num_subcarrier = 468;
1515 else if (strstr(channel_bandwidth_str, "80") != NULL)
1516 num_subcarrier = 234;
1517 else if (strstr(channel_bandwidth_str, "40") != NULL)
1518 num_subcarrier = 108;
1519 else if (strstr(channel_bandwidth_str, "20") != NULL)
1520 num_subcarrier = 52;
1521 code_bits = 6;
1522 code_rate = (float)3/4;
1523 Symbol_duration = 32;
1524 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1525 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1526 snprintf(output_string, 64, "65 Mb/s");
1527 return RETURN_OK;
1528 } else {
1529 snprintf(output_string, 64, "0 Mb/s");
1530 return RETURN_OK;
1531 }
developer06a01d92022-09-07 16:32:39 +08001532
developerbcc556a2022-09-22 20:02:45 +08001533 // Spatial streams
1534 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1535 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1536 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001537 }
developerbcc556a2022-09-22 20:02:45 +08001538
1539 // multiple 10 is to align duration unit (0.1 us)
1540 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1541 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1542
developer06a01d92022-09-07 16:32:39 +08001543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1544
1545 return RETURN_OK;
1546}
1547#if 0
1548INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1549{
1550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1551 char cmd[64];
1552 char buf[1024];
1553 int apIndex;
1554
1555 if (NULL == output_string)
1556 return RETURN_ERR;
1557
1558 apIndex=(radioIndex==0)?0:1;
1559
developerd946fd62022-12-08 18:03:28 +08001560 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001561 _syscmd(cmd,buf, sizeof(buf));
1562
1563 snprintf(output_string, 64, "%s", buf);
1564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1565 return RETURN_OK;
1566}
1567#endif
1568
1569
1570//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1571//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1572INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1573{
developer963da0c2022-09-13 15:58:27 +08001574 wifi_band band = band_invalid;
1575
developer06a01d92022-09-07 16:32:39 +08001576 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1577 if (NULL == output_string)
1578 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001579
1580 band = wifi_index_to_band(radioIndex);
1581
1582 memset(output_string, 0, 10);
1583 if (band == band_2_4)
1584 strcpy(output_string, "2.4GHz");
1585 else if (band == band_5)
1586 strcpy(output_string, "5GHz");
1587 else if (band == band_6)
1588 strcpy(output_string, "6GHz");
1589 else
1590 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1592
1593 return RETURN_OK;
1594#if 0
1595 char buf[MAX_BUF_SIZE]={'\0'};
1596 char str[MAX_BUF_SIZE]={'\0'};
1597 char cmd[MAX_CMD_SIZE]={'\0'};
1598 char *ch=NULL;
1599 char *ch2=NULL;
1600
1601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1602 if (NULL == output_string)
1603 return RETURN_ERR;
1604
1605
1606 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1607
1608 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1609 {
1610 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1611 return RETURN_ERR;
1612 }
1613 ch=strchr(buf,'\n');
1614 *ch='\0';
1615 ch=strchr(buf,'=');
1616 if(ch==NULL)
1617 return RETURN_ERR;
1618
1619
1620 ch++;
1621
1622 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1623 strcpy(buf,"0");
1624 if(strlen(ch) == 1)
1625 ch=strcat(buf,ch);
1626
1627
1628 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1629
1630 if(_syscmd(cmd,str,64) == RETURN_ERR)
1631 {
1632 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1633 return RETURN_ERR;
1634 }
1635
1636
1637 ch2=strchr(str,'\n');
1638 //replace \n with \0
1639 *ch2='\0';
1640 ch2=strchr(str,'=');
1641 if(ch2==NULL)
1642 {
1643 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1644 return RETURN_ERR;
1645 }
1646 else
1647 wifi_dbg_printf("%s",ch2+1);
1648
1649
1650 ch2++;
1651
1652
1653 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1654
1655 memset(buf,'\0',sizeof(buf));
1656 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1657 {
1658 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1659 return RETURN_ERR;
1660 }
1661 if (strstr(buf,"2.4") != NULL )
1662 strcpy(output_string,"2.4GHz");
1663 else if(strstr(buf,"5.") != NULL )
1664 strcpy(output_string,"5GHz");
1665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1666
1667 return RETURN_OK;
1668#endif
1669}
1670
1671//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1672//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1673INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1674{
developerb7593de2022-10-18 09:51:57 +08001675 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1677 if (NULL == output_string)
1678 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001679 band = wifi_index_to_band(radioIndex);
1680
1681 if (band == band_2_4)
1682 snprintf(output_string, 64, "2.4GHz");
1683 else if (band == band_5)
1684 snprintf(output_string, 64, "5GHz");
1685 else if (band == band_6)
1686 snprintf(output_string, 64, "6GHz");
1687
developer06a01d92022-09-07 16:32:39 +08001688 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1689
1690 return RETURN_OK;
1691#if 0
1692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1693 char buf[MAX_BUF_SIZE]={'\0'};
1694 char str[MAX_BUF_SIZE]={'\0'};
1695 char cmd[MAX_CMD_SIZE]={'\0'};
1696 char *ch=NULL;
1697 char *ch2=NULL;
1698 char ch1[5]="0";
1699
1700 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1701
1702 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1703 {
1704 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1705 return RETURN_ERR;
1706 }
1707
1708 ch=strchr(buf,'\n');
1709 *ch='\0';
1710 ch=strchr(buf,'=');
1711 if(ch==NULL)
1712 return RETURN_ERR;
1713 ch++;
1714
1715 if(strlen(ch)==1)
1716 {
1717 strcat(ch1,ch);
1718
1719 }
1720 else
1721 {
1722 strcpy(ch1,ch);
1723 }
1724
1725
1726
1727 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1728 if(_syscmd(cmd,str,64) == RETURN_ERR)
1729 {
1730 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1731 return RETURN_ERR;
1732 }
1733
1734
1735 ch2=strchr(str,'\n');
1736 //replace \n with \0
1737 *ch2='\0';
1738 ch2=strchr(str,'=');
1739 if(ch2==NULL)
1740 {
1741 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1742 return RETURN_ERR;
1743 }
1744 else
1745 wifi_dbg_printf("%s",ch2+1);
1746 ch2++;
1747
1748
1749 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1750 memset(buf,'\0',sizeof(buf));
1751 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1752 {
1753 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1754 return RETURN_ERR;
1755 }
1756
1757
1758 if(strstr(buf,"2.4")!=NULL)
1759 {
1760 strcpy(output_string,"2.4GHz");
1761 }
1762 if(strstr(buf,"5.")!=NULL)
1763 {
1764 strcpy(output_string,"5GHz");
1765 }
1766 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1767 return RETURN_OK;
1768#endif
1769}
1770
1771//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1772//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1773INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1774{
developer963da0c2022-09-13 15:58:27 +08001775 char cmd[128]={0};
1776 char buf[128]={0};
1777 char temp_output[128] = {0};
1778 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001779 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001780
1781 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001782 if (NULL == output_string)
1783 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001784
1785 band = wifi_index_to_band(radioIndex);
1786 if (band == band_2_4) {
1787 strcat(temp_output, "b,g,");
1788 } else if (band == band_5) {
1789 strcat(temp_output, "a,");
1790 }
developer033b37b2022-10-18 11:27:46 +08001791 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001792 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001793 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001794 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001795 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001796 strcat(temp_output, "n,");
1797 }
developer06a01d92022-09-07 16:32:39 +08001798
developer963da0c2022-09-13 15:58:27 +08001799 // vht capabilities
1800 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001801 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001802 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001803 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001804 strcat(temp_output, "ac,");
1805 }
1806 }
1807
1808 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001809 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001810 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001811 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001812 strcat(temp_output, "ax,");
1813 }
1814
developer7c4cd202023-03-01 10:56:29 +08001815 // eht capabilities
1816 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'EHT MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
1817 _syscmd(cmd, buf, sizeof(buf));
1818 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
1819 strcat(temp_output, "be,");
1820 }
1821
developer963da0c2022-09-13 15:58:27 +08001822 // Remove the last comma
1823 if (strlen(temp_output) != 0)
1824 temp_output[strlen(temp_output)-1] = '\0';
1825 strncpy(output_string, temp_output, strlen(temp_output));
1826 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001827 return RETURN_OK;
1828}
1829
1830//Get the radio operating mode, and pure mode flag. eg: "ac"
1831//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1832INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1833{
1834 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1835 if (NULL == output_string)
1836 return RETURN_ERR;
1837
1838 if (radioIndex == 0) {
1839 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1840 *gOnly = FALSE;
1841 *nOnly = TRUE;
1842 *acOnly = FALSE;
1843 } else {
1844 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1845 *gOnly = FALSE;
1846 *nOnly = FALSE;
1847 *acOnly = FALSE;
1848 }
1849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1850
1851 return RETURN_OK;
1852#if 0
1853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1854 char buf[64] = {0};
1855 char config_file[MAX_BUF_SIZE] = {0};
1856
1857 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1858 return RETURN_ERR;
1859
1860 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1861 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1862
1863 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1864 if (strlen(buf) == 0)
1865 {
1866 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1867 return RETURN_ERR;
1868 }
1869 if(strcmp(buf,"g")==0)
1870 {
1871 wifi_dbg_printf("\nG\n");
1872 *gOnly=TRUE;
1873 *nOnly=FALSE;
1874 *acOnly=FALSE;
1875 }
1876 else if(strcmp(buf,"n")==0)
1877 {
1878 wifi_dbg_printf("\nN\n");
1879 *gOnly=FALSE;
1880 *nOnly=TRUE;
1881 *acOnly=FALSE;
1882 }
1883 else if(strcmp(buf,"ac")==0)
1884 {
1885 wifi_dbg_printf("\nac\n");
1886 *gOnly=FALSE;
1887 *nOnly=FALSE;
1888 *acOnly=TRUE;
1889 }
1890 /* hostapd-5G.conf has "a" as hw_mode */
1891 else if(strcmp(buf,"a")==0)
1892 {
1893 wifi_dbg_printf("\na\n");
1894 *gOnly=FALSE;
1895 *nOnly=FALSE;
1896 *acOnly=FALSE;
1897 }
1898 else
1899 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1900
1901 //for a,n mode
1902 if(radioIndex == 1)
1903 {
1904 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1905 if(strcmp(buf,"1")==0)
1906 {
1907 strncpy(output_string, "n", 1);
1908 *nOnly=FALSE;
1909 }
1910 }
1911
1912 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1913 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1914 return RETURN_OK;
1915#endif
1916}
1917
developerdb744382022-09-13 15:34:54 +08001918INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1919{
1920 char cmd[128] = {0};
1921 char buf[64] = {0};
1922 char config_file[64] = {0};
1923 wifi_band band;
1924
1925 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1926 if(NULL == output_string || NULL == pureMode)
1927 return RETURN_ERR;
1928
1929 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001930 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer7c4cd202023-03-01 10:56:29 +08001931 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | sed \"s/ieee80211\\.*/\1/\"", config_file);
developerdb744382022-09-13 15:34:54 +08001932 _syscmd(cmd, buf, sizeof(buf));
1933
1934 band = wifi_index_to_band(radioIndex);
1935 // puremode is a bit map
1936 *pureMode = 0;
1937 if (band == band_2_4) {
1938 strcat(output_string, "b,g");
1939 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1940 if (strstr(buf, "n") != NULL) {
1941 strcat(output_string, ",n");
1942 *pureMode |= WIFI_MODE_N;
1943 }
1944 if (strstr(buf, "ax") != NULL) {
1945 strcat(output_string, ",ax");
1946 *pureMode |= WIFI_MODE_AX;
1947 }
developer7c4cd202023-03-01 10:56:29 +08001948 if (strstr(buf, "be") != NULL) {
1949 strcat(output_string, ",be");
1950 *pureMode |= WIFI_MODE_BE;
1951 }
developerdb744382022-09-13 15:34:54 +08001952 } else if (band == band_5) {
1953 strcat(output_string, "a");
1954 *pureMode |= WIFI_MODE_A;
1955 if (strstr(buf, "n") != NULL) {
1956 strcat(output_string, ",n");
1957 *pureMode |= WIFI_MODE_N;
1958 }
1959 if (strstr(buf, "ac") != NULL) {
1960 strcat(output_string, ",ac");
1961 *pureMode |= WIFI_MODE_AC;
1962 }
1963 if (strstr(buf, "ax") != NULL) {
1964 strcat(output_string, ",ax");
1965 *pureMode |= WIFI_MODE_AX;
1966 }
developer7c4cd202023-03-01 10:56:29 +08001967 if (strstr(buf, "be") != NULL) {
1968 strcat(output_string, ",be");
1969 *pureMode |= WIFI_MODE_BE;
1970 }
developerdb744382022-09-13 15:34:54 +08001971 } else if (band == band_6) {
1972 if (strstr(buf, "ax") != NULL) {
1973 strcat(output_string, "ax");
1974 *pureMode |= WIFI_MODE_AX;
1975 }
developer7c4cd202023-03-01 10:56:29 +08001976 if (strstr(buf, "be") != NULL) {
1977 strcat(output_string, ",be");
1978 *pureMode |= WIFI_MODE_BE;
1979 }
developerdb744382022-09-13 15:34:54 +08001980 }
1981
1982 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1983 return RETURN_OK;
1984}
1985
1986// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001987INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1988{
1989 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1990 if (strcmp (channelMode,"11A") == 0)
1991 {
1992 writeBandWidth(radioIndex,"20MHz");
1993 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1994 printf("\nChannel Mode is 802.11a (5GHz)\n");
1995 }
1996 else if (strcmp (channelMode,"11NAHT20") == 0)
1997 {
1998 writeBandWidth(radioIndex,"20MHz");
1999 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2000 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2001 }
2002 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2003 {
2004 writeBandWidth(radioIndex,"40MHz");
2005 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2006 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2007 }
2008 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2009 {
2010 writeBandWidth(radioIndex,"40MHz");
2011 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2012 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2013 }
2014 else if (strcmp (channelMode,"11ACVHT20") == 0)
2015 {
2016 writeBandWidth(radioIndex,"20MHz");
2017 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2018 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2019 }
2020 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2021 {
2022 writeBandWidth(radioIndex,"40MHz");
2023 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2024 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2025 }
2026 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2027 {
2028 writeBandWidth(radioIndex,"40MHz");
2029 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2030 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2031 }
2032 else if (strcmp (channelMode,"11ACVHT80") == 0)
2033 {
2034 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2035 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2036 }
2037 else if (strcmp (channelMode,"11ACVHT160") == 0)
2038 {
2039 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2040 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2041 }
2042 else if (strcmp (channelMode,"11B") == 0)
2043 {
2044 writeBandWidth(radioIndex,"20MHz");
2045 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2046 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2047 }
2048 else if (strcmp (channelMode,"11G") == 0)
2049 {
2050 writeBandWidth(radioIndex,"20MHz");
2051 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2052 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2053 }
2054 else if (strcmp (channelMode,"11NGHT20") == 0)
2055 {
2056 writeBandWidth(radioIndex,"20MHz");
2057 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2058 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2059 }
2060 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2061 {
2062 writeBandWidth(radioIndex,"40MHz");
2063 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2064 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2065 }
2066 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2067 {
2068 writeBandWidth(radioIndex,"40MHz");
2069 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2070 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2071 }
2072 else
2073 {
2074 return RETURN_ERR;
2075 }
2076 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2077
2078 return RETURN_OK;
2079}
2080
developerdb744382022-09-13 15:34:54 +08002081// Set the radio operating mode, and pure mode flag.
2082INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2083{
developer7c4cd202023-03-01 10:56:29 +08002084 int num_hostapd_support_mode = 4; // n, ac, ax, be
developerdb744382022-09-13 15:34:54 +08002085 struct params list[num_hostapd_support_mode];
2086 char config_file[64] = {0};
2087 char bandwidth[16] = {0};
developer7c4cd202023-03-01 10:56:29 +08002088 char supported_mode[32] = {0};
developerdb744382022-09-13 15:34:54 +08002089 int mode_check_bit = 1 << 3; // n mode
developer7c4cd202023-03-01 10:56:29 +08002090 bool eht_support = FALSE;
developerdb744382022-09-13 15:34:54 +08002091
2092 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2093 // Set radio mode
2094 list[0].name = "ieee80211n";
2095 list[1].name = "ieee80211ac";
2096 list[2].name = "ieee80211ax";
developer7c4cd202023-03-01 10:56:29 +08002097 list[3].name = "ieee80211be";
developerdb744382022-09-13 15:34:54 +08002098 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2099
2100 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002101 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002102 list[0].value = "1";
2103 else
2104 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002105 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002106 list[1].value = "1";
2107 else
2108 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002109 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002110 list[2].value = "1";
2111 else
2112 list[2].value = "0";
developer7c4cd202023-03-01 10:56:29 +08002113 if (pureMode & WIFI_MODE_BE)
2114 list[3].value = "1";
2115 else
2116 list[3].value = "0";
2117
2118 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2119 if (strstr(supported_mode, "be") != NULL)
2120 eht_support = TRUE;
2121
2122 if (eht_support)
2123 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2124 else
2125 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode-1);
developerdb744382022-09-13 15:34:54 +08002126
2127 if (channelMode == NULL || strlen(channelMode) == 0)
2128 return RETURN_OK;
2129 // Set bandwidth
2130 if (strstr(channelMode, "40") != NULL)
2131 strcpy(bandwidth, "40MHz");
2132 else if (strstr(channelMode, "80") != NULL)
2133 strcpy(bandwidth, "80MHz");
2134 else if (strstr(channelMode, "160") != NULL)
2135 strcpy(bandwidth, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002136 else if (strstr(channelMode, "320") != NULL)
2137 strcpy(bandwidth, "320MHz");
developerdb744382022-09-13 15:34:54 +08002138 else // 11A, 11B, 11G....
2139 strcpy(bandwidth, "20MHz");
2140
2141 writeBandWidth(radioIndex, bandwidth);
2142 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2143
2144 wifi_reloadAp(radioIndex);
2145 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2146
2147 return RETURN_OK;
2148}
2149
developer1d12ebf2022-10-04 15:13:38 +08002150INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2151
2152 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002153 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002154 struct params params = {0};
2155 wifi_band band = band_invalid;
2156
2157 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2158
2159 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002160
2161 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002162 return RETURN_ERR;
2163 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2164 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002165 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2166 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002167
2168 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2169 params.name = "hw_mode";
2170 params.value = hw_mode;
2171 wifi_hostapdWrite(config_file, &params, 1);
2172 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2173
developeref938762022-10-19 17:21:01 +08002174 if (band == band_2_4) {
2175 if (strncmp(hw_mode, "b", 1) == 0) {
2176 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2177 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2178 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2179 snprintf(buf, sizeof(buf), "%s", "1,2");
2180 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2181 } else {
2182 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2183
2184 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2185 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2186 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2187 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2188 }
2189 }
2190
developer1d12ebf2022-10-04 15:13:38 +08002191 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2192 return RETURN_OK;
2193}
2194
developere8988ba2022-10-18 17:42:30 +08002195INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2196{
2197 char config_file[64] = {0};
2198 struct params params = {0};
2199 wifi_band band = band_invalid;
2200
2201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2202
2203 band = wifi_index_to_band(radioIndex);
2204
2205 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2206 params.name = "noscan";
2207 params.value = noscan;
2208 wifi_hostapdWrite(config_file, &params, 1);
2209 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2210
2211 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2212 return RETURN_OK;
2213}
2214
developer06a01d92022-09-07 16:32:39 +08002215//Get the list of supported channel. eg: "1-11"
2216//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2217INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2218{
developer6318ed52022-09-13 15:17:58 +08002219 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002220 if (NULL == output_string)
2221 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002222 char cmd[256] = {0};
2223 char buf[128] = {0};
2224 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002225 int phyId = 0;
2226
developer6318ed52022-09-13 15:17:58 +08002227 // Parse possible channel number and separate them with commas.
2228 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002229 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002230 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002231 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002232 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer6318ed52022-09-13 15:17:58 +08002233 else
developer033b37b2022-10-18 11:27:46 +08002234 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar\\|no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer6318ed52022-09-13 15:17:58 +08002235
2236 _syscmd(cmd,buf,sizeof(buf));
2237 strncpy(output_string, buf, sizeof(buf));
2238
2239 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2240 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002241}
2242
2243//Get the list for used channel. eg: "1,6,9,11"
2244//The output_string is a max length 256 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2245INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2246{
developerd946fd62022-12-08 18:03:28 +08002247 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002248 char cmd[128] = {0};
2249 char buf[128] = {0};
2250 char config_file[64] = {0};
2251 int channel = 0;
2252 int freq = 0;
2253 int bandwidth = 0;
2254 int center_freq = 0;
2255 int center_channel = 0;
2256 int channel_delta = 0;
2257 wifi_band band = band_invalid;
2258
2259 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2260
developer06a01d92022-09-07 16:32:39 +08002261 if (NULL == output_string)
2262 return RETURN_ERR;
2263
developerac6f1142022-12-20 19:26:35 +08002264 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +08002265 return RETURN_ERR;
2266 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002267 _syscmd(cmd, buf, sizeof(buf));
2268 if (strlen(buf) == 0) {
2269 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2270 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002271 }
developerf5745ee2022-10-05 16:09:53 +08002272 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2273
2274 if (bandwidth == 20) {
2275 snprintf(output_string, 256, "%d", channel);
2276 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002277 }
developerf5745ee2022-10-05 16:09:53 +08002278
2279 center_channel = ieee80211_frequency_to_channel(center_freq);
2280
2281 band = wifi_index_to_band(radioIndex);
2282 if (band == band_2_4 && bandwidth == 40) {
2283 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2284 memset(buf, 0, sizeof(buf));
2285 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2286
developerf22724d2022-12-22 17:24:14 +08002287 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
developerf5745ee2022-10-05 16:09:53 +08002288 snprintf(output_string, 256, "%d,%d", channel, channel+4);
developerf22724d2022-12-22 17:24:14 +08002289 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
developerf5745ee2022-10-05 16:09:53 +08002290 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2291 } else {
2292 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2293 return RETURN_ERR;
2294 }
2295 } else if (band == band_5 || band == band_6){
2296 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
developer72ec5572023-01-05 16:27:13 +08002297 // example: bandwidth 80: center is 42 (5210), channels are "36,40,44,48" (5170-5250). The delta should be 6.
developerf5745ee2022-10-05 16:09:53 +08002298 channel_delta = (bandwidth-20)/10;
developer72ec5572023-01-05 16:27:13 +08002299 memset(output_string, 0, 256);
2300 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2301 // If i is not the last channel, we add a comma.
2302 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2303 strncat(output_string, buf, strlen(buf));
2304 }
developerf5745ee2022-10-05 16:09:53 +08002305 } else
2306 return RETURN_ERR;
2307
2308 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002309 return RETURN_OK;
2310}
2311
2312//Get the running channel number
2313INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2314{
developer5b398df2022-11-17 20:39:48 +08002315 char channel_str[16] = {0};
2316 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002317
developer5b398df2022-11-17 20:39:48 +08002318 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002319 return RETURN_ERR;
2320
developer5b398df2022-11-17 20:39:48 +08002321 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2322 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002323
developer5b398df2022-11-17 20:39:48 +08002324 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002325
developer06a01d92022-09-07 16:32:39 +08002326 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002327}
2328
2329
2330INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2331{
2332 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002333 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002334
2335 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2336 if (NULL == output_ulong)
2337 return RETURN_ERR;
2338
developer06a01d92022-09-07 16:32:39 +08002339 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002340 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2341 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002342 _syscmd(cmd,buf,sizeof(buf));
2343 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2344 if (*output_ulong == 0) {
2345 return RETURN_ERR;
2346 }
2347
2348 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2349 return RETURN_OK;
2350}
2351
2352//Storing the previous channel value
2353INT wifi_storeprevchanval(INT radioIndex)
2354{
2355 char buf[256] = {0};
2356 char output[4]={'\0'};
2357 char config_file[MAX_BUF_SIZE] = {0};
2358 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2359 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2360 if(radioIndex == 0)
2361 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2362 else if(radioIndex == 1)
2363 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2364 system(buf);
2365 Radio_flag = FALSE;
2366 return RETURN_OK;
2367}
2368
2369//Set the running channel number
2370INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2371{
developer76989232022-10-04 14:13:19 +08002372 // We only write hostapd config here
2373 char str_channel[8]={0};
2374 char *list_channel;
2375 char config_file[128] = {0};
2376 char possible_channels[256] = {0};
2377 int max_radio_num = 0;
2378 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002379
developer76989232022-10-04 14:13:19 +08002380 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002381
developer76989232022-10-04 14:13:19 +08002382 // Check valid
2383 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002384
developer76989232022-10-04 14:13:19 +08002385 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2386 list_channel = strtok(possible_channels, ",");
2387 while(true)
developer06a01d92022-09-07 16:32:39 +08002388 {
developer76989232022-10-04 14:13:19 +08002389 if(list_channel == NULL) { // input not in the list
2390 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2391 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002392 }
developer76989232022-10-04 14:13:19 +08002393 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2394 break;
2395 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002396 }
2397
developer76989232022-10-04 14:13:19 +08002398 list.name = "channel";
2399 list.value = str_channel;
2400 wifi_getMaxRadioNumber(&max_radio_num);
2401 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002402 {
developer76989232022-10-04 14:13:19 +08002403 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2404 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002405 }
2406
developer76989232022-10-04 14:13:19 +08002407 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002408 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002409}
developer06a01d92022-09-07 16:32:39 +08002410
2411INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2412{
developer7c4cd202023-03-01 10:56:29 +08002413 struct params list[3];
2414 char str_idx[16] = {0};
2415 char supported_mode[32] = {0};
2416 char config_file[64] = {0};
developer76989232022-10-04 14:13:19 +08002417 int max_num_radios = 0;
2418 wifi_band band = band_invalid;
developer7c4cd202023-03-01 10:56:29 +08002419 bool eht_support = FALSE;
developer76989232022-10-04 14:13:19 +08002420
2421 band = wifi_index_to_band(radioIndex);
2422 if (band == band_2_4)
2423 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002424
developer7c4cd202023-03-01 10:56:29 +08002425 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2426 if (strstr(supported_mode, "be") != NULL)
2427 eht_support = TRUE;
2428
developer30423732022-12-01 16:17:49 +08002429 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002430 list[0].name = "vht_oper_centr_freq_seg0_idx";
2431 list[0].value = str_idx;
2432 list[1].name = "he_oper_centr_freq_seg0_idx";
2433 list[1].value = str_idx;
developer7c4cd202023-03-01 10:56:29 +08002434 list[2].name = "eht_oper_centr_freq_seg0_idx";
2435 list[2].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002436
developer76989232022-10-04 14:13:19 +08002437 wifi_getMaxRadioNumber(&max_num_radios);
2438 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002439 {
developer76989232022-10-04 14:13:19 +08002440 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
developer7c4cd202023-03-01 10:56:29 +08002441 if (eht_support)
2442 wifi_hostapdWrite(config_file, list, 3);
developer76989232022-10-04 14:13:19 +08002443 else
2444 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002445 }
2446
2447 return RETURN_OK;
2448}
2449
2450//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2451//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2452INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2453{
2454 //Set to wifi config only. Wait for wifi reset to apply.
2455 char buf[256] = {0};
2456 char str_channel[256] = {0};
2457 int count = 0;
2458 ULONG Value = 0;
2459 FILE *fp = NULL;
2460 if(enable == TRUE)
2461 {
developer06a01d92022-09-07 16:32:39 +08002462 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002463 }
developer5884e982022-10-06 10:52:50 +08002464 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002465}
2466
developer0b246d12022-09-30 15:24:20 +08002467INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2468{
2469 if (output_bool == NULL)
2470 return RETURN_ERR;
2471
2472 *output_bool = TRUE;
2473
2474 return RETURN_OK;
2475}
2476
developer06a01d92022-09-07 16:32:39 +08002477INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2478{
2479 if (NULL == output_bool)
2480 return RETURN_ERR;
2481 *output_bool=FALSE;
2482 return RETURN_OK;
2483}
2484
2485INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2486{
2487 if (NULL == output_bool)
2488 return RETURN_ERR;
2489 *output_bool=FALSE;
2490 return RETURN_OK;
2491}
2492
2493INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2494{
2495 //Set to wifi config only. Wait for wifi reset to apply.
2496 return RETURN_OK;
2497}
2498
2499INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2500{
2501 return RETURN_OK;
2502}
2503
2504INT wifi_factoryResetAP(int apIndex)
2505{
developer838cca92022-10-03 13:19:57 +08002506 char ap_config_file[64] = {0};
2507 char cmd[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002508 char buf[128] = {0};
developer89df4502023-02-16 20:45:02 +08002509 int max_radio_num = 0;
developer838cca92022-10-03 13:19:57 +08002510
developer06a01d92022-09-07 16:32:39 +08002511 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002512
2513 wifi_setApEnable(apIndex, FALSE);
2514 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2515 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
developer72ec5572023-01-05 16:27:13 +08002516 _syscmd(cmd, buf, sizeof(buf));
developer89df4502023-02-16 20:45:02 +08002517 wifi_getMaxRadioNumber(&max_radio_num);
2518 if (apIndex <= max_radio_num) // The ap is default radio interface, we should default up it.
2519 wifi_setApEnable(apIndex, TRUE);
developer838cca92022-10-03 13:19:57 +08002520
developer06a01d92022-09-07 16:32:39 +08002521 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002522
developer06a01d92022-09-07 16:32:39 +08002523 return RETURN_OK;
2524}
2525
2526//To set Band Steering AP group
2527//To-do
2528INT wifi_setBandSteeringApGroup(char *ApGroup)
2529{
2530 return RETURN_OK;
2531}
2532
developer1e5aa162022-09-13 16:06:24 +08002533INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2534{
2535 char config_file[128] = {'\0'};
2536 char buf[128] = {'\0'};
2537
2538 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2539 if (dtimInterval == NULL)
2540 return RETURN_ERR;
2541
2542 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2543 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2544
2545 if (strlen(buf) == 0) {
2546 *dtimInterval = 2;
2547 } else {
2548 *dtimInterval = strtoul(buf, NULL, 10);
2549 }
2550
2551 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2552 return RETURN_OK;
2553}
2554
developer06a01d92022-09-07 16:32:39 +08002555INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2556{
developer5f222492022-09-13 15:21:52 +08002557 struct params params={0};
2558 char config_file[MAX_BUF_SIZE] = {'\0'};
2559 char buf[MAX_BUF_SIZE] = {'\0'};
2560
2561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2562 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002563 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002564 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002565 }
2566
2567 params.name = "dtim_period";
2568 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2569 params.value = buf;
2570
2571 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2572 wifi_hostapdWrite(config_file, &params, 1);
2573 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2574
2575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2576 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002577}
2578
2579//Check if the driver support the Dfs
2580INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2581{
developer78a15382022-11-02 10:57:40 +08002582 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002583 if (NULL == output_bool)
2584 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002585 *output_bool=FALSE;
2586
2587 band = wifi_index_to_band(radioIndex);
2588 if (band == band_5)
2589 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002590 return RETURN_OK;
2591}
2592
2593//The output_string is a max length 256 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2594//The value of this parameter is a comma seperated list of channel number
2595INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2596{
2597 if (NULL == output_pool)
2598 return RETURN_ERR;
2599 if (radioIndex==1)
2600 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2601 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2602
2603 return RETURN_OK;
2604}
2605
2606INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2607{
2608 //Set to wifi config. And apply instantly.
2609 return RETURN_OK;
2610}
2611
2612INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2613{
2614 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2615 return RETURN_ERR;
2616 *output_interval_seconds=1800;
2617 *output_dwell_milliseconds=40;
2618
2619 return RETURN_OK;
2620}
2621
2622INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2623{
2624 //Set to wifi config. And apply instantly.
2625 return RETURN_OK;
2626}
2627
developerbfc18512022-10-05 17:54:28 +08002628INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2629{
2630 if (output_bool == NULL)
2631 return RETURN_ERR;
2632 *output_bool = true;
2633 return RETURN_OK;
2634}
2635
2636INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2637{
2638 return RETURN_OK;
2639}
2640
developer06a01d92022-09-07 16:32:39 +08002641//Get the Dfs enable status
2642INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2643{
developer9964b5b2022-09-13 15:59:34 +08002644 char buf[16] = {0};
2645 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002646
2647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2648
developer30423732022-12-01 16:17:49 +08002649 if (output_bool == NULL)
2650 return RETURN_ERR;
2651
developer9964b5b2022-09-13 15:59:34 +08002652 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002653 f = fopen(DFS_ENABLE_FILE, "r");
2654 if (f != NULL) {
2655 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002656 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002657 *output_bool = FALSE;
2658 fclose(f);
2659 }
2660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002661 return RETURN_OK;
2662}
2663
2664//Set the Dfs enable status
2665INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2666{
developer9964b5b2022-09-13 15:59:34 +08002667 char config_file[128] = {0};
2668 FILE *f = NULL;
2669 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002670
2671 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2672
developer9964b5b2022-09-13 15:59:34 +08002673 f = fopen(DFS_ENABLE_FILE, "w");
2674 if (f == NULL)
2675 return RETURN_ERR;
2676 fprintf(f, "%d", enable);
2677 fclose(f);
2678
2679 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002680 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002681 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2682 wifi_hostapdWrite(config_file, &params, 1);
2683 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2684
2685 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2686
developer9964b5b2022-09-13 15:59:34 +08002687 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002688 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002689}
2690
2691//Check if the driver support the AutoChannelRefreshPeriod
2692INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2693{
2694 if (NULL == output_bool)
2695 return RETURN_ERR;
2696 *output_bool=FALSE; //not support
2697
2698 return RETURN_OK;
2699}
2700
2701//Get the ACS refresh period in seconds
2702INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2703{
2704 if (NULL == output_ulong)
2705 return RETURN_ERR;
2706 *output_ulong=300;
2707
2708 return RETURN_OK;
2709}
2710
2711//Set the ACS refresh period in seconds
2712INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2713{
2714 return RETURN_ERR;
2715}
2716
developer7c4cd202023-03-01 10:56:29 +08002717INT getEHT320ChannelBandwidthSet(int radioIndex, int *BandwidthSet)
2718{
2719 int center_channel = 0;
2720 char config_file[32] = {0};
2721 char buf[32] = {0};
2722
2723 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2724 wifi_hostapdRead(config_file, "eht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2725
2726 center_channel = strtoul(buf, NULL, 10);
2727 center_channel += 1; // Add 1 to become muiltiple of 16
2728 if (center_channel % 64 == 32)
2729 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_1MHZ;
2730 else if (center_channel % 64 == 0)
2731 *BandwidthSet = WIFI_CHANNELBANDWIDTH_320_2MHZ;
2732 else
2733 return RETURN_ERR;
2734 return RETURN_OK;
2735}
2736
developer06a01d92022-09-07 16:32:39 +08002737//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2738//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2739INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2740{
developer72ec5572023-01-05 16:27:13 +08002741 char buf[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002742 char extchannel[128] = {0};
developer72ec5572023-01-05 16:27:13 +08002743 char config_file[128] = {0};
developer70490032022-09-13 15:45:20 +08002744 BOOL radio_enable = FALSE;
developerfa41b1f2023-01-06 10:25:51 +08002745 wifi_band band;
developer70490032022-09-13 15:45:20 +08002746
2747 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2748
developer06a01d92022-09-07 16:32:39 +08002749 if (NULL == output_string)
2750 return RETURN_ERR;
2751
developer70490032022-09-13 15:45:20 +08002752 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2753 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002754
developer70490032022-09-13 15:45:20 +08002755 if (radio_enable != TRUE)
2756 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002757
developerfa41b1f2023-01-06 10:25:51 +08002758 band = wifi_index_to_band(radioIndex);
developer72ec5572023-01-05 16:27:13 +08002759 if (band == band_2_4) {
developerfa41b1f2023-01-06 10:25:51 +08002760 wifi_getRadioExtChannel(radioIndex, extchannel);
developer72ec5572023-01-05 16:27:13 +08002761 if (strncmp(extchannel, "Auto", 4) == 0) // Auto means that we did not set ht_capab HT40+/-
2762 snprintf(output_string, 64, "20MHz");
2763 else
2764 snprintf(output_string, 64, "40MHz");
2765
2766 } else {
2767 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2768 wifi_hostapdRead(config_file, "he_oper_chwidth", buf, sizeof(buf));
2769 if (strncmp(buf, "0", 1) == 0) { // Check whether we set central channel
2770 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2771 if (strncmp(buf, "0", 1) == 0)
2772 snprintf(output_string, 64, "20MHz");
2773 else
2774 snprintf(output_string, 64, "40MHz");
2775
2776 } else if (strncmp(buf, "1", 1) == 0)
2777 snprintf(output_string, 64, "80MHz");
developer7c4cd202023-03-01 10:56:29 +08002778 else if (strncmp(buf, "2", 1) == 0) {
developer72ec5572023-01-05 16:27:13 +08002779 snprintf(output_string, 64, "160MHz");
developer7c4cd202023-03-01 10:56:29 +08002780 wifi_hostapdRead(config_file, "eht_oper_chwidth", buf, sizeof(buf));
2781 if (strncmp(buf, "9", 1) == 0) {
2782 int BandwidthSet = 0;
2783 if (getEHT320ChannelBandwidthSet(radioIndex, &BandwidthSet) != RETURN_OK)
2784 return RETURN_ERR;
2785 if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_1MHZ)
2786 snprintf(output_string, 64, "320-1MHz");
2787 else if (BandwidthSet == WIFI_CHANNELBANDWIDTH_320_2MHZ)
2788 snprintf(output_string, 64, "320-2MHz");
2789 }
2790 }
developer06a01d92022-09-07 16:32:39 +08002791 }
developer72ec5572023-01-05 16:27:13 +08002792
developer06a01d92022-09-07 16:32:39 +08002793 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002794
2795 return RETURN_OK;
2796}
2797
2798//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002799INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002800{
developerf7a466e2022-09-29 11:55:56 +08002801 char config_file[128];
2802 char set_value[16];
developer7c4cd202023-03-01 10:56:29 +08002803 char supported_mode[32] = {0};
2804 struct params params[3];
developerf7a466e2022-09-29 11:55:56 +08002805 int max_radio_num = 0;
developer7c4cd202023-03-01 10:56:29 +08002806 bool eht_support = FALSE;
developerf7a466e2022-09-29 11:55:56 +08002807
developer06a01d92022-09-07 16:32:39 +08002808 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002809
developerf7a466e2022-09-29 11:55:56 +08002810 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002811 return RETURN_ERR;
2812
developer7c4cd202023-03-01 10:56:29 +08002813 if(strstr(bandwidth,"160") != NULL || strstr(bandwidth,"320") != NULL)
developerf7a466e2022-09-29 11:55:56 +08002814 strcpy(set_value, "2");
2815 else if(strstr(bandwidth,"80") != NULL)
2816 strcpy(set_value, "1");
2817 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2818 strcpy(set_value, "0");
developer72ec5572023-01-05 16:27:13 +08002819 else if (strstr(bandwidth, "Auto") != NULL)
2820 return RETURN_OK;
2821 else {
developerf7a466e2022-09-29 11:55:56 +08002822 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002823 return RETURN_ERR;
2824 }
2825
developer7c4cd202023-03-01 10:56:29 +08002826 wifi_getRadioSupportedStandards(radioIndex, supported_mode);
2827 if (strstr(supported_mode, "be") != NULL)
2828 eht_support = TRUE;
2829
developerf7a466e2022-09-29 11:55:56 +08002830 params[0].name = "vht_oper_chwidth";
2831 params[0].value = set_value;
2832 params[1].name = "he_oper_chwidth";
2833 params[1].value = set_value;
developer7c4cd202023-03-01 10:56:29 +08002834 params[2].name = "eht_oper_chwidth";
2835 if (strstr(bandwidth,"320") != NULL) // We set oper_chwidth to 9 for EHT320
2836 params[2].value = "9";
2837 else
2838 params[2].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002839
developerf7a466e2022-09-29 11:55:56 +08002840 wifi_getMaxRadioNumber(&max_radio_num);
2841 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002842 {
developer7c4cd202023-03-01 10:56:29 +08002843 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2844 if (eht_support == TRUE)
2845 wifi_hostapdWrite(config_file, params, 3);
2846 else
2847 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002848 }
2849
2850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2851 return RETURN_OK;
2852}
2853
2854//Getting current radio extension channel
2855INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2856{
2857 CHAR buf[150] = {0};
2858 CHAR cmd[150] = {0};
2859 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2860 _syscmd(cmd, buf, sizeof(buf));
2861 if(NULL != strstr(buf,"HT40+"))
2862 strcpy(Value,"AboveControlChannel");
2863 else if(NULL != strstr(buf,"HT40-"))
2864 strcpy(Value,"BelowControlChannel");
2865 return RETURN_OK;
2866}
2867
2868//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2869//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2870INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2871{
developerfa41b1f2023-01-06 10:25:51 +08002872 char config_file[64] = {0};
developerfa41b1f2023-01-06 10:25:51 +08002873 wifi_band band;
developerfa41b1f2023-01-06 10:25:51 +08002874
2875 if (output_string == NULL)
developer06a01d92022-09-07 16:32:39 +08002876 return RETURN_ERR;
2877
developerfa41b1f2023-01-06 10:25:51 +08002878 band = wifi_index_to_band(radioIndex);
2879 if (band == band_invalid)
developer06a01d92022-09-07 16:32:39 +08002880 return RETURN_ERR;
developerfa41b1f2023-01-06 10:25:51 +08002881
2882 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2883
2884 snprintf(output_string, 64, "Auto");
developer72ec5572023-01-05 16:27:13 +08002885 wifi_halgetRadioExtChannel(config_file, output_string);
developer06a01d92022-09-07 16:32:39 +08002886
2887 return RETURN_OK;
2888}
2889
developer57fa24a2023-03-15 17:25:07 +08002890// This function handle 20MHz to remove HT40+/- in hostapd config, other bandwidths are handled in wifi_setRadioExtChannel.
2891INT wifi_RemoveRadioExtChannel(INT radioIndex, CHAR *ext_str)
2892{
2893 struct params params={0};
2894 char config_file[64] = {0};
2895 char ht_capab[128]={0};
2896 char buf[128] = {0};
2897 char cmd[128] = {0};
2898 int max_radio_num =0;
2899 bool stbcEnable = FALSE;
2900
2901 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2902 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2903 _syscmd(cmd, buf, sizeof(buf));
2904 if (strlen(buf) != 0)
2905 stbcEnable = TRUE;
2906
2907 strcpy(ht_capab, HOSTAPD_HT_CAPAB);
2908 params.value = ht_capab;
2909 params.name = "ht_capab";
2910
2911 wifi_getMaxRadioNumber(&max_radio_num);
2912 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2913 {
2914 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2915 wifi_hostapdWrite(config_file, &params, 1);
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;
developer643b28f2023-04-04 10:26:01 +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));
developerf7e92b62023-05-04 17:06:52 +080011181 if (strncmp(buf, "1", 1) == 0) {
developer58599c22022-09-13 16:40:34 +080011182 *enable = true;
developerf7e92b62023-05-04 17:06:52 +080011183 *precac = true;
11184 } else {
developer58599c22022-09-13 16:40:34 +080011185 *enable = false;
developerf7e92b62023-05-04 17:06:52 +080011186 *precac = false;
11187 }
developer58599c22022-09-13 16:40:34 +080011188
11189 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11190 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011191}
11192
11193INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11194{
developer58599c22022-09-13 16:40:34 +080011195 *supported = TRUE;
11196 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011197}
11198
developera7149722023-01-11 11:36:21 +080011199bool check_is_hemu_vendor_new_patch() {
11200 char cmd[128] = {0};
11201 char buf[128] = {0};
11202
11203 snprintf(cmd, sizeof(cmd), "hostapd_cli -h 2>&1 | grep set_hemu");
11204 _syscmd(cmd, buf, sizeof(buf));
11205
11206 if (strlen(buf) > 0)
11207 return FALSE;
11208 else
11209 return TRUE;
11210}
11211
developer3e6b1692022-09-30 18:04:05 +080011212INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11213{
11214 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11215 struct params params = {0};
11216 char config_file[64] = {0};
11217 char buf[64] = {0};
developera7149722023-01-11 11:36:21 +080011218 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011219 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011220 bool new_vendor_patch = FALSE;
developer3e6b1692022-09-30 18:04:05 +080011221 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11222
developera7149722023-01-11 11:36:21 +080011223 wifi_getDownlinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011224
11225 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11226 set_mu_type &= ~0x05; // unset bit 0, 2
11227 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11228 set_mu_type |= 0x01;
11229 set_mu_type &= ~0x04;
11230 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11231 set_mu_type &= ~0x01;
11232 set_mu_type |= 0x04;
11233 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11234 set_mu_type |= 0x05; // set bit 0, 2
11235 }
11236
developera7149722023-01-11 11:36:21 +080011237 new_vendor_patch = check_is_hemu_vendor_new_patch();
11238 if (new_vendor_patch)
11239 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11240 else
11241 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11242
11243 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011244 sprintf(buf, "%u", set_mu_type);
11245 params.value = buf;
11246 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11247 wifi_hostapdWrite(config_file, &params, 1);
11248 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011249 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011250
11251 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11252 return RETURN_OK;
11253}
11254
11255INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11256{
11257 struct params params={0};
11258 char config_file[64] = {0};
11259 char buf[64] = {0};
11260 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011261 bool new_vendor_patch = FALSE;
11262 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011263
11264 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11265
11266 if (mu_type == NULL)
11267 return RETURN_ERR;
11268
developera7149722023-01-11 11:36:21 +080011269 new_vendor_patch = check_is_hemu_vendor_new_patch();
11270
11271 if (new_vendor_patch)
11272 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11273 else
11274 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11275
developer3e6b1692022-09-30 18:04:05 +080011276 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011277 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011278 get_mu_type = strtol(buf, NULL, 10);
11279
11280 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11281 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11282 else if (get_mu_type & 0x04)
11283 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11284 else if (get_mu_type & 0x01)
11285 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11286 else
11287 *mu_type = WIFI_DL_MU_TYPE_NONE;
11288
11289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11290 return RETURN_OK;
11291}
11292
11293INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11294{
11295 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11296 struct params params={0};
11297 char config_file[64] = {0};
11298 char buf[64] = {0};
11299 unsigned int set_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011300 bool new_vendor_patch = FALSE;
11301 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011302 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11303
developera7149722023-01-11 11:36:21 +080011304 wifi_getUplinkMuType(radio_index, &set_mu_type);
developer3e6b1692022-09-30 18:04:05 +080011305
11306 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11307 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11308 set_mu_type &= ~0x0a;
11309 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11310 set_mu_type |= 0x02;
11311 set_mu_type &= ~0x08;
11312 }
11313
developera7149722023-01-11 11:36:21 +080011314 new_vendor_patch = check_is_hemu_vendor_new_patch();
11315
11316 if (new_vendor_patch)
11317 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11318 else
11319 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11320
11321 params.name = hemu_vendor_cmd;
developer3e6b1692022-09-30 18:04:05 +080011322 sprintf(buf, "%u", set_mu_type);
11323 params.value = buf;
11324 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11325 wifi_hostapdWrite(config_file, &params, 1);
11326 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developera7149722023-01-11 11:36:21 +080011327 wifi_reloadAp(radio_index);
developer3e6b1692022-09-30 18:04:05 +080011328
11329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11330 return RETURN_OK;
11331}
11332
11333INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11334{
11335 struct params params={0};
11336 char config_file[64] = {0};
11337 char buf[64] = {0};
11338 unsigned int get_mu_type = 0;
developera7149722023-01-11 11:36:21 +080011339 bool new_vendor_patch = FALSE;
11340 char hemu_vendor_cmd[16] = {0};
developer3e6b1692022-09-30 18:04:05 +080011341
11342 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11343
developera7149722023-01-11 11:36:21 +080011344 new_vendor_patch = check_is_hemu_vendor_new_patch();
11345
11346 if (new_vendor_patch)
11347 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "mu_onoff");
11348 else
11349 snprintf(hemu_vendor_cmd, sizeof(hemu_vendor_cmd), "hemu_onoff");
11350
developer3e6b1692022-09-30 18:04:05 +080011351 if (mu_type == NULL)
11352 return RETURN_ERR;
11353
11354 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
developera7149722023-01-11 11:36:21 +080011355 wifi_hostapdRead(config_file, hemu_vendor_cmd, buf, sizeof(buf));
developer3e6b1692022-09-30 18:04:05 +080011356
11357 get_mu_type = strtol(buf, NULL, 10);
11358 if (get_mu_type & 0x02)
11359 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11360 else
11361 *mu_type = WIFI_DL_MU_TYPE_NONE;
11362
11363 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11364 return RETURN_OK;
11365}
11366
11367
developer454b9462022-09-13 15:29:16 +080011368INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11369{
11370 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011371 char buf[256] = {0};
11372 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011373 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011374 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011375 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011376 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011377
11378 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11379
developer254882b2022-09-30 17:12:31 +080011380 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011381 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11382 return RETURN_ERR;
11383 }
developer454b9462022-09-13 15:29:16 +080011384
developer254882b2022-09-30 17:12:31 +080011385 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011386 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011387
developer254882b2022-09-30 17:12:31 +080011388 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11389 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011390 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011391 _syscmd(cmd, buf, sizeof(buf));
11392 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11393 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11394 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011395 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 +080011396 _syscmd(cmd, buf, sizeof(buf));
11397 }
11398 if (band == band_5) {
11399 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11400 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011401 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 +080011402 _syscmd(cmd, buf, sizeof(buf));
11403 }
11404 }
11405 }
11406 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011407
developer254882b2022-09-30 17:12:31 +080011408 if (guard_interval == wifi_guard_interval_400)
11409 strcpy(GI, "0.4");
11410 else if (guard_interval == wifi_guard_interval_800)
11411 strcpy(GI, "0.8");
11412 else if (guard_interval == wifi_guard_interval_1600)
11413 strcpy(GI, "1.6");
11414 else if (guard_interval == wifi_guard_interval_3200)
11415 strcpy(GI, "3.2");
11416 else if (guard_interval == wifi_guard_interval_auto)
11417 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011418 // Record GI for get GI function
11419 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11420 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011421 if (f == NULL)
11422 return RETURN_ERR;
11423 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011424 fclose(f);
11425 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11426 return RETURN_OK;
11427}
11428
11429INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11430{
11431 char buf[32] = {0};
11432 char cmd[64] = {0};
11433
11434 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11435
11436 if (guard_interval == NULL)
11437 return RETURN_ERR;
11438
developer7c4cd202023-03-01 10:56:29 +080011439 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer454b9462022-09-13 15:29:16 +080011440 _syscmd(cmd, buf, sizeof(buf));
11441
11442 if (strncmp(buf, "0.4", 3) == 0)
11443 *guard_interval = wifi_guard_interval_400;
11444 else if (strncmp(buf, "0.8", 3) == 0)
11445 *guard_interval = wifi_guard_interval_800;
11446 else if (strncmp(buf, "1.6", 3) == 0)
11447 *guard_interval = wifi_guard_interval_1600;
11448 else if (strncmp(buf, "3.2", 3) == 0)
11449 *guard_interval = wifi_guard_interval_3200;
11450 else
11451 *guard_interval = wifi_guard_interval_auto;
11452
11453 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11454 return RETURN_OK;
11455}
11456
developer3cc61d12022-09-13 16:36:05 +080011457INT wifi_setBSSColor(INT radio_index, UCHAR color)
11458{
11459 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11460 struct params params = {0};
11461 char config_file[128] = {0};
11462 char bss_color[4] ={0};
developer2acb9632023-03-14 14:58:31 +080011463 UCHAR *color_list;
11464 int color_num = 0;
11465 int maxNumberColors = 64;
11466 BOOL color_is_aval = FALSE;
11467
11468 color_list = calloc(maxNumberColors, sizeof(UCHAR));
11469 if (wifi_getAvailableBSSColor(radio_index, maxNumberColors, color_list, &color_num) != RETURN_OK)
11470 return RETURN_ERR;
11471
11472 if (color > 63)
11473 return RETURN_ERR;
11474
11475 for (int i = 0; i < color_num; i++) {
11476 if (color_list[i] == color) {
11477 color_is_aval = TRUE;
11478 break;
11479 }
11480 }
11481 if (color_is_aval == FALSE) {
11482 fprintf(stderr, "%s: color %hhu is not avaliable.\n", __func__, color);
11483 return RETURN_ERR;
11484 }
developer3cc61d12022-09-13 16:36:05 +080011485
11486 params.name = "he_bss_color";
11487 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11488 params.value = bss_color;
developer2acb9632023-03-14 14:58:31 +080011489 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer3cc61d12022-09-13 16:36:05 +080011490 wifi_hostapdWrite(config_file, &params, 1);
11491 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer2acb9632023-03-14 14:58:31 +080011492 wifi_reloadAp(radio_index);
11493
developer3cc61d12022-09-13 16:36:05 +080011494 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11495 return RETURN_OK;
11496}
11497
11498INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11499{
developer3cc61d12022-09-13 16:36:05 +080011500 char buf[64] = {0};
developer2acb9632023-03-14 14:58:31 +080011501 char cmd[128] = {0};
11502 char interface_name[16] = {0};
developer3cc61d12022-09-13 16:36:05 +080011503
developer3cc61d12022-09-13 16:36:05 +080011504 if (NULL == color)
11505 return RETURN_ERR;
11506
developer2acb9632023-03-14 14:58:31 +080011507 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11508 return RETURN_ERR;
developer3cc61d12022-09-13 16:36:05 +080011509
developer2acb9632023-03-14 14:58:31 +080011510 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_bss_color | cut -d '=' -f2", interface_name);
11511 _syscmd(cmd, buf, sizeof(buf));
11512 *color = (UCHAR)strtoul(buf, NULL, 10);
developer3cc61d12022-09-13 16:36:05 +080011513
developer2acb9632023-03-14 14:58:31 +080011514 return RETURN_OK;
11515}
11516
11517INT wifi_getAvailableBSSColor(INT radio_index, INT maxNumberColors, UCHAR* colorList, INT *numColorReturned)
11518{
11519 char buf[64] = {0};
11520 char cmd[128] = {0};
11521 char interface_name[16] = {0};
11522 unsigned long long color_bitmap = 0;
developer3cc61d12022-09-13 16:36:05 +080011523
developer2acb9632023-03-14 14:58:31 +080011524 if (NULL == colorList || NULL == numColorReturned)
11525 return RETURN_ERR;
11526
11527 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
11528 return RETURN_ERR;
11529
11530 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_color_bmp | head -n 1 | cut -d '=' -f2", interface_name);
11531 _syscmd(cmd, buf, sizeof(buf));
11532 color_bitmap = strtoull(buf, NULL, 16);
11533
11534 *numColorReturned = 0;
11535 for (int i = 0; i < maxNumberColors; i++) {
11536 if (color_bitmap & 1) {
11537 colorList[*numColorReturned] = i;
11538 (*numColorReturned) += 1;
11539 }
11540 color_bitmap >>= 1;
11541 }
developer3cc61d12022-09-13 16:36:05 +080011542 return RETURN_OK;
11543}
11544
developer06a01d92022-09-07 16:32:39 +080011545/* multi-psk support */
11546INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11547{
11548 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011549 char interface_name[16] = {0};
11550
developerac6f1142022-12-20 19:26:35 +080011551 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011552 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011553
developerd946fd62022-12-08 18:03:28 +080011554 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11555 interface_name,
developer06a01d92022-09-07 16:32:39 +080011556 mac[0],
11557 mac[1],
11558 mac[2],
11559 mac[3],
11560 mac[4],
11561 mac[5]
11562 );
11563 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11564 _syscmd(cmd, key->wifi_keyId, 64);
11565
11566
11567 return RETURN_OK;
11568}
11569
11570INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11571{
developerd946fd62022-12-08 18:03:28 +080011572 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011573 FILE *fd = NULL;
11574 char fname[100];
11575 char cmd[128] = {0};
11576 char out[64] = {0};
11577 wifi_key_multi_psk_t * key = NULL;
11578 if(keysNumber < 0)
11579 return RETURN_ERR;
11580
developer431128d2022-12-16 15:30:41 +080011581 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011582 fd = fopen(fname, "w");
11583 if (!fd) {
11584 return RETURN_ERR;
11585 }
11586 key= (wifi_key_multi_psk_t *) keys;
11587 for(int i=0; i<keysNumber; ++i, key++) {
11588 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11589 }
11590 fclose(fd);
11591
11592 //reload file
developerac6f1142022-12-20 19:26:35 +080011593 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011594 return RETURN_ERR;
11595 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011596 _syscmd(cmd, out, 64);
11597 return RETURN_OK;
11598}
11599
11600INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11601{
11602 FILE *fd = NULL;
11603 char fname[100];
11604 char * line = NULL;
11605 char * pos = NULL;
11606 size_t len = 0;
11607 ssize_t read = 0;
11608 INT ret = RETURN_OK;
11609 wifi_key_multi_psk_t *keys_it = NULL;
11610
11611 if (keysNumber < 1) {
11612 return RETURN_ERR;
11613 }
11614
developer431128d2022-12-16 15:30:41 +080011615 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011616 fd = fopen(fname, "r");
11617 if (!fd) {
11618 return RETURN_ERR;
11619 }
11620
11621 if (keys == NULL) {
11622 ret = RETURN_ERR;
11623 goto close;
11624 }
11625
11626 keys_it = keys;
11627 while ((read = getline(&line, &len, fd)) != -1) {
11628 //Strip trailing new line if present
11629 if (read > 0 && line[read-1] == '\n') {
11630 line[read-1] = '\0';
11631 }
11632
11633 if(strcmp(line,"keyid=")) {
11634 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11635 if (!(pos = index(line, ' '))) {
11636 ret = RETURN_ERR;
11637 goto close;
11638 }
11639 pos++;
11640 //Here should be 00:00:00:00:00:00
11641 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11642 printf("Not supported MAC: %s\n", pos);
11643 }
11644 if (!(pos = index(pos, ' '))) {
11645 ret = RETURN_ERR;
11646 goto close;
11647 }
11648 pos++;
11649
11650 //The rest is PSK
11651 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11652 keys_it++;
11653
11654 if(--keysNumber <= 0)
11655 break;
11656 }
11657 }
11658
11659close:
11660 free(line);
11661 fclose(fd);
11662 return ret;
11663}
11664/* end of multi-psk support */
11665
11666INT wifi_setNeighborReports(UINT apIndex,
11667 UINT numNeighborReports,
11668 wifi_NeighborReport_t *neighborReports)
11669{
11670 char cmd[256] = { 0 };
11671 char hex_bssid[13] = { 0 };
11672 char bssid[18] = { 0 };
11673 char nr[256] = { 0 };
11674 char ssid[256];
11675 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011676 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011677 INT ret;
11678
11679 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011680 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
developerac6f1142022-12-20 19:26:35 +080011681 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080011682 return RETURN_ERR;
11683 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 +080011684 system(cmd);
11685
11686 for(unsigned int i = 0; i < numNeighborReports; i++)
11687 {
11688 memset(ssid, 0, sizeof(ssid));
11689 ret = wifi_getSSIDName(apIndex, ssid);
11690 if (ret != RETURN_OK)
11691 return RETURN_ERR;
11692
11693 memset(hex_ssid, 0, sizeof(hex_ssid));
11694 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11695 sprintf(hex_ssid + k,"%02x", ssid[j]);
11696
11697 snprintf(hex_bssid, sizeof(hex_bssid),
11698 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11699 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11700 snprintf(bssid, sizeof(bssid),
11701 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11702 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11703
11704 snprintf(nr, sizeof(nr),
11705 "%s" // bssid
11706 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11707 "%02hhx" // operclass
11708 "%02hhx" // channel
11709 "%02hhx", // phy_mode
11710 hex_bssid,
11711 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11712 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11713 neighborReports[i].opClass,
11714 neighborReports[i].channel,
11715 neighborReports[i].phyTable);
11716
11717 snprintf(cmd, sizeof(cmd),
11718 "hostapd_cli set_neighbor "
11719 "%s " // bssid
11720 "ssid=%s " // ssid
11721 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011722 "-i %s",
11723 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011724
11725 if (WEXITSTATUS(system(cmd)) != 0)
11726 {
11727 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11728 }
11729 }
11730
11731 return RETURN_OK;
11732}
11733
11734INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11735{
11736 return RETURN_OK;
11737}
11738
11739#ifdef _WIFI_HAL_TEST_
11740int main(int argc,char **argv)
11741{
11742 int index;
11743 INT ret=0;
11744 char buf[1024]="";
11745
11746 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11747 if(argc<3)
11748 {
11749 if(argc==2)
11750 {
11751 if(!strcmp(argv[1], "init"))
11752 return wifi_init();
11753 if(!strcmp(argv[1], "reset"))
11754 return wifi_reset();
11755 if(!strcmp(argv[1], "wifi_getHalVersion"))
11756 {
11757 char buffer[64];
11758 if(wifi_getHalVersion(buffer)==RETURN_OK)
11759 printf("Version: %s\n", buffer);
11760 else
11761 printf("Error in wifi_getHalVersion\n");
11762 return RETURN_OK;
11763 }
11764 }
11765 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11766 exit(-1);
11767 }
11768
11769 index = atoi(argv[2]);
11770 if(strstr(argv[1], "wifi_getApName")!=NULL)
11771 {
11772 wifi_getApName(index,buf);
11773 printf("Ap name is %s \n",buf);
11774 return 0;
11775 }
11776 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11777 {
11778 BOOL b = FALSE;
11779 BOOL *output_bool = &b;
11780 wifi_getRadioAutoChannelEnable(index,output_bool);
11781 printf("Channel enabled = %d \n",b);
11782 return 0;
11783 }
11784 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11785 {
11786 wifi_getApWpaEncryptionMode(index,buf);
11787 printf("encryption enabled = %s\n",buf);
11788 return 0;
11789 }
11790 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11791 {
11792 BOOL b = FALSE;
11793 BOOL *output_bool = &b;
11794 wifi_getApSsidAdvertisementEnable(index,output_bool);
11795 printf("advertisment enabled = %d\n",b);
11796 return 0;
11797 }
11798 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11799 {
11800 if(argc <= 3 )
11801 {
11802 printf("Insufficient arguments \n");
11803 exit(-1);
11804 }
11805
11806 char sta[20] = {'\0'};
11807 ULLONG handle= 0;
11808 strcpy(sta,argv[3]);
11809 mac_address_t st;
11810 mac_addr_aton(st,sta);
11811
11812 wifi_associated_dev_tid_stats_t tid_stats;
11813 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11814 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11815 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);
11816 }
11817
11818 if(strstr(argv[1], "getApEnable")!=NULL) {
11819 BOOL enable;
11820 ret=wifi_getApEnable(index, &enable);
11821 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11822 }
11823 else if(strstr(argv[1], "setApEnable")!=NULL) {
11824 BOOL enable = atoi(argv[3]);
11825 ret=wifi_setApEnable(index, enable);
11826 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11827 }
11828 else if(strstr(argv[1], "getApStatus")!=NULL) {
11829 char status[64];
11830 ret=wifi_getApStatus(index, status);
11831 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11832 }
11833 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11834 {
11835 wifi_getSSIDNameStatus(index,buf);
11836 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11837 return 0;
11838 }
11839 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11840 wifi_ssidTrafficStats2_t stats={0};
11841 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11842 printf("%s %d: returns %d\n", argv[1], index, ret);
11843 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11844 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11845 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11846 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11847 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11848 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11849 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11850 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11851 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11852 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11853 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11854 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11855 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11856 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11857 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11858 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11859 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11860 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11861 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11862 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11863 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11864 }
11865 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11866 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11867 UINT array_size=0;
11868 UINT i=0;
11869 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11870 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11871 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11872 printf(" neighbor %d:\n", i);
11873 printf(" ap_SSID =%s\n", pt->ap_SSID);
11874 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11875 printf(" ap_Mode =%s\n", pt->ap_Mode);
11876 printf(" ap_Channel =%d\n", pt->ap_Channel);
11877 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11878 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11879 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11880 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11881 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11882 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11883 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11884 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11885 printf(" ap_Noise =%d\n", pt->ap_Noise);
11886 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11887 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11888 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11889 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11890 }
11891 if(neighbor_ap_array)
11892 free(neighbor_ap_array); //make sure to free the list
11893 }
11894 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11895 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11896 UINT array_size=0;
11897 UINT i=0;
11898 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11899 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11900 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11901 printf(" associated_dev %d:\n", i);
11902 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11903 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11904 printf(" cli_SNR =%d\n", pt->cli_SNR);
11905 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11906 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11907 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11908 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11909 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11910 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11911 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11912 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11913 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11914 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11915 }
11916 if(associated_dev_array)
11917 free(associated_dev_array); //make sure to free the list
11918 }
11919
11920 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11921 {
11922#define MAX_ARRAY_SIZE 64
11923 int i, array_size;
11924 char *p, *ch_str;
11925 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11926
11927 if(argc != 5)
11928 {
11929 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11930 exit(-1);
11931 }
11932 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11933
11934 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11935 {
11936 strtok_r(ch_str, ",", &p);
11937 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11938 }
11939 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11940 if(!array_size)
11941 array_size=1;//Need to print current channel statistics
11942 for(i=0; i<array_size; i++)
11943 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11944 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11945 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11946 input_output_channelStats_array[i].ch_number,\
11947 input_output_channelStats_array[i].ch_noise,\
11948 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11949 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11950 input_output_channelStats_array[i].ch_utilization_busy,\
11951 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11952 input_output_channelStats_array[i].ch_utilization_total);
11953 }
11954
11955 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11956 {
11957 if(argc <= 3 )
11958 {
11959 printf("Insufficient arguments \n");
11960 exit(-1);
11961 }
11962 char mac_addr[20] = {'\0'};
11963 wifi_device_t output_struct;
11964 int dev_index = atoi(argv[3]);
11965
11966 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11967 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11968 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);
11969 }
11970
11971 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11972 {
11973 if (argc <= 3)
11974 {
11975 printf("Insufficient arguments\n");
11976 exit(-1);
11977 }
11978 char args[256];
11979 wifi_NeighborReport_t *neighborReports;
11980
11981 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11982 if (!neighborReports)
11983 {
11984 printf("Failed to allocate memory");
11985 exit(-1);
11986 }
11987
11988 for (int i = 3; i < argc; ++i)
11989 {
11990 char *val;
11991 int j = 0;
11992 memset(args, 0, sizeof(args));
11993 strncpy(args, argv[i], sizeof(args));
11994 val = strtok(args, ";");
11995 while (val != NULL)
11996 {
11997 if (j == 0)
11998 {
11999 mac_addr_aton(neighborReports[i - 3].bssid, val);
12000 } else if (j == 1)
12001 {
12002 neighborReports[i - 3].info = strtol(val, NULL, 16);
12003 } else if (j == 2)
12004 {
12005 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12006 } else if (j == 3)
12007 {
12008 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12009 } else if (j == 4)
12010 {
12011 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12012 } else {
12013 printf("Insufficient arguments]n\n");
12014 exit(-1);
12015 }
12016 val = strtok(NULL, ";");
12017 j++;
12018 }
12019 }
12020
12021 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12022 if (ret != RETURN_OK)
12023 {
12024 printf("wifi_setNeighborReports ret = %d", ret);
12025 exit(-1);
12026 }
12027 }
12028 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12029 {
12030 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12031 printf("%s.\n", buf);
12032 else
12033 printf("Error returned\n");
12034 }
12035 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12036 {
12037 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12038 printf("%s.\n", buf);
12039 else
12040 printf("Error returned\n");
12041 }
12042 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12043 {
12044 if (argc <= 2)
12045 {
12046 printf("Insufficient arguments\n");
12047 exit(-1);
12048 }
12049 char buf[64]= {'\0'};
12050 wifi_getRadioOperatingChannelBandwidth(index,buf);
12051 printf("Current bandwidth is %s \n",buf);
12052 return 0;
12053 }
12054 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12055 {
12056 if (argc <= 5)
12057 {
12058 printf("Insufficient arguments\n");
12059 exit(-1);
12060 }
12061 UINT channel = atoi(argv[3]);
12062 UINT width = atoi(argv[4]);
12063 UINT beacon = atoi(argv[5]);
12064 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12065 printf("Result = %d", ret);
12066 }
12067
12068 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12069 return 0;
12070}
12071
12072#endif
12073
12074#ifdef WIFI_HAL_VERSION_3
12075
developer1e5aa162022-09-13 16:06:24 +080012076INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12077{
12078 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12079 if (bitMap & WIFI_BITRATE_1MBPS)
12080 strcat(BasicRate, "1,");
12081 if (bitMap & WIFI_BITRATE_2MBPS)
12082 strcat(BasicRate, "2,");
12083 if (bitMap & WIFI_BITRATE_5_5MBPS)
12084 strcat(BasicRate, "5.5,");
12085 if (bitMap & WIFI_BITRATE_6MBPS)
12086 strcat(BasicRate, "6,");
12087 if (bitMap & WIFI_BITRATE_9MBPS)
12088 strcat(BasicRate, "9,");
12089 if (bitMap & WIFI_BITRATE_11MBPS)
12090 strcat(BasicRate, "11,");
12091 if (bitMap & WIFI_BITRATE_12MBPS)
12092 strcat(BasicRate, "12,");
12093 if (bitMap & WIFI_BITRATE_18MBPS)
12094 strcat(BasicRate, "18,");
12095 if (bitMap & WIFI_BITRATE_24MBPS)
12096 strcat(BasicRate, "24,");
12097 if (bitMap & WIFI_BITRATE_36MBPS)
12098 strcat(BasicRate, "36,");
12099 if (bitMap & WIFI_BITRATE_48MBPS)
12100 strcat(BasicRate, "48,");
12101 if (bitMap & WIFI_BITRATE_54MBPS)
12102 strcat(BasicRate, "54,");
12103 if (strlen(BasicRate) != 0) // remove last comma
12104 BasicRate[strlen(BasicRate) - 1] = '\0';
12105 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12106 return RETURN_OK;
12107}
12108
12109INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12110{
12111 UINT BitMap = 0;
12112 char *rate;
12113
12114 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12115 rate = strtok(BasicRatesList, ",");
12116 while(rate != NULL)
12117 {
12118 if (strcmp(rate, "1") == 0)
12119 BitMap |= WIFI_BITRATE_1MBPS;
12120 else if (strcmp(rate, "2") == 0)
12121 BitMap |= WIFI_BITRATE_2MBPS;
12122 else if (strcmp(rate, "5.5") == 0)
12123 BitMap |= WIFI_BITRATE_5_5MBPS;
12124 else if (strcmp(rate, "6") == 0)
12125 BitMap |= WIFI_BITRATE_6MBPS;
12126 else if (strcmp(rate, "9") == 0)
12127 BitMap |= WIFI_BITRATE_9MBPS;
12128 else if (strcmp(rate, "11") == 0)
12129 BitMap |= WIFI_BITRATE_11MBPS;
12130 else if (strcmp(rate, "12") == 0)
12131 BitMap |= WIFI_BITRATE_12MBPS;
12132 else if (strcmp(rate, "18") == 0)
12133 BitMap |= WIFI_BITRATE_18MBPS;
12134 else if (strcmp(rate, "24") == 0)
12135 BitMap |= WIFI_BITRATE_24MBPS;
12136 else if (strcmp(rate, "36") == 0)
12137 BitMap |= WIFI_BITRATE_36MBPS;
12138 else if (strcmp(rate, "48") == 0)
12139 BitMap |= WIFI_BITRATE_48MBPS;
12140 else if (strcmp(rate, "54") == 0)
12141 BitMap |= WIFI_BITRATE_54MBPS;
12142 rate = strtok(NULL, ",");
12143 }
12144 *basicRateBitMap = BitMap;
12145 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12146 return RETURN_OK;
12147}
12148
developer7c4cd202023-03-01 10:56:29 +080012149INT setEHT320CentrlChannel(UINT radioIndex, int channel, wifi_channelBandwidth_t bandwidth)
12150{
12151 int center_channel = 0;
12152 char central_channel_str[16] = {0};
12153 char config_file[32] = {0};
12154 struct params param = {0};
12155
12156 center_channel = util_unii_6g_centerfreq("HT320", channel);
12157 if (bandwidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) {
12158 if (channel >= 193)
12159 return RETURN_ERR;
12160 if (channel >= 33) {
12161 if (channel > center_channel)
12162 center_channel += 32;
12163 else
12164 center_channel -= 32;
12165 }
12166 } else if (bandwidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12167 if (channel <= 29)
12168 return RETURN_ERR;
12169 }
12170 snprintf(central_channel_str, sizeof(central_channel_str), "%d", center_channel);
12171 param.name = "eht_oper_centr_freq_seg0_idx";
12172 param.value = central_channel_str;
12173 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12174 wifi_hostapdWrite(config_file, &param, 1);
12175
12176 return RETURN_OK;
12177}
12178
12179INT wifi_setRadioOpclass(INT radioIndex, INT bandwidth)
12180{
12181 int op_class = 0;
12182 char config_file[32] = {0};
12183 char op_class_str[8] = {0};
12184 struct params param = {0};
12185
12186 if (bandwidth == 20)
12187 op_class = 131;
12188 else if (bandwidth == 40)
12189 op_class = 132;
12190 else if (bandwidth == 80)
12191 op_class = 133;
12192 else if (bandwidth == 160)
12193 op_class = 134;
12194 else if (bandwidth == 320)
12195 op_class = 137;
12196 else
12197 return RETURN_ERR;
12198 snprintf(op_class_str, sizeof(op_class_str), "%d", op_class);
12199 param.name = "op_class";
12200 param.value = op_class_str;
12201 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12202 wifi_hostapdWrite(config_file, &param, 1);
12203 return RETURN_OK;
12204}
12205
12206INT wifi_getRadioOpclass(INT radioIndex, UINT *class)
12207{
12208 char config_file[32] = {0};
12209 char buf [16] = {0};
12210
12211 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
12212 if (wifi_hostapdRead(config_file, "op_class", buf, sizeof(buf)) != 0)
12213 return RETURN_ERR; // 6g band should set op_class
12214 *class = (UINT)strtoul(buf, NULL, 10);
12215
12216 return RETURN_OK;
12217}
12218
developer1e5aa162022-09-13 16:06:24 +080012219// 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 +080012220INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12221{
developer1e5aa162022-09-13 16:06:24 +080012222 char buf[128] = {0};
12223 char cmd[128] = {0};
12224 char config_file[64] = {0};
12225 int bandwidth;
developer517a9792022-10-05 19:37:42 +080012226 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080012227 wifi_radio_operationParam_t current_param;
12228
12229 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12230
12231 multiple_set = TRUE;
12232 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12233 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12234 return RETURN_ERR;
12235 }
12236 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12237 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12238 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12239 return RETURN_ERR;
12240 }
12241 }
developer5884e982022-10-06 10:52:50 +080012242
12243 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12244 bandwidth = 20;
12245 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12246 bandwidth = 40;
12247 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12248 bandwidth = 80;
12249 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12250 bandwidth = 160;
developer7c4cd202023-03-01 10:56:29 +080012251 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ)
12252 bandwidth = 320;
developer5884e982022-10-06 10:52:50 +080012253 if (operationParam->autoChannelEnabled){
12254 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12255 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12256 return RETURN_ERR;
12257 }
12258 }else{
developer1e5aa162022-09-13 16:06:24 +080012259 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12260 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12261 return RETURN_ERR;
12262 }
12263 }
developer5884e982022-10-06 10:52:50 +080012264
developer7c4cd202023-03-01 10:56:29 +080012265 // if set EHT 320. We need to overide the central channel config set by wifi_pushRadioChannel2.
12266 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_2MHZ) {
12267 if (setEHT320CentrlChannel(index, operationParam->channel, operationParam->channelWidth) != RETURN_OK) {
12268 fprintf(stderr, "%s: failed to set EHT 320 bandwidth with channel %d and %s setting\n", __func__, operationParam->channel, \
12269 (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_320_1MHZ) ? "EHT320-1" : "EHT320-2");
12270 return RETURN_ERR;
12271 }
12272 }
12273
12274 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12275 if (wifi_setRadioOpclass(index, bandwidth) != RETURN_OK) {
12276 fprintf(stderr, "%s: wifi_setRadioOpclass return error.\n", __func__);
12277 return RETURN_ERR;
12278 }
12279 }
12280
developer1e5aa162022-09-13 16:06:24 +080012281 if (current_param.variant != operationParam->variant) {
12282 // Two different definition bit map, so need to check every bit.
12283 if (operationParam->variant & WIFI_80211_VARIANT_A)
12284 set_mode |= WIFI_MODE_A;
12285 if (operationParam->variant & WIFI_80211_VARIANT_B)
12286 set_mode |= WIFI_MODE_B;
12287 if (operationParam->variant & WIFI_80211_VARIANT_G)
12288 set_mode |= WIFI_MODE_G;
12289 if (operationParam->variant & WIFI_80211_VARIANT_N)
12290 set_mode |= WIFI_MODE_N;
12291 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12292 set_mode |= WIFI_MODE_AC;
12293 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12294 set_mode |= WIFI_MODE_AX;
developer7c4cd202023-03-01 10:56:29 +080012295 if (operationParam->variant & WIFI_80211_VARIANT_BE)
12296 set_mode |= WIFI_MODE_BE;
developer1e5aa162022-09-13 16:06:24 +080012297 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12298 memset(buf, 0, sizeof(buf));
12299 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12300 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12301 return RETURN_ERR;
12302 }
12303 }
12304 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12305 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12306 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12307 return RETURN_ERR;
12308 }
12309 }
12310 if (current_param.beaconInterval != operationParam->beaconInterval) {
12311 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12312 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12313 return RETURN_ERR;
12314 }
12315 }
12316 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12317 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12318 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12319 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12320 return RETURN_ERR;
12321 }
12322 }
12323 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12324 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12325 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12326 return RETURN_ERR;
12327 }
12328 }
12329 if (current_param.guardInterval != operationParam->guardInterval) {
12330 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12331 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12332 return RETURN_ERR;
12333 }
12334 }
12335 if (current_param.transmitPower != operationParam->transmitPower) {
12336 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12337 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12338 return RETURN_ERR;
12339 }
12340 }
12341 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12342 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12343 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12344 return RETURN_ERR;
12345 }
12346 }
12347 if (current_param.obssCoex != operationParam->obssCoex) {
12348 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12349 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12350 return RETURN_ERR;
12351 }
12352 }
12353 if (current_param.stbcEnable != operationParam->stbcEnable) {
12354 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12355 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12356 return RETURN_ERR;
12357 }
12358 }
12359 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12360 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12361 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12362 return RETURN_ERR;
12363 }
12364 }
12365
12366 // if enable is true, then restart the radio
12367 wifi_setRadioEnable(index, FALSE);
12368 if (operationParam->enable == TRUE)
12369 wifi_setRadioEnable(index, TRUE);
12370 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12371
developer06a01d92022-09-07 16:32:39 +080012372 return RETURN_OK;
12373}
12374
12375INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12376{
developer1e5aa162022-09-13 16:06:24 +080012377 char band[64] = {0};
12378 char buf[256] = {0};
12379 char config_file[64] = {0};
12380 char cmd[128] = {0};
12381 int ret = RETURN_ERR;
12382 int mode = 0;
12383 ULONG channel = 0;
12384 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080012385
12386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12387 printf("Entering %s index = %d\n", __func__, (int)index);
12388
developer1e5aa162022-09-13 16:06:24 +080012389 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12390 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12391 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012392 {
developer1e5aa162022-09-13 16:06:24 +080012393 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012394 return RETURN_ERR;
12395 }
12396 operationParam->enable = enabled;
12397
12398 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080012399 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012400 {
developer1e5aa162022-09-13 16:06:24 +080012401 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012402 return RETURN_ERR;
12403 }
12404
12405 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080012406 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080012407 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080012408 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080012409 else if (!strcmp(band, "6GHz"))
12410 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012411 else
12412 {
developer1e5aa162022-09-13 16:06:24 +080012413 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080012414 band);
12415 }
12416
developer1e5aa162022-09-13 16:06:24 +080012417 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12418 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12419 operationParam->channel = 0;
12420 operationParam->autoChannelEnabled = TRUE;
12421 } else {
12422 operationParam->channel = strtol(buf, NULL, 10);
12423 operationParam->autoChannelEnabled = FALSE;
12424 }
12425
developer06a01d92022-09-07 16:32:39 +080012426 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080012427 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12428 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12429 return RETURN_ERR;
12430 }
developer06a01d92022-09-07 16:32:39 +080012431 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12432 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12433 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080012434 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
developer7c4cd202023-03-01 10:56:29 +080012435 else if (!strcmp(buf, "320-1MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_1MHZ;
12436 else if (!strcmp(buf, "320-2MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_320_2MHZ;
developer06a01d92022-09-07 16:32:39 +080012437 else
12438 {
developer1e5aa162022-09-13 16:06:24 +080012439 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12440 return false;
developer06a01d92022-09-07 16:32:39 +080012441 }
12442
developer7c4cd202023-03-01 10:56:29 +080012443 if (operationParam->band == WIFI_FREQUENCY_6_BAND) {
12444 if (wifi_getRadioOpclass(index, &operationParam->op_class) != RETURN_OK) {
12445 fprintf(stderr, "%s: op_class is not set.\n", __func__);
12446 return RETURN_ERR;
12447 }
12448 }
12449
developer1e5aa162022-09-13 16:06:24 +080012450 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12451 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12452 return RETURN_ERR;
12453 }
12454 // Two different definition bit map, so need to check every bit.
12455 if (mode & WIFI_MODE_A)
12456 operationParam->variant |= WIFI_80211_VARIANT_A;
12457 if (mode & WIFI_MODE_B)
12458 operationParam->variant |= WIFI_80211_VARIANT_B;
12459 if (mode & WIFI_MODE_G)
12460 operationParam->variant |= WIFI_80211_VARIANT_G;
12461 if (mode & WIFI_MODE_N)
12462 operationParam->variant |= WIFI_80211_VARIANT_N;
12463 if (mode & WIFI_MODE_AC)
12464 operationParam->variant |= WIFI_80211_VARIANT_AC;
12465 if (mode & WIFI_MODE_AX)
12466 operationParam->variant |= WIFI_80211_VARIANT_AX;
developer7c4cd202023-03-01 10:56:29 +080012467 if (mode & WIFI_MODE_BE)
12468 operationParam->variant |= WIFI_80211_VARIANT_BE;
developer1e5aa162022-09-13 16:06:24 +080012469 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12470 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12471 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012472 }
developer1e5aa162022-09-13 16:06:24 +080012473 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12474 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12475 return RETURN_ERR;
12476 }
12477 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12478 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12479 return RETURN_ERR;
12480 }
developer06a01d92022-09-07 16:32:39 +080012481
developer1e5aa162022-09-13 16:06:24 +080012482 memset(buf, 0, sizeof(buf));
12483 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12484 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12485 return RETURN_ERR;
12486 }
12487 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12488
12489 memset(buf, 0, sizeof(buf));
12490 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12491 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12492 return RETURN_ERR;
12493 }
12494 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12495
12496 memset(buf, 0, sizeof(buf));
12497 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12498 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12499
12500 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12501 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12502 return RETURN_ERR;
12503 }
12504 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12505 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12506 return RETURN_ERR;
12507 }
12508
12509 memset(buf, 0, sizeof(buf));
12510 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12511 if (strcmp(buf, "-1") == 0) {
12512 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12513 operationParam->ctsProtection = FALSE;
12514 } else {
12515 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12516 operationParam->ctsProtection = TRUE;
12517 }
12518
12519 memset(buf, 0, sizeof(buf));
12520 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12521 if (strcmp(buf, "0") == 0)
12522 operationParam->obssCoex = FALSE;
12523 else
12524 operationParam->obssCoex = TRUE;
12525
12526 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12527 _syscmd(cmd, buf, sizeof(buf));
12528 if (strlen(buf) != 0)
12529 operationParam->stbcEnable = TRUE;
12530 else
12531 operationParam->stbcEnable = FALSE;
12532
12533 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12534 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12535 return RETURN_ERR;
12536 }
12537
12538 // Below value is hardcoded
12539
12540 operationParam->numSecondaryChannels = 0;
12541 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12542 operationParam->channelSecondary[i] = 0;
12543 }
12544 operationParam->csa_beacon_count = 15;
12545 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012546
12547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12548 return RETURN_OK;
12549}
12550
12551static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12552{
developerc086fb72022-10-04 10:18:22 +080012553 int max_radio_num = 0;
12554
12555 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012556 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012557 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12558 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012559 }
12560
developerc086fb72022-10-04 10:18:22 +080012561 return (arrayIndex * max_radio_num) + radioIndex;
12562}
developer06a01d92022-09-07 16:32:39 +080012563
developerc086fb72022-10-04 10:18:22 +080012564wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12565 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12566 return WIFI_BITRATE_1MBPS;
12567 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12568 return WIFI_BITRATE_2MBPS;
12569 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12570 return WIFI_BITRATE_5_5MBPS;
12571 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12572 return WIFI_BITRATE_6MBPS;
12573 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12574 return WIFI_BITRATE_9MBPS;
12575 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12576 return WIFI_BITRATE_11MBPS;
12577 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12578 return WIFI_BITRATE_12MBPS;
12579 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12580 return WIFI_BITRATE_18MBPS;
12581 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12582 return WIFI_BITRATE_24MBPS;
12583 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12584 return WIFI_BITRATE_36MBPS;
12585 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12586 return WIFI_BITRATE_48MBPS;
12587 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12588 return WIFI_BITRATE_54MBPS;
12589 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012590}
12591
developer1d57d002022-10-12 18:03:15 +080012592INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12593{
12594 if (beacon == WIFI_BITRATE_1MBPS)
12595 strcpy(beacon_str, "1Mbps");
12596 else if (beacon == WIFI_BITRATE_2MBPS)
12597 strcpy(beacon_str, "2Mbps");
12598 else if (beacon == WIFI_BITRATE_5_5MBPS)
12599 strcpy(beacon_str, "5.5Mbps");
12600 else if (beacon == WIFI_BITRATE_6MBPS)
12601 strcpy(beacon_str, "6Mbps");
12602 else if (beacon == WIFI_BITRATE_9MBPS)
12603 strcpy(beacon_str, "9Mbps");
12604 else if (beacon == WIFI_BITRATE_11MBPS)
12605 strcpy(beacon_str, "11Mbps");
12606 else if (beacon == WIFI_BITRATE_12MBPS)
12607 strcpy(beacon_str, "12Mbps");
12608 else if (beacon == WIFI_BITRATE_18MBPS)
12609 strcpy(beacon_str, "18Mbps");
12610 else if (beacon == WIFI_BITRATE_24MBPS)
12611 strcpy(beacon_str, "24Mbps");
12612 else if (beacon == WIFI_BITRATE_36MBPS)
12613 strcpy(beacon_str, "36Mbps");
12614 else if (beacon == WIFI_BITRATE_48MBPS)
12615 strcpy(beacon_str, "48Mbps");
12616 else if (beacon == WIFI_BITRATE_54MBPS)
12617 strcpy(beacon_str, "54Mbps");
12618 return RETURN_OK;
12619}
12620
developer06a01d92022-09-07 16:32:39 +080012621INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12622{
developerc086fb72022-10-04 10:18:22 +080012623 INT mode = 0;
12624 INT ret = -1;
12625 INT output = 0;
12626 int i = 0;
12627 int vap_index = 0;
12628 BOOL enabled = FALSE;
12629 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012630 wifi_vap_security_t security = {0};
developera77d84b2023-02-22 16:10:50 +080012631
developer06a01d92022-09-07 16:32:39 +080012632
12633 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12634 printf("Entering %s index = %d\n", __func__, (int)index);
12635
developera77d84b2023-02-22 16:10:50 +080012636 for (i = 0; i < MAX_NUM_VAP_PER_RADIO; i++)
developer06a01d92022-09-07 16:32:39 +080012637 {
developerc086fb72022-10-04 10:18:22 +080012638 map->vap_array[i].radio_index = index;
12639
developer06a01d92022-09-07 16:32:39 +080012640 vap_index = array_index_to_vap_index(index, i);
12641 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012642 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012643
developerc086fb72022-10-04 10:18:22 +080012644 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012645
12646 map->vap_array[i].vap_index = vap_index;
12647
12648 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012649 ret = wifi_getApName(vap_index, buf);
12650 if (ret != RETURN_OK) {
developera77d84b2023-02-22 16:10:50 +080012651 printf("%s: wifi_getApName return error. vap_index=%d\n", __func__, vap_index);
12652
developerc086fb72022-10-04 10:18:22 +080012653 return RETURN_ERR;
12654 }
12655 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12656
12657 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012658 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012659 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012660 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012661 return RETURN_ERR;
12662 }
12663 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 +080012664
12665 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012666 if (ret != RETURN_OK) {
12667 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012668 return RETURN_ERR;
12669 }
12670 map->vap_array[i].u.bss_info.enabled = enabled;
12671
developerc086fb72022-10-04 10:18:22 +080012672 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12673 if (ret != RETURN_OK) {
12674 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12675 return RETURN_ERR;
12676 }
developer06a01d92022-09-07 16:32:39 +080012677 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012678
12679 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12680 if (ret != RETURN_OK) {
12681 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12682 return RETURN_ERR;
12683 }
12684 map->vap_array[i].u.bss_info.isolation = enabled;
12685
12686 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12687 if (ret != RETURN_OK) {
12688 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12689 return RETURN_ERR;
12690 }
12691 map->vap_array[i].u.bss_info.bssMaxSta = output;
12692
12693 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12694 if (ret != RETURN_OK) {
12695 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12696 return RETURN_ERR;
12697 }
12698 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012699
developerc086fb72022-10-04 10:18:22 +080012700 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12701 if (ret != RETURN_OK) {
12702 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12703 return RETURN_ERR;
12704 }
12705 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012706
developerc086fb72022-10-04 10:18:22 +080012707 ret = wifi_getApSecurity(vap_index, &security);
12708 if (ret != RETURN_OK) {
12709 printf("%s: wifi_getApSecurity return error\n", __func__);
12710 return RETURN_ERR;
12711 }
12712 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012713
developerc086fb72022-10-04 10:18:22 +080012714 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12715 if (ret != RETURN_OK) {
12716 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12717 return RETURN_ERR;
12718 }
12719 if (mode == 0)
12720 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12721 else
12722 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12723 if (mode == 1)
12724 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12725 else if (mode == 2)
12726 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012727
developerc086fb72022-10-04 10:18:22 +080012728 ret = wifi_getApWmmEnable(vap_index, &enabled);
12729 if (ret != RETURN_OK) {
12730 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12731 return RETURN_ERR;
12732 }
12733 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012734
developerc086fb72022-10-04 10:18:22 +080012735 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12736 if (ret != RETURN_OK) {
12737 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012738 return RETURN_ERR;
12739 }
developerc086fb72022-10-04 10:18:22 +080012740 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012741
12742 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012743 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012744 if (ret != RETURN_OK) {
12745 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12746 return RETURN_ERR;
12747 }
12748 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012749
developerc086fb72022-10-04 10:18:22 +080012750 memset(buf, 0, sizeof(buf));
12751 ret = wifi_getBaseBSSID(vap_index, buf);
12752 if (ret != RETURN_OK) {
12753 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12754 return RETURN_ERR;
12755 }
12756 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12757 &map->vap_array[i].u.bss_info.bssid[0],
12758 &map->vap_array[i].u.bss_info.bssid[1],
12759 &map->vap_array[i].u.bss_info.bssid[2],
12760 &map->vap_array[i].u.bss_info.bssid[3],
12761 &map->vap_array[i].u.bss_info.bssid[4],
12762 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012763 // 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]);
12764
12765 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12766 if (ret != RETURN_OK) {
12767 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12768 return RETURN_ERR;
12769 }
12770 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developera77d84b2023-02-22 16:10:50 +080012771 map->num_vaps++;
developerc086fb72022-10-04 10:18:22 +080012772 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012773 }
12774 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12775 return RETURN_OK;
12776}
12777
developer431128d2022-12-16 15:30:41 +080012778void checkVapStatus(int apIndex, bool *enable)
12779{
12780 char if_name[16] = {0};
12781 char cmd[128] = {0};
12782 char buf[128] = {0};
12783
12784 *enable = FALSE;
developerac6f1142022-12-20 19:26:35 +080012785 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
developer431128d2022-12-16 15:30:41 +080012786 return;
12787
12788 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12789 _syscmd(cmd, buf, sizeof(buf));
12790 if (strlen(buf) > 0)
12791 *enable = TRUE;
12792 return;
12793}
12794
developerd946fd62022-12-08 18:03:28 +080012795static int prepareInterface(UINT apIndex, char *new_interface)
12796{
12797 char cur_interface[16] = {0};
12798 char config_file[128] = {0};
12799 char cmd[128] = {0};
12800 char buf[16] = {0};
12801 int max_radio_num = 0;
12802 int radioIndex = -1;
12803 int phyIndex = -1;
12804
12805 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12806 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12807
12808 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12809 wifi_getMaxRadioNumber(&max_radio_num);
12810 radioIndex = apIndex % max_radio_num;
12811 phyIndex = radio_index_to_phy(radioIndex);
12812 // disable and del old interface, then add new interface
12813 wifi_setApEnable(apIndex, FALSE);
developer2f18b9f2023-03-17 19:32:57 +080012814 if (!(apIndex/max_radio_num)) {
12815 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
12816 _syscmd(cmd, buf, sizeof(buf));
12817 }
developerd946fd62022-12-08 18:03:28 +080012818 }
developer431128d2022-12-16 15:30:41 +080012819 // update the vap status file
12820 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12821 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012822 return RETURN_OK;
12823}
12824
developer06a01d92022-09-07 16:32:39 +080012825INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12826{
developerd946fd62022-12-08 18:03:28 +080012827 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012828 unsigned int i;
12829 wifi_vap_info_t *vap_info = NULL;
12830 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012831 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012832 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012833 char buf[256] = {0};
12834 char cmd[128] = {0};
12835 char config_file[64] = {0};
12836 char bssid[32] = {0};
12837 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012838 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012839
12840 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12841 printf("Entering %s index = %d\n", __func__, (int)index);
12842 for (i = 0; i < map->num_vaps; i++)
12843 {
developer1d57d002022-10-12 18:03:15 +080012844 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012845 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012846
12847 // Check vap status file to enable multiple ap if the system boot.
12848 checkVapStatus(vap_info->vap_index, &enable);
12849 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012850 continue;
developer06a01d92022-09-07 16:32:39 +080012851
developer1d57d002022-10-12 18:03:15 +080012852 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12853
developer431128d2022-12-16 15:30:41 +080012854 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12855 enable = FALSE;
12856
12857 // multi-ap first up need to copy current radio config
12858 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012859 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12860 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012861 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12862 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12863 } else {
12864 // Check whether the interface name is valid or this ap change it.
12865 int apIndex = -1;
12866 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12867 if (apIndex != -1 && apIndex != vap_info->vap_index)
12868 continue;
12869 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012870 }
developer06a01d92022-09-07 16:32:39 +080012871
developer1d57d002022-10-12 18:03:15 +080012872 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012873 params[0].name = "interface";
12874 params[0].value = vap_info->vap_name;
12875 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12876 params[1].name = "bssid";
12877 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012878 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012879 params[2].name = "wpa_psk_file";
12880 params[2].value = psk_file;
12881
12882 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12883 wifi_hostapdWrite(config_file, params, 3);
12884
12885 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12886 _syscmd(cmd, buf, sizeof(buf));
12887
12888 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12889 if (ret != RETURN_OK) {
12890 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12891 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012892 }
developer1d57d002022-10-12 18:03:15 +080012893
12894 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12895 if (ret != RETURN_OK) {
12896 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12897 return RETURN_ERR;
12898 }
12899
12900 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12901 if (ret != RETURN_OK) {
12902 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12903 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012904 }
12905
developer1d57d002022-10-12 18:03:15 +080012906 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12907 if (ret != RETURN_OK) {
12908 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12909 return RETURN_ERR;
12910 }
developer06a01d92022-09-07 16:32:39 +080012911
developer1d57d002022-10-12 18:03:15 +080012912 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12913 if (ret != RETURN_OK) {
12914 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12915 return RETURN_ERR;
12916 }
developer06a01d92022-09-07 16:32:39 +080012917
developer1d57d002022-10-12 18:03:15 +080012918 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12919 if (ret != RETURN_OK) {
12920 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12921 return RETURN_ERR;
12922 }
12923
developer804c64f2022-10-19 13:54:40 +080012924 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012925 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012926 }else {
12927 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012928 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012929 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12930 _syscmd(cmd, buf, sizeof(buf));
12931 }else{
developer1d57d002022-10-12 18:03:15 +080012932 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012933 }
developer1d57d002022-10-12 18:03:15 +080012934 }
12935
12936 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12937 if (ret != RETURN_OK) {
12938 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12939 return RETURN_ERR;
12940 }
12941
12942 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12943 if (ret != RETURN_OK) {
12944 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12945 return RETURN_ERR;
12946 }
12947
12948 memset(buf, 0, sizeof(buf));
12949 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12950 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12951 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12952 if (ret != RETURN_OK) {
12953 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12954 return RETURN_ERR;
12955 }
12956
12957 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12958 if (ret != RETURN_OK) {
12959 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12960 return RETURN_ERR;
12961 }
12962
developer1d57d002022-10-12 18:03:15 +080012963 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12964 if (ret != RETURN_OK) {
12965 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12966 return RETURN_ERR;
12967 }
12968
12969 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12970 if (ret != RETURN_OK) {
12971 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12972 return RETURN_ERR;
12973 }
developer06a01d92022-09-07 16:32:39 +080012974
developer2f995fb2023-02-24 10:40:44 +080012975 wifi_setApEnable(vap_info->vap_index, FALSE);
12976 wifi_setApEnable(vap_info->vap_index, TRUE);
12977 multiple_set = FALSE;
12978
12979 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12980
developer1d57d002022-10-12 18:03:15 +080012981 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012982 }
12983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12984 return RETURN_OK;
12985}
12986
12987int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12988{
12989 char *token, *next;
12990 const char s[2] = ",";
12991 int count =0;
12992
12993 /* get the first token */
12994 token = strtok_r(pchannels, s, &next);
12995
12996 /* walk through other tokens */
12997 while( token != NULL && count < MAX_CHANNELS) {
12998 chlistptr->channels_list[count++] = atoi(token);
12999 token = strtok_r(NULL, s, &next);
13000 }
13001
13002 return count;
13003}
13004
13005static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13006{
13007 INT status;
13008 wifi_channels_list_t *chlistp;
13009 CHAR output_string[64];
13010 CHAR pchannels[128];
developer7930d352022-12-21 17:55:42 +080013011 CHAR interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +080013012 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080013013
13014 if(rcap == NULL)
13015 {
13016 return RETURN_ERR;
13017 }
13018
13019 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080013020 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080013021
developer1e5aa162022-09-13 16:06:24 +080013022 if (band == band_2_4)
13023 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13024 else if (band == band_5)
13025 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13026 else if (band == band_6)
13027 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080013028
13029 chlistp = &(rcap->channel_list[0]);
13030 memset(pchannels, 0, sizeof(pchannels));
13031
13032 /* possible number of radio channels */
13033 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13034 {
13035 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13036 }
13037 /* Number of channels and list*/
13038 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13039
13040 /* autoChannelSupported */
13041 /* always ON with wifi_getRadioAutoChannelSupported */
13042 rcap->autoChannelSupported = TRUE;
13043
13044 /* DCSSupported */
13045 /* always ON with wifi_getRadioDCSSupported */
13046 rcap->DCSSupported = TRUE;
13047
13048 /* zeroDFSSupported - TBD */
13049 rcap->zeroDFSSupported = FALSE;
13050
13051 /* Supported Country List*/
13052 memset(output_string, 0, sizeof(output_string));
13053 status = wifi_getRadioCountryCode(radioIndex, output_string);
13054 if( status != 0 ) {
13055 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13056 return RETURN_ERR;
13057 } else {
13058 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13059 }
13060 if(!strcmp(output_string,"US")){
13061 rcap->countrySupported[0] = wifi_countrycode_US;
13062 rcap->countrySupported[1] = wifi_countrycode_CA;
13063 } else if (!strcmp(output_string,"CA")) {
13064 rcap->countrySupported[0] = wifi_countrycode_CA;
13065 rcap->countrySupported[1] = wifi_countrycode_US;
13066 } else {
13067 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13068 }
13069
13070 rcap->numcountrySupported = 2;
13071
13072 /* csi */
13073 rcap->csi.maxDevices = 8;
13074 rcap->csi.soudingFrameSupported = TRUE;
13075
developer7930d352022-12-21 17:55:42 +080013076 wifi_GetInterfaceName(radioIndex, interface_name);
13077 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
developer06a01d92022-09-07 16:32:39 +080013078
13079 /* channelWidth - all supported bandwidths */
13080 int i=0;
13081 rcap->channelWidth[i] = 0;
developer7c4cd202023-03-01 10:56:29 +080013082
13083 /* mode - all supported variants */
13084 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13085 wifi_getRadioSupportedStandards(radioIndex, output_string);
13086
developer06a01d92022-09-07 16:32:39 +080013087 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13088 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13089 WIFI_CHANNELBANDWIDTH_40MHZ);
developer7c4cd202023-03-01 10:56:29 +080013090 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G);
developer06a01d92022-09-07 16:32:39 +080013091
developer7c4cd202023-03-01 10:56:29 +080013092 if (strstr(output_string, "n") != NULL)
13093 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13094 if (strstr(output_string, "ax") != NULL)
13095 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13096 if (strstr(output_string, "be") != NULL)
13097 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13098 } else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND) {
developer06a01d92022-09-07 16:32:39 +080013099 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13100 WIFI_CHANNELBANDWIDTH_40MHZ |
13101 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer7c4cd202023-03-01 10:56:29 +080013102 rcap->mode[i] = ( WIFI_80211_VARIANT_A);
developer06a01d92022-09-07 16:32:39 +080013103
developer7c4cd202023-03-01 10:56:29 +080013104 if (strstr(output_string, "n") != NULL)
13105 rcap->mode[i] |= WIFI_80211_VARIANT_N;
13106 if (strstr(output_string, "ac") != NULL)
13107 rcap->mode[i] |= WIFI_80211_VARIANT_AC;
13108 if (strstr(output_string, "ax") != NULL)
13109 rcap->mode[i] |= WIFI_80211_VARIANT_AX;
13110 if (strstr(output_string, "be") != NULL)
13111 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13112 } else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13113 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13114 WIFI_CHANNELBANDWIDTH_40MHZ |
13115 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
developer1e5aa162022-09-13 16:06:24 +080013116 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer7c4cd202023-03-01 10:56:29 +080013117
13118 if (strstr(output_string, "be") != NULL) {
13119 rcap->mode[i] |= WIFI_80211_VARIANT_BE;
13120 rcap->channelWidth[i] |= WIFI_CHANNELBANDWIDTH_320_1MHZ | WIFI_CHANNELBANDWIDTH_320_2MHZ;
13121 }
developer06a01d92022-09-07 16:32:39 +080013122 }
developer7c4cd202023-03-01 10:56:29 +080013123
developer06a01d92022-09-07 16:32:39 +080013124 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13125 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13126
13127 /* supportedBitRate - all supported bitrates */
13128 rcap->supportedBitRate[i] = 0;
13129 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13130 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13131 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13132 }
developer1e5aa162022-09-13 16:06:24 +080013133 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080013134 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13135 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13136 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13137 }
13138
13139
13140 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13141 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13142 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13143 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13144 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13145 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13146 rcap->cipherSupported = 0;
13147 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13148 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13149
13150 return RETURN_OK;
13151}
13152
13153INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13154{
developer30423732022-12-01 16:17:49 +080013155 INT status = 0, radioIndex = 0;
13156 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080013157 int iter = 0;
developer30423732022-12-01 16:17:49 +080013158 unsigned int j = 0;
developer7930d352022-12-21 17:55:42 +080013159 int max_num_radios;
developer30423732022-12-01 16:17:49 +080013160 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080013161
13162 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13163
13164 memset(cap, 0, sizeof(wifi_hal_capability_t));
13165
13166 /* version */
13167 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13168 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13169
13170 /* number of radios platform property */
developer7930d352022-12-21 17:55:42 +080013171 wifi_getMaxRadioNumber(&max_num_radios);
13172 cap->wifi_prop.numRadios = max_num_radios;
developer06a01d92022-09-07 16:32:39 +080013173
13174 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13175 {
13176 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13177 if (status != 0) {
13178 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13179 return RETURN_ERR;
13180 }
13181
13182 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13183 {
developer804c64f2022-10-19 13:54:40 +080013184 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080013185 {
13186 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13187 return RETURN_ERR;
13188 }
13189 iface_info = &cap->wifi_prop.interface_map[iter];
13190 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13191 iface_info->rdk_radio_index = radioIndex;
13192 memset(output, 0, sizeof(output));
13193 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13194 {
13195 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13196 }
13197 // TODO: bridge name
13198 // TODO: vlan id
13199 // TODO: primary
13200 iface_info->index = array_index_to_vap_index(radioIndex, j);
13201 memset(output, 0, sizeof(output));
developer7930d352022-12-21 17:55:42 +080013202 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080013203 {
13204 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13205 }
13206 iter++;
13207 }
13208 }
13209
13210 cap->BandSteeringSupported = FALSE;
13211 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13212 return RETURN_OK;
13213}
13214
developer9df4e652022-10-11 11:27:38 +080013215INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13216{
13217 struct params h_config={0};
13218 char config_file[64] = {0};
13219
13220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13221
13222 h_config.name = "okc";
13223 h_config.value = okc_enable?"1":"0";
13224
13225 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13226 wifi_hostapdWrite(config_file, &h_config, 1);
13227 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13228
13229 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13230 return RETURN_OK;
13231}
13232
13233INT wifi_setSAEMFP(int ap_index, BOOL enable)
13234{
13235 struct params h_config={0};
13236 char config_file[64] = {0};
13237 char buf[128] = {0};
13238
13239 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13240
13241 h_config.name = "sae_require_mfp";
13242 h_config.value = enable?"1":"0";
13243
13244 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13245 wifi_hostapdWrite(config_file, &h_config, 1);
13246 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13247
13248 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13249 return RETURN_OK;
13250}
13251
13252INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13253{
13254 struct params h_config={0};
13255 char config_file[64] = {0};
13256 char buf[128] = {0};
13257
13258 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13259
13260 h_config.name = "sae_pwe";
13261 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13262 h_config.value = buf;
13263
13264 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13265 wifi_hostapdWrite(config_file, &h_config, 1);
13266 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13267
13268 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13269 return RETURN_OK;
13270}
13271
13272INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13273{
13274 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13275 struct params h_config={0};
13276 char config_file[64] = {0};
13277
13278 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13279
13280 h_config.name = "wpa_disable_eapol_key_retries";
13281 h_config.value = disable_EAPOL_retries?"1":"0";
13282
13283 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13284 wifi_hostapdWrite(config_file, &h_config, 1);
13285 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13286
13287 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13288 return RETURN_OK;
13289}
13290
developer06a01d92022-09-07 16:32:39 +080013291INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13292{
developer587c1b62022-09-27 15:58:59 +080013293 char buf[128] = {0};
13294 char config_file[128] = {0};
developer4b102122023-02-15 10:53:03 +080013295 char cmd[128] = {0};
developer587c1b62022-09-27 15:58:59 +080013296 char password[64] = {0};
13297 char mfp[32] = {0};
13298 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080013299 BOOL okc_enable = FALSE;
13300 BOOL sae_MFP = FALSE;
13301 BOOL disable_EAPOL_retries = TRUE;
13302 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080013303 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080013304 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080013305
13306 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13307
13308 multiple_set = TRUE;
13309 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13310 if (security->mode == wifi_security_mode_none) {
13311 strcpy(wpa_mode, "None");
13312 } else if (security->mode == wifi_security_mode_wpa_personal)
13313 strcpy(wpa_mode, "WPA-Personal");
13314 else if (security->mode == wifi_security_mode_wpa2_personal)
13315 strcpy(wpa_mode, "WPA2-Personal");
13316 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13317 strcpy(wpa_mode, "WPA-WPA2-Personal");
13318 else if (security->mode == wifi_security_mode_wpa_enterprise)
13319 strcpy(wpa_mode, "WPA-Enterprise");
13320 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13321 strcpy(wpa_mode, "WPA2-Enterprise");
13322 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13323 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013324 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080013325 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080013326 okc_enable = TRUE;
13327 sae_MFP = TRUE;
13328 sae_pwe = 2;
13329 disable_EAPOL_retries = FALSE;
13330 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080013331 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080013332 okc_enable = TRUE;
13333 sae_MFP = TRUE;
13334 sae_pwe = 2;
13335 disable_EAPOL_retries = FALSE;
13336 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080013337 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080013338 sae_MFP = TRUE;
13339 sae_pwe = 2;
13340 disable_EAPOL_retries = FALSE;
developerae432c62023-04-24 11:07:20 +080013341 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer5c9fee82023-01-13 14:44:16 +080013342 strcpy(wpa_mode, "OWE");
13343 sae_MFP = TRUE;
13344 sae_pwe = 2;
13345 disable_EAPOL_retries = FALSE;
developer9df4e652022-10-11 11:27:38 +080013346 }
13347
13348 band = wifi_index_to_band(ap_index);
13349 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13350 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13351 return RETURN_ERR;
13352 }
developer587c1b62022-09-27 15:58:59 +080013353
13354 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080013355 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080013356 wifi_setSAEMFP(ap_index, sae_MFP);
13357 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080013358 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080013359
developerae432c62023-04-24 11:07:20 +080013360 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer4b102122023-02-15 10:53:03 +080013361 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) {
13362 int key_len = strlen(security->u.key.key);
13363 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
13364 if (key_len == 64) { // set wpa_psk
13365 strncpy(password, security->u.key.key, 64); // 64 characters
13366 password[64] = '\0';
13367 wifi_setApSecurityPreSharedKey(ap_index, password);
13368 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
13369 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
13370 strncpy(password, security->u.key.key, 63);
13371 password[63] = '\0';
13372 wifi_setApSecurityKeyPassphrase(ap_index, password);
13373 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
13374 } else
13375 return RETURN_ERR;
13376 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013377 }
13378 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13379 params.name = "sae_password";
13380 params.value = security->u.key.key;
13381 wifi_hostapdWrite(config_file, &params, 1);
developer4b102122023-02-15 10:53:03 +080013382 } else { // remove sae_password
13383 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
13384 _syscmd(cmd, buf, sizeof(buf));
developer9df4e652022-10-11 11:27:38 +080013385 }
13386 }
developer587c1b62022-09-27 15:58:59 +080013387
13388 if (security->mode != wifi_security_mode_none) {
13389 memset(&params, 0, sizeof(params));
13390 params.name = "wpa_pairwise";
13391 if (security->encr == wifi_encryption_tkip)
13392 params.value = "TKIP";
13393 else if (security->encr == wifi_encryption_aes)
13394 params.value = "CCMP";
13395 else if (security->encr == wifi_encryption_aes_tkip)
13396 params.value = "TKIP CCMP";
13397 wifi_hostapdWrite(config_file, &params, 1);
13398 }
13399
13400 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080013401 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080013402 else if (security->mfp == wifi_mfp_cfg_optional)
13403 strcpy(mfp, "Optional");
13404 else if (security->mfp == wifi_mfp_cfg_required)
13405 strcpy(mfp, "Required");
13406 wifi_setApSecurityMFPConfig(ap_index, mfp);
13407
13408 memset(&params, 0, sizeof(params));
13409 params.name = "transition_disable";
13410 if (security->wpa3_transition_disable == TRUE)
13411 params.value = "0x01";
13412 else
13413 params.value = "0x00";
13414 wifi_hostapdWrite(config_file, &params, 1);
13415
13416 memset(&params, 0, sizeof(params));
13417 params.name = "wpa_group_rekey";
13418 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13419 params.value = buf;
13420 wifi_hostapdWrite(config_file, &params, 1);
13421
13422 memset(&params, 0, sizeof(params));
13423 params.name = "wpa_strict_rekey";
13424 params.value = security->strict_rekey?"1":"0";
13425 wifi_hostapdWrite(config_file, &params, 1);
13426
13427 memset(&params, 0, sizeof(params));
13428 params.name = "wpa_pairwise_update_count";
developer4b102122023-02-15 10:53:03 +080013429 if (security->eapol_key_retries == 0)
13430 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer587c1b62022-09-27 15:58:59 +080013431 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13432 params.value = buf;
13433 wifi_hostapdWrite(config_file, &params, 1);
13434
13435 memset(&params, 0, sizeof(params));
13436 params.name = "disable_pmksa_caching";
13437 params.value = security->disable_pmksa_caching?"1":"0";
13438 wifi_hostapdWrite(config_file, &params, 1);
13439
developer23e71282023-01-18 10:25:19 +080013440 if (multiple_set == FALSE) {
13441 wifi_setApEnable(ap_index, FALSE);
13442 wifi_setApEnable(ap_index, TRUE);
13443 }
developer587c1b62022-09-27 15:58:59 +080013444
13445 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13446
developer06a01d92022-09-07 16:32:39 +080013447 return RETURN_OK;
13448}
13449
13450INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13451{
developer9df4e652022-10-11 11:27:38 +080013452 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080013453 char config_file[128] = {0};
13454 int disable = 0;
developer4b102122023-02-15 10:53:03 +080013455 bool set_sae = FALSE;
developer587c1b62022-09-27 15:58:59 +080013456
13457 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13458 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13459 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13460 security->mode = wifi_security_mode_none;
13461 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080013462 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080013463 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080013464 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013465 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013466 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080013467 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080013468 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013469 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080013470 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013471 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013472 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013473 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080013474 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080013475 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080013476 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080013477 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080013478 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080013479 security->mode = wifi_security_mode_wpa3_enterprise;
developer5c9fee82023-01-13 14:44:16 +080013480 else if (!strcmp(buf, "OWE"))
developerae432c62023-04-24 11:07:20 +080013481 security->mode = wifi_security_mode_enhanced_open;
developer587c1b62022-09-27 15:58:59 +080013482 }
13483
13484 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13485 if (security->mode == wifi_security_mode_none)
13486 security->encr = wifi_encryption_none;
13487 else {
13488 if (strcmp(buf, "TKIP") == 0)
13489 security->encr = wifi_encryption_tkip;
13490 else if (strcmp(buf, "CCMP") == 0)
13491 security->encr = wifi_encryption_aes;
13492 else
13493 security->encr = wifi_encryption_aes_tkip;
13494 }
13495
developer9df4e652022-10-11 11:27:38 +080013496 if (security->mode != wifi_encryption_none) {
13497 memset(buf, 0, sizeof(buf));
13498 // wpa3 can use one or both configs as password, so we check sae_password first.
13499 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developer4b102122023-02-15 10:53:03 +080013500 if (strlen(buf) != 0) {
13501 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
13502 security->u.key.type = wifi_security_key_type_sae;
13503 set_sae = TRUE;
13504 strncpy(security->u.key.key, buf, sizeof(buf));
13505 }
13506 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13507 if (strlen(buf) != 0){
13508 if (set_sae == TRUE)
13509 security->u.key.type = wifi_security_key_type_psk_sae;
13510 else if (strlen(buf) == 64)
13511 security->u.key.type = wifi_security_key_type_psk;
13512 else
13513 security->u.key.type = wifi_security_key_type_pass;
13514 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer9df4e652022-10-11 11:27:38 +080013515 }
developer9df4e652022-10-11 11:27:38 +080013516 security->u.key.key[255] = '\0';
13517 }
13518
developer587c1b62022-09-27 15:58:59 +080013519 memset(buf, 0, sizeof(buf));
13520 wifi_getApSecurityMFPConfig(ap_index, buf);
13521 if (strcmp(buf, "Disabled") == 0)
13522 security->mfp = wifi_mfp_cfg_disabled;
13523 else if (strcmp(buf, "Optional") == 0)
13524 security->mfp = wifi_mfp_cfg_optional;
13525 else if (strcmp(buf, "Required") == 0)
13526 security->mfp = wifi_mfp_cfg_required;
13527
13528 memset(buf, 0, sizeof(buf));
13529 security->wpa3_transition_disable = FALSE;
13530 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13531 disable = strtol(buf, NULL, 16);
13532 if (disable != 0)
13533 security->wpa3_transition_disable = TRUE;
13534
13535 memset(buf, 0, sizeof(buf));
13536 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13537 if (strlen(buf) == 0)
13538 security->rekey_interval = 86400;
13539 else
13540 security->rekey_interval = strtol(buf, NULL, 10);
13541
13542 memset(buf, 0, sizeof(buf));
13543 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13544 if (strlen(buf) == 0)
13545 security->strict_rekey = 1;
13546 else
13547 security->strict_rekey = strtol(buf, NULL, 10);
13548
13549 memset(buf, 0, sizeof(buf));
13550 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13551 if (strlen(buf) == 0)
13552 security->eapol_key_retries = 4;
13553 else
13554 security->eapol_key_retries = strtol(buf, NULL, 10);
13555
13556 memset(buf, 0, sizeof(buf));
13557 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13558 if (strlen(buf) == 0)
13559 security->disable_pmksa_caching = FALSE;
13560 else
13561 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13562
13563 /* TODO
13564 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13565 */
13566 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13567 security->eap_identity_req_timeout = 0;
13568 security->eap_identity_req_retries = 0;
13569 security->eap_req_timeout = 0;
13570 security->eap_req_retries = 0;
13571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013572 return RETURN_OK;
13573}
13574
13575#endif /* WIFI_HAL_VERSION_3 */
13576
13577#ifdef WIFI_HAL_VERSION_3_PHASE2
13578INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13579{
developerd946fd62022-12-08 18:03:28 +080013580 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013581 char cmd[128] = {0};
13582 char buf[128] = {0};
13583 char *mac_addr = NULL;
13584 BOOL status = FALSE;
13585 size_t len = 0;
13586
13587 if(ap_index > MAX_APS)
13588 return RETURN_ERR;
13589
13590 *output_numDevices = 0;
13591 wifi_getApEnable(ap_index, &status);
13592 if (status == FALSE)
13593 return RETURN_OK;
13594
developerac6f1142022-12-20 19:26:35 +080013595 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013596 return RETURN_ERR;
13597 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013598 _syscmd(cmd, buf, sizeof(buf));
13599
13600 mac_addr = strtok(buf, "\n");
13601 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13602 *output_numDevices = i + 1;
13603 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13604 addr_ptr = output_deviceMacAddressArray[i];
13605 mac_addr_aton(addr_ptr, mac_addr);
13606 mac_addr = strtok(NULL, "\n");
13607 }
13608
13609 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013610}
13611#else
13612INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13613{
developerd946fd62022-12-08 18:03:28 +080013614 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013615 char cmd[128];
13616 BOOL status = false;
13617
13618 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13619 return RETURN_ERR;
13620
13621 output_buf[0] = '\0';
13622
13623 wifi_getApEnable(ap_index,&status);
13624 if (!status)
13625 return RETURN_OK;
13626
developerac6f1142022-12-20 19:26:35 +080013627 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
developerd946fd62022-12-08 18:03:28 +080013628 return RETURN_ERR;
13629 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013630 _syscmd(cmd, output_buf, output_buf_size);
13631
13632 return RETURN_OK;
13633}
13634#endif
developer2f513ab2022-09-13 14:26:06 +080013635
13636INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13637{
13638 char output[16]={'\0'};
13639 char config_file[MAX_BUF_SIZE] = {0};
13640
13641 if (!enable)
13642 return RETURN_ERR;
13643
13644 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13645 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13646
13647 if (strlen(output) == 0)
13648 *enable = FALSE;
13649 else if (strncmp(output, "1", 1) == 0)
13650 *enable = TRUE;
13651 else
13652 *enable = FALSE;
13653
13654 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13655 return RETURN_OK;
13656}
developer2d9c30f2022-09-13 15:06:14 +080013657
13658INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13659{
developer804c64f2022-10-19 13:54:40 +080013660 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013661 return RETURN_ERR;
13662 *output_enable=TRUE;
13663 return RETURN_OK;
13664}
developerfd7d2892022-09-13 16:44:53 +080013665
13666INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13667{
13668 char cmd[128] = {0};
13669 char buf[128] = {0};
13670 char line[128] = {0};
13671 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013672 FILE *f = NULL;
13673 int index = 0;
13674 int exp = 0;
13675 int mantissa = 0;
13676 int duration = 0;
13677 int radio_index = 0;
13678 int max_radio_num = 0;
13679 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013680 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013681 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13682
13683 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013684
developerfd7d2892022-09-13 16:44:53 +080013685 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013686
13687 phyId = radio_index_to_phy(radio_index);
13688 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013689 _syscmd(cmd, buf, sizeof(buf));
13690 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13691 if (*numSessionReturned > maxNumberSessions)
13692 *numSessionReturned = maxNumberSessions;
13693 else if (*numSessionReturned < 1) {
13694 *numSessionReturned = 0;
13695 return RETURN_OK;
13696 }
13697
developer033b37b2022-10-18 11:27:46 +080013698 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 +080013699 if ((f = popen(cmd, "r")) == NULL) {
13700 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13701 return RETURN_ERR;
13702 }
13703
13704 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013705 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013706 char *tmp = NULL;
13707 strcpy(buf, line);
13708 tmp = strtok(buf, " ");
13709 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13710 tmp = strtok(NULL, " ");
13711 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13712 tmp = strtok(NULL, " ");
13713 if (strstr(tmp, "t")) {
13714 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13715 }
13716 if (strstr(tmp, "a")) {
13717 twtSessions[index].twtParameters.operation.announced = TRUE;
13718 }
13719 tmp = strtok(NULL, " ");
13720 exp = strtol(tmp, NULL, 10);
13721 tmp = strtok(NULL, " ");
13722 mantissa = strtol(tmp, NULL, 10);
13723 tmp = strtok(NULL, " ");
13724 duration = strtol(tmp, NULL, 10);
13725
13726 // only implicit supported
13727 twtSessions[index].twtParameters.operation.implicit = TRUE;
13728 // only individual agreement supported
13729 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13730
13731 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13732 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013733 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013734 // Overflow handling
13735 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13736 } else {
13737 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13738 }
13739 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13740 index++;
13741 }
13742
13743 pclose(f);
13744 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13745 return RETURN_OK;
13746}