blob: a8bb5b80fe632c9ebb10b54d19004c8aef7acd11 [file] [log] [blame]
developer72fb0bb2023-01-11 09:46:29 +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*/
37#define MTK_IMPL
38#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
66#define MAX_BUF_SIZE 256
67#define MAX_CMD_SIZE 256
68#define IF_NAME_SIZE 16
69#define CONFIG_PREFIX "/nvram/hostapd"
developer4903e3f2023-05-15 10:04:40 +080070#define LOGAN_DAT_FILE "/etc/wireless/mediatek/mt7990.b"
developer72fb0bb2023-01-11 09:46:29 +080071#define ACL_PREFIX "/nvram/hostapd-acl"
72#define DENY_PREFIX "/nvram/hostapd-deny"
73//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
74#define SOCK_PREFIX "/var/run/hostapd/wifi"
75#define VAP_STATUS_FILE "/nvram/vap-status"
76#define ESSID_FILE "/tmp/essid"
77#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
78#define CHANNEL_STATS_FILE "/tmp/channel_stats"
79#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
80#define VLAN_FILE "/nvram/hostapd.vlan"
81#define PSK_FILE "/nvram/hostapd"
82#define MCS_FILE "/tmp/MCS"
developera1255e42023-05-13 17:45:02 +080083#define POWER_PERCENTAGE "/tmp/POWER"
84#define MGMT_POWER_CTRL "/tmp/mgmt_power_ctrl"
85/*LOGAN_DAT_FILE: may be different on customer's platform.*/
86#define LOGAN_DAT_FILE "/etc/wireless/mediatek/mt7990.b"
87
developer72fb0bb2023-01-11 09:46:29 +080088#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer72fb0bb2023-01-11 09:46:29 +080089#define BRIDGE_NAME "brlan0"
developer4903e3f2023-05-15 10:04:40 +080090#define BASE_PHY_INDEX 1
91#define BASE_RADIO_INDEX 0
developer72fb0bb2023-01-11 09:46:29 +080092
93/*
94 MAX_APS - Number of all AP available in system
95 2x Home AP
96 2x Backhaul AP
97 2x Guest AP
98 2x Secure Onboard AP
99 2x Service AP
100
101*/
102
103
104#define MAX_APS MAX_NUM_RADIOS*5
developer7e4a2a62023-04-06 19:56:03 +0800105
106#define PREFIX_WIFI2G "ra"
107#define PREFIX_WIFI5G "rai"
108#define PREFIX_WIFI6G "rax"
developer72fb0bb2023-01-11 09:46:29 +0800109
110#ifndef RADIO_PREFIX
111#define RADIO_PREFIX "wlan"
112#endif
113
114#define MAX_ASSOCIATED_STA_NUM 2007
115
116//Uncomment to enable debug logs
117//#define WIFI_DEBUG
118
119#ifdef WIFI_DEBUG
120#define wifi_dbg_printf printf
121#define WIFI_ENTRY_EXIT_DEBUG printf
122#else
123#define wifi_dbg_printf(format, args...) printf("")
124#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
125#endif
126
127#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
128#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
129#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
130#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
131#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
132#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
133#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
134#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
135#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
136#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
137
138#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
139
140#define BW_FNAME "/nvram/bw_file.txt"
141
142#define PS_MAX_TID 16
143
developer96b38512023-02-22 11:17:45 +0800144#define MAX_CARD_INDEX 3
145
developer72fb0bb2023-01-11 09:46:29 +0800146static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
148 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
149 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
150 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
151 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
152 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
153 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
154 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
155 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
156 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
157 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
158 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
159 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
160 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
161 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
162 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
163};
164
165typedef unsigned long long u64;
166
167/* Enum to define WiFi Bands */
168typedef enum
169{
170 band_invalid = -1,
171 band_2_4 = 0,
172 band_5 = 1,
173 band_6 = 2,
174} wifi_band;
175
developer17038e62023-03-02 14:43:43 +0800176char* wifi_band_str[] = {
177 "2G",
178 "5G",
179 "6G",
180};
181
developer72fb0bb2023-01-11 09:46:29 +0800182typedef enum {
183 WIFI_MODE_A = 0x01,
184 WIFI_MODE_B = 0x02,
185 WIFI_MODE_G = 0x04,
186 WIFI_MODE_N = 0x08,
187 WIFI_MODE_AC = 0x10,
188 WIFI_MODE_AX = 0x20,
developera1255e42023-05-13 17:45:02 +0800189 WIFI_MODE_BE = 0x40,
developer72fb0bb2023-01-11 09:46:29 +0800190} wifi_ieee80211_Mode;
191
192#ifdef WIFI_HAL_VERSION_3
193
194// Return number of elements in array
195#ifndef ARRAY_SIZE
196#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
197#endif /* ARRAY_SIZE */
198
199#ifndef ARRAY_AND_SIZE
200#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
201#endif /* ARRAY_AND_SIZE */
202
203#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
204
205typedef struct {
206 int32_t value;
207 int32_t param;
208 intptr_t key;
209 intptr_t data;
210} wifi_secur_list;
211
212static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
213static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
214wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
215wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
216char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
217static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
218
219static wifi_secur_list map_security[] =
220{
221 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
222 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
223 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
224 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
225 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
226 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
227 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
228 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
229 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
230 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
231 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
232 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
233};
234
235wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
236{
237 wifi_secur_list *item;
238 int i;
239
240 for (item = list,i = 0;i < list_sz; item++, i++) {
241 if ((int)(item->key) == key) {
242 return item;
243 }
244 }
245
246 return NULL;
247}
248
249char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
250{
251 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
252
253 if (!item) {
254 return "";
255 }
256
257 return (char *)(item->data);
258}
259
260wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
261{
262 wifi_secur_list *item;
263 int i;
264
265 for (item = list,i = 0;i < list_sz; item++, i++) {
266 if (strcmp((char *)(item->data), str) == 0) {
267 return item;
268 }
269 }
270
271 return NULL;
272}
273#endif /* WIFI_HAL_VERSION_3 */
274
developer96b38512023-02-22 11:17:45 +0800275
276static char l1profile[32] = "/etc/wireless/l1profile.dat";
developer17038e62023-03-02 14:43:43 +0800277char main_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
278char ext_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
279#define MAX_SSID_LEN 64
280char default_ssid[MAX_NUM_RADIOS][MAX_SSID_LEN];;
developer745f0bd2023-03-06 14:32:53 +0800281int radio_band[MAX_NUM_RADIOS];
developer17038e62023-03-02 14:43:43 +0800282
283static int array_index_to_vap_index(UINT radioIndex, int arrayIndex);
284static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex);
285
developer96b38512023-02-22 11:17:45 +0800286
287static int
288get_value(const char *conf_file, const char *param, char *value, int len)
289{
290 FILE *fp;
291 int ret = -1;
292 int param_len = strlen(param);
293 int buf_len;
294 char buf[256];
295
296 fp = fopen(conf_file, "r");
297 if (!fp) {
298 return -1;
299 }
300
301 while (fgets(buf, sizeof(buf), fp)) {
302 buf_len = strlen(buf);
303 if (buf[buf_len - 1] == '\n') {
304 buf_len--;
305 buf[buf_len] = '\0';
306 }
307 if ((buf_len > param_len) &&
308 (strncmp(buf, param, param_len) == 0) &&
309 (buf[param_len] == '=')) {
310
311 if (buf_len == (param_len + 1)) {
312 value[0] = '\0';
313 ret = 0;
314 } else {
315 ret = snprintf(value, len, "%s", buf + (param_len + 1));
316 }
317 fclose(fp);
318 return ret;
319 }
320 }
321 fclose(fp);
322 return -1;
323}
324
325static int
326get_value_by_idx(const char *conf_file, const char *param, int idx, char *value, int len)
327{
328 char buf[256];
329 int ret;
330 char *save_ptr = NULL;
331 char *tok = NULL;
332
333 ret = get_value(conf_file, param, buf, sizeof(buf));
334 if (ret < 0)
335 return ret;
336
337 tok = strtok_r(buf, ";", &save_ptr);
338 do {
339 if (idx == 0 || tok == NULL)
340 break;
341 else
342 idx--;
343
344 tok = strtok_r(NULL, ";", &save_ptr);
345 } while (tok != NULL);
346
347 if (tok) {
348 ret = snprintf(value, len, "%s", tok);
349 } else {
350 ret = 0;
351 value[0] = '\0';
352 }
353
354 return ret;
355}
356
357
developer72fb0bb2023-01-11 09:46:29 +0800358#ifdef HAL_NETLINK_IMPL
359typedef struct {
360 int id;
361 struct nl_sock* socket;
362 struct nl_cb* cb;
363} Netlink;
364
365static int mac_addr_aton(unsigned char *mac_addr, char *arg)
366{
367 unsigned int mac_addr_int[6]={};
368 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);
369 mac_addr[0] = mac_addr_int[0];
370 mac_addr[1] = mac_addr_int[1];
371 mac_addr[2] = mac_addr_int[2];
372 mac_addr[3] = mac_addr_int[3];
373 mac_addr[4] = mac_addr_int[4];
374 mac_addr[5] = mac_addr_int[5];
375 return 0;
376}
377
378static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
379{
380 unsigned int mac_addr_int[6]={};
381 mac_addr_int[0] = arg[0];
382 mac_addr_int[1] = arg[1];
383 mac_addr_int[2] = arg[2];
384 mac_addr_int[3] = arg[3];
385 mac_addr_int[4] = arg[4];
386 mac_addr_int[5] = arg[5];
387 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]);
388 return;
389}
390
391static int ieee80211_frequency_to_channel(int freq)
392{
393 /* see 802.11-2007 17.3.8.3.2 and Annex J */
394 if (freq == 2484)
395 return 14;
396 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
397 else if (freq == 5935)
398 return 2;
399 else if (freq < 2484)
400 return (freq - 2407) / 5;
401 else if (freq >= 4910 && freq <= 4980)
402 return (freq - 4000) / 5;
403 else if (freq < 5950)
404 return (freq - 5000) / 5;
405 else if (freq <= 45000) /* DMG band lower limit */
406 /* see 802.11ax D6.1 27.3.23.2 */
407 return (freq - 5950) / 5;
408 else if (freq >= 58320 && freq <= 70200)
409 return (freq - 56160) / 2160;
410 else
411 return 0;
412}
413
414static int initSock80211(Netlink* nl) {
415 nl->socket = nl_socket_alloc();
416 if (!nl->socket) {
417 fprintf(stderr, "Failing to allocate the sock\n");
418 return -ENOMEM;
419 }
420
421 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
422
423 if (genl_connect(nl->socket)) {
424 fprintf(stderr, "Failed to connect\n");
425 nl_close(nl->socket);
426 nl_socket_free(nl->socket);
427 return -ENOLINK;
428 }
429
430 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
431 if (nl->id< 0) {
432 fprintf(stderr, "interface not found.\n");
433 nl_close(nl->socket);
434 nl_socket_free(nl->socket);
435 return -ENOENT;
436 }
437
438 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
439 if ((!nl->cb)) {
440 fprintf(stderr, "Failed to allocate netlink callback.\n");
441 nl_close(nl->socket);
442 nl_socket_free(nl->socket);
443 return ENOMEM;
444 }
445
446 return nl->id;
447}
448
449static int nlfree(Netlink *nl)
450{
451 nl_cb_put(nl->cb);
452 nl_close(nl->socket);
453 nl_socket_free(nl->socket);
454 return 0;
455}
456
457static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
458 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
459 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
460 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
461};
462
463static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
464};
465
466static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
467};
468
469typedef struct _wifi_channelStats_loc {
470 INT array_size;
471 INT ch_number;
472 BOOL ch_in_pool;
473 INT ch_noise;
474 BOOL ch_radar_noise;
475 INT ch_max_80211_rssi;
476 INT ch_non_80211_noise;
477 INT ch_utilization;
478 ULLONG ch_utilization_total;
479 ULLONG ch_utilization_busy;
480 ULLONG ch_utilization_busy_tx;
481 ULLONG ch_utilization_busy_rx;
482 ULLONG ch_utilization_busy_self;
483 ULLONG ch_utilization_busy_ext;
484} wifi_channelStats_t_loc;
485
486typedef struct wifi_device_info {
487 INT wifi_devIndex;
488 UCHAR wifi_devMacAddress[6];
489 CHAR wifi_devIPAddress[64];
490 BOOL wifi_devAssociatedDeviceAuthentiationState;
491 INT wifi_devSignalStrength;
492 INT wifi_devTxRate;
493 INT wifi_devRxRate;
494} wifi_device_info_t;
495
496#endif
497
498//For 5g Alias Interfaces
499static BOOL priv_flag = TRUE;
500static BOOL pub_flag = TRUE;
501static BOOL Radio_flag = TRUE;
502//wifi_setApBeaconRate(1, beaconRate);
503
504BOOL multiple_set = FALSE;
505
506struct params
507{
508 char * name;
509 char * value;
510};
511
512static int _syscmd(char *cmd, char *retBuf, int retBufSize)
513{
514 FILE *f;
515 char *ptr = retBuf;
516 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
517
518 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
519 if((f = popen(cmd, "r")) == NULL) {
520 fprintf(stderr,"\npopen %s error\n", cmd);
521 return RETURN_ERR;
522 }
523
524 while(!feof(f))
525 {
526 *ptr = 0;
527 if(bufSize>=128) {
528 bufbytes=128;
529 } else {
530 bufbytes=bufSize-1;
531 }
532
533 fgets(ptr,bufbytes,f);
534 readbytes=strlen(ptr);
535
536 if(!readbytes)
537 break;
538
539 bufSize-=readbytes;
540 ptr += readbytes;
541 }
542 cmd_ret = pclose(f);
543 retBuf[retBufSize-1]=0;
544 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
545
546 return cmd_ret >> 8;
547}
548
549INT radio_index_to_phy(int radioIndex)
550{
developer17038e62023-03-02 14:43:43 +0800551 /* TODO */
552 return radioIndex;
developer72fb0bb2023-01-11 09:46:29 +0800553}
554
555INT wifi_getMaxRadioNumber(INT *max_radio_num)
556{
557 char cmd[64] = {0};
558 char buf[4] = {0};
559
560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
561
562 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
563 _syscmd(cmd, buf, sizeof(buf));
564 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
565
566 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
567
568 return RETURN_OK;
569}
570
developer17038e62023-03-02 14:43:43 +0800571wifi_band radio_index_to_band(int radioIndex)
572{
developer745f0bd2023-03-06 14:32:53 +0800573 return radio_band[radioIndex];
developer17038e62023-03-02 14:43:43 +0800574}
575
developer72fb0bb2023-01-11 09:46:29 +0800576wifi_band wifi_index_to_band(int apIndex)
577{
578 char cmd[128] = {0};
579 char buf[64] = {0};
580 int nl80211_band = 0;
581 int i = 0;
582 int phyIndex = 0;
583 int radioIndex = 0;
584 int max_radio_num = 0;
585 wifi_band band = band_invalid;
586
587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
588
589 wifi_getMaxRadioNumber(&max_radio_num);
590 radioIndex = apIndex % max_radio_num;
591 phyIndex = radio_index_to_phy(radioIndex);
592 while(i < 10){
593 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
594 _syscmd(cmd, buf, sizeof(buf));
595 nl80211_band = strtol(buf, NULL, 10);
596 if (nl80211_band == 1)
597 band = band_2_4;
598 else if (nl80211_band == 2)
599 band = band_5;
600 else if (nl80211_band == 4) // band == 3 is 60GHz
601 band = band_6;
602
603 if(band != band_invalid)
604 break;
developer69b61b02023-03-07 17:17:44 +0800605
developer72fb0bb2023-01-11 09:46:29 +0800606 i++;
607 sleep(1);
608 }
609
610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
611 return band;
612}
developer4903e3f2023-05-15 10:04:40 +0800613
614static int wifi_datfileRead(char *dat_file, char *param, char *output, int output_size)
615{
616 char cmd[MAX_CMD_SIZE]={'\0'};
617 char buf[MAX_BUF_SIZE]={'\0'};
618 int ret = 0;
619
620 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", dat_file, param);
621 ret = _syscmd(cmd, buf, sizeof(buf));
622 if ((ret != 0) && (strlen(buf) == 0))
623 return -1;
624 snprintf(output, output_size, "%s", buf);
625
626 return 0;
627}
628static int wifi_datfileWrite(char *dat_file, struct params *list, int item_count)
629{
630 char cmd[MAX_CMD_SIZE]={'\0'};
631 char buf[MAX_BUF_SIZE]={'\0'};
632
633 for(int i=0;i<item_count;i++) {
634 wifi_datfileRead(dat_file, list[i].name, buf, sizeof(buf));
635 if (strlen(buf) == 0) //Insert
636 snprintf(cmd, sizeof(cmd), "sed -i -e '$a %s=%s' %s", list[i].name, list[i].value, dat_file);
637 else //Update
638 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, dat_file);
639
640 if(_syscmd(cmd, buf, sizeof(buf)))
641 return -1;
642 }
developer72fb0bb2023-01-11 09:46:29 +0800643
developer4903e3f2023-05-15 10:04:40 +0800644 return 0;
645}
developer72fb0bb2023-01-11 09:46:29 +0800646static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
647{
developer7e4a2a62023-04-06 19:56:03 +0800648 char cmd[MAX_CMD_SIZE] = {0};
649 char buf[MAX_BUF_SIZE] = {0};
650 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +0800651
developer7e4a2a62023-04-06 19:56:03 +0800652 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
653 conf_file, param);
developer72fb0bb2023-01-11 09:46:29 +0800654
developer7e4a2a62023-04-06 19:56:03 +0800655 if (ret < 0) {
656 printf("%s: snprintf error!", __func__);
657 return -1;
658 }
659
660 ret = _syscmd(cmd, buf, sizeof(buf));
661 if ((ret != 0) && (strlen(buf) == 0)) {
662 printf("%s: _syscmd error!", __func__);
663 return -1;
664 }
665
666 snprintf(output, output_size, "%s", buf);
667
668 return 0;
developer72fb0bb2023-01-11 09:46:29 +0800669}
670
671static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
672{
developer7e4a2a62023-04-06 19:56:03 +0800673 char cmd[MAX_CMD_SIZE] = {0};
674 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +0800675
developer7e4a2a62023-04-06 19:56:03 +0800676 for (int i = 0; i < item_count; i++) {
developer72fb0bb2023-01-11 09:46:29 +0800677 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +0800678 if (strlen(buf) == 0) /*no such item, insert it*/
developera1255e42023-05-13 17:45:02 +0800679 snprintf(cmd, sizeof(cmd), "sed -i -e '$a %s=%s' %s", list[i].name, list[i].value, conf_file);
developer7e4a2a62023-04-06 19:56:03 +0800680 else /*find the item, update it*/
developer72fb0bb2023-01-11 09:46:29 +0800681 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
developera1255e42023-05-13 17:45:02 +0800682
developer72fb0bb2023-01-11 09:46:29 +0800683 if(_syscmd(cmd, buf, sizeof(buf)))
684 return -1;
685 }
686
developera1255e42023-05-13 17:45:02 +0800687 return 0;
688}
689static int wifi_datfileRead(char *conf_file, char *param, char *output, int output_size)
690{
691 char cmd[MAX_CMD_SIZE] = {0};
692 char buf[MAX_BUF_SIZE] = {0};
693 int ret = 0;
694
695 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
696 conf_file, param);
697
698 if (ret < 0) {
699 printf("%s: snprintf error!", __func__);
700 return -1;
701 }
702
703 ret = _syscmd(cmd, buf, sizeof(buf));
704 if ((ret != 0) && (strlen(buf) == 0)) {
705 printf("%s: _syscmd error!", __func__);
706 return -1;
707 }
708
709 snprintf(output, output_size, "%s", buf);
710
developer72fb0bb2023-01-11 09:46:29 +0800711 return 0;
712}
713
developera1255e42023-05-13 17:45:02 +0800714static int wifi_datfileWrite(char *conf_file, struct params *list, int item_count)
715{
716 char cmd[MAX_CMD_SIZE] = {0};
717 char buf[MAX_BUF_SIZE] = {0};
718
719 for (int i = 0; i < item_count; i++) {
720 wifi_datfileRead(conf_file, list[i].name, buf, sizeof(buf));
721 if (strlen(buf) == 0) /*no such item, insert it*/
722 snprintf(cmd, sizeof(cmd), "sed -i -e '$a %s=%s' %s", list[i].name, list[i].value, conf_file);
723 else /*find the item, update it*/
724 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
725
726 if(_syscmd(cmd, buf, sizeof(buf)))
727 return -1;
728 }
729
730 return 0;
731}
732
developer72fb0bb2023-01-11 09:46:29 +0800733//For Getting Current Interface Name from corresponding hostapd configuration
734static int wifi_GetInterfaceName(int apIndex, char *interface_name)
735{
736 char config_file[128] = {0};
737
738 if (interface_name == NULL)
739 return RETURN_ERR;
740
741 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
742
743 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
744 wifi_hostapdRead(config_file, "interface", interface_name, 16);
745 if (strlen(interface_name) == 0)
746 return RETURN_ERR;
747
748 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
749 return RETURN_OK;
750}
751
developer4903e3f2023-05-15 10:04:40 +0800752/* index: radio index or phy index
753 phy: true-> base phy command
754 false-> base radio command */
755static int wifi_mwctlSet(int index, struct params *mwctl, bool phy)
756{
757 char cmd[MAX_CMD_SIZE]={'\0'};
758 char buf[MAX_BUF_SIZE]={'\0'};
759 char interface_name[16] = {0};
760
761 if (phy == TRUE)
762 snprintf(cmd, sizeof(cmd), "mwctl phy phy%d set %s%s", index, mwctl->name, mwctl->value);
763 else {
764 if (wifi_GetInterfaceName(index, interface_name) != RETURN_OK)
765 return RETURN_ERR;
766 snprintf(cmd, sizeof(cmd), "mwctl %s set %s%s", interface_name, mwctl->name, mwctl->value);
767 }
768 if (_syscmd(cmd, buf, sizeof(buf)))
769 return RETURN_ERR;
770
developera1255e42023-05-13 17:45:02 +0800771static UCHAR get_bssnum_byindex(INT radio_index, UCHAR *bss_cnt)
772{
773 char interface_name[IF_NAME_SIZE] = {0};
774 char cmd[MAX_BUF_SIZE]={'\0'};
775 char buf[MAX_CMD_SIZE]={'\0'};
776 UCHAR channel = 0;
777
778 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
779 return RETURN_ERR;
780 /*interface name to channel number*/
781 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep -i 'channel' | cut -d ' ' -f2", interface_name);
782 _syscmd(cmd, buf, sizeof(buf));
783 channel = atoi(buf);
784 WIFI_ENTRY_EXIT_DEBUG("%s:channel=%d\n", __func__, channel);
785 /*count dev number with the same channel*/
786 snprintf(cmd, sizeof(cmd), "iw dev | grep -i 'channel %d' | wc -l", channel);
787 _syscmd(cmd, buf, sizeof(buf));
788 *bss_cnt = atoi(buf) - 1;/*1 for apcli interface*/
789 WIFI_ENTRY_EXIT_DEBUG("%s:bss_cnt=%d\n", __func__, *bss_cnt);
790 return RETURN_OK;
791}
developer72fb0bb2023-01-11 09:46:29 +0800792
793static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
794{
795 char interface_name[16] = {0};
796 if (multiple_set == TRUE)
797 return RETURN_OK;
798 char cmd[MAX_CMD_SIZE]="", output[32]="";
799 FILE *fp;
800 int i;
801 //NOTE RELOAD should be done in ApplySSIDSettings
802 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
803 return RETURN_ERR;
804 for(i=0; i<item_count; i++, list++)
805 {
developer4903e3f2023-05-15 10:04:40 +0800806 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s SET %s %s", interface_name, list->name, list->value);
807 printf("ck_test: %s, cmd:%s\n", __func__, cmd);
developer72fb0bb2023-01-11 09:46:29 +0800808 if((fp = popen(cmd, "r"))==NULL)
809 {
810 perror("popen failed");
811 return -1;
812 }
813 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
814 {
815 pclose(fp);
816 perror("fgets failed");
817 return -1;
818 }
819 pclose(fp);
820 }
821 return 0;
822}
823
developer7e4a2a62023-04-06 19:56:03 +0800824static int wifi_quick_reload_ap(int apIndex)
825{
826 char interface_name[IF_NAME_SIZE] = {0};
827 char cmd[MAX_CMD_SIZE] = {0};
828 char buf[MAX_BUF_SIZE] = {0};
829
830 if (multiple_set == TRUE)
831 return RETURN_OK;
832
833 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
834 return RETURN_ERR;
835
836 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
837 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
838 return RETURN_ERR;
839
840 return RETURN_OK;
841}
842
developer72fb0bb2023-01-11 09:46:29 +0800843static int wifi_reloadAp(int apIndex)
844{
845 char interface_name[16] = {0};
846 if (multiple_set == TRUE)
847 return RETURN_OK;
848 char cmd[MAX_CMD_SIZE]="";
849 char buf[MAX_BUF_SIZE]="";
850
851 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
852 return RETURN_ERR;
853 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
854 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
855 return RETURN_ERR;
856
857 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
858 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
859 return RETURN_ERR;
860
861 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
862 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
863 return RETURN_ERR;
864
865 return RETURN_OK;
866}
867
868INT File_Reading(CHAR *file, char *Value)
869{
870 FILE *fp = NULL;
871 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
872 int count = 0;
873
874 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
875 fp = popen(file,"r");
876 if(fp == NULL)
877 return RETURN_ERR;
878
879 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
880 {
881 for(count=0;buf[count]!='\n';count++)
882 copy_buf[count]=buf[count];
883 copy_buf[count]='\0';
884 }
885 strcpy(Value,copy_buf);
886 pclose(fp);
887 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
888
889 return RETURN_OK;
890}
891
892void wifi_RestartHostapd_2G()
893{
894 int Public2GApIndex = 4;
895
896 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
897 wifi_setApEnable(Public2GApIndex, FALSE);
898 wifi_setApEnable(Public2GApIndex, TRUE);
899 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
900}
901
902void wifi_RestartHostapd_5G()
903{
904 int Public5GApIndex = 5;
905
906 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
907 wifi_setApEnable(Public5GApIndex, FALSE);
908 wifi_setApEnable(Public5GApIndex, TRUE);
909 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
910}
911
912void wifi_RestartPrivateWifi_2G()
913{
914 int PrivateApIndex = 0;
915
916 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
917 wifi_setApEnable(PrivateApIndex, FALSE);
918 wifi_setApEnable(PrivateApIndex, TRUE);
919 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
920}
921
922void wifi_RestartPrivateWifi_5G()
923{
924 int Private5GApIndex = 1;
925
926 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
927 wifi_setApEnable(Private5GApIndex, FALSE);
928 wifi_setApEnable(Private5GApIndex, TRUE);
929 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
930}
931
932static int writeBandWidth(int radioIndex,char *bw_value)
933{
934 char buf[MAX_BUF_SIZE];
935 char cmd[MAX_CMD_SIZE];
936
937 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
938 if(_syscmd(cmd, buf, sizeof(buf)))
939 {
940 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
941 _syscmd(cmd, buf, sizeof(buf));
942 return RETURN_OK;
943 }
944
945 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
946 _syscmd(cmd,buf,sizeof(buf));
947 return RETURN_OK;
948}
949
950static int readBandWidth(int radioIndex,char *bw_value)
951{
952 char buf[MAX_BUF_SIZE] = {0};
953 char cmd[MAX_CMD_SIZE] = {0};
954 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
955 _syscmd(cmd,buf,sizeof(buf));
956 if(NULL!=strstr(buf,"20MHz"))
957 {
958 strcpy(bw_value,"20MHz");
959 }
960 else if(NULL!=strstr(buf,"40MHz"))
961 {
962 strcpy(bw_value,"40MHz");
963 }
964 else if(NULL!=strstr(buf,"80MHz"))
965 {
966 strcpy(bw_value,"80MHz");
967 }
968 else
969 {
970 return RETURN_ERR;
971 }
972 return RETURN_OK;
973}
974
975// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
976INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
977{
978 struct params params={'\0'};
979 char config_file[MAX_BUF_SIZE] = {0};
980 char buf[MAX_BUF_SIZE] = {'\0'};
981
982 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
983 // Copy the numeric value
984 if (strlen (beaconRate) >= 5) {
985 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
986 buf[strlen(beaconRate) - 4] = '\0';
987 } else if (strlen(beaconRate) > 0)
988 strcpy(buf, beaconRate);
989 else
990 return RETURN_ERR;
991
992 params.name = "beacon_rate";
993 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
994 if (strncmp(buf, "5.5", 3) == 0) {
995 snprintf(buf, sizeof(buf), "55");
996 params.value = buf;
997 } else {
998 strcat(buf, "0");
999 params.value = buf;
1000 }
1001
1002 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1003 wifi_hostapdWrite(config_file, &params, 1);
1004 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1006
1007 return RETURN_OK;
1008}
1009
1010INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
1011{
1012 char config_file[128] = {'\0'};
1013 char temp_output[128] = {'\0'};
1014 char buf[128] = {'\0'};
1015 char cmd[128] = {'\0'};
1016 int rate = 0;
1017 int phyId = 0;
1018
1019 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1020 if (NULL == beaconRate)
1021 return RETURN_ERR;
1022
1023 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1024 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
1025 phyId = radio_index_to_phy(radioIndex);
1026 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
1027 if(strlen(buf) > 0) {
1028 if (strncmp(buf, "55", 2) == 0)
1029 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
1030 else {
1031 rate = strtol(buf, NULL, 10)/10;
1032 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
1033 }
1034 } else {
1035 // config not set, so we would use lowest rate as default
1036 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
1037 _syscmd(cmd, buf, sizeof(buf));
1038 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
1039 }
1040 strncpy(beaconRate, temp_output, sizeof(temp_output));
1041 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1042
1043 return RETURN_OK;
1044}
1045
1046INT wifi_setLED(INT radioIndex, BOOL enable)
1047{
1048 return 0;
1049}
1050INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
1051{
1052 return RETURN_OK;
1053}
1054/**********************************************************************************
1055 *
developer69b61b02023-03-07 17:17:44 +08001056 * Wifi Subsystem level function prototypes
developer72fb0bb2023-01-11 09:46:29 +08001057 *
1058**********************************************************************************/
1059//---------------------------------------------------------------------------------------------------
1060//Wifi system api
1061//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
developer69b61b02023-03-07 17:17:44 +08001062INT wifi_getHalVersion(CHAR *output_string) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08001063{
1064 if(!output_string)
1065 return RETURN_ERR;
1066 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
1067
1068 return RETURN_OK;
1069}
1070
1071
1072/* wifi_factoryReset() function */
1073/**
developer69b61b02023-03-07 17:17:44 +08001074* @description Clears internal variables to implement a factory reset of the Wi-Fi
developer72fb0bb2023-01-11 09:46:29 +08001075* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
1076*
1077* @param None
1078*
1079* @return The status of the operation.
1080* @retval RETURN_OK if successful.
1081* @retval RETURN_ERR if any error is detected
1082*
1083* @execution Synchronous
1084* @sideeffect None
1085*
1086* @note This function must not suspend and must not invoke any blocking system
1087* calls. It should probably just send a message to a driver event handler task.
1088*
1089*/
1090INT wifi_factoryReset()
1091{
1092 char cmd[128];
1093
1094 /*delete running hostapd conf files*/
1095 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
1096 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
1097 system(cmd);
1098 system("systemctl restart hostapd.service");
1099
1100 return RETURN_OK;
1101}
1102
1103/* wifi_factoryResetRadios() function */
1104/**
1105* @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.
1106*
1107* @param None
1108* @return The status of the operation
1109* @retval RETURN_OK if successful
1110* @retval RETURN_ERR if any error is detected
1111*
1112* @execution Synchronous
1113*
1114* @sideeffect None
1115*
1116* @note This function must not suspend and must not invoke any blocking system
1117* calls. It should probably just send a message to a driver event handler task.
1118*
1119*/
1120INT wifi_factoryResetRadios()
1121{
1122 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
1123 return RETURN_OK;
1124
1125 return RETURN_ERR;
1126}
1127
1128
1129/* wifi_factoryResetRadio() function */
1130/**
1131* @description Restore selected radio parameters without touching access point parameters
1132*
1133* @param radioIndex - Index of Wi-Fi Radio channel
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_factoryResetRadio(int radioIndex) //RDKB
1147{
1148 system("systemctl stop hostapd.service");
1149
1150 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1151 if(radioIndex == 0)
1152 system("rm /nvram/hostapd0.conf");
1153 else if(radioIndex == 1)
1154 system("rm /nvram/hostapd1.conf");
1155 else
1156 return RETURN_ERR;
1157
1158 system("systemctl start hostapd.service");
1159 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1160 return RETURN_OK;
1161}
1162
1163/* wifi_initRadio() function */
1164/**
1165* Description: This function call initializes the specified radio.
developer69b61b02023-03-07 17:17:44 +08001166* Implementation specifics may dictate the functionality since
developer72fb0bb2023-01-11 09:46:29 +08001167* different hardware implementations may have different initilization requirements.
1168* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
1169*
1170* @return The status of the operation.
1171* @retval RETURN_OK if successful.
1172* @retval RETURN_ERR if any error is detected
1173*
1174* @execution Synchronous.
1175* @sideeffect None.
1176*
1177* @note This function must not suspend and must not invoke any blocking system
1178* calls. It should probably just send a message to a driver event handler task.
1179*
1180*/
1181INT wifi_initRadio(INT radioIndex)
1182{
1183 //TODO: Initializes the wifi subsystem (for specified radio)
1184 return RETURN_OK;
1185}
1186void macfilter_init()
1187{
1188 char count[4]={'\0'};
1189 char buf[253]={'\0'};
1190 char tmp[19]={'\0'};
1191 int dev_count,block,mac_entry=0;
1192 char res[4]={'\0'};
1193 char acl_file_path[64] = {'\0'};
1194 FILE *fp = NULL;
1195 int index=0;
1196 char iface[10]={'\0'};
1197 char config_file[MAX_BUF_SIZE] = {0};
1198
1199
1200 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1201
1202 fp=fopen(acl_file_path,"w+");
1203 if (fp == NULL) {
1204 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
developer17038e62023-03-02 14:43:43 +08001205 return;
developer72fb0bb2023-01-11 09:46:29 +08001206 }
1207 sprintf(buf,"#!/bin/sh \n");
1208 fprintf(fp,"%s\n",buf);
1209
1210 system("chmod 0777 /tmp/mac_filter.sh");
1211
1212 for(index=0;index<=1;index++)
1213 {
1214 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1215 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1216 sprintf(buf,"syscfg get %dcountfilter",index);
1217 _syscmd(buf,count,sizeof(count));
1218 mac_entry=atoi(count);
1219
1220 sprintf(buf,"syscfg get %dblockall",index);
1221 _syscmd(buf,res,sizeof(res));
1222 block = atoi(res);
1223
1224 //Allow only those macs mentioned in ACL
1225 if(block==1)
1226 {
1227 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1228 fprintf(fp,"%s\n",buf);
1229 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1230 {
1231 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1232 _syscmd(buf,tmp,sizeof(tmp));
1233 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1234 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1235 fprintf(fp,"%s\n",buf);
1236 }
1237 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1238 fprintf(fp,"%s\n",buf);
1239 }
1240
1241 //Block all the macs mentioned in ACL
1242 else if(block==2)
1243 {
1244 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1245 fprintf(fp,"%s\n",buf);
1246
1247 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1248 {
1249 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1250 _syscmd(buf,tmp,sizeof(tmp));
1251 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1252 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1253 fprintf(fp,"%s\n",buf);
1254 }
1255 }
1256 }
1257 fclose(fp);
1258}
1259
developer17038e62023-03-02 14:43:43 +08001260
1261static void
1262wifi_ParseProfile(void)
1263{
1264 int i;
1265 int max_radio_num = 0;
1266 int card_idx;
1267 int band_idx;
1268 int phy_idx = 0;
developer745f0bd2023-03-06 14:32:53 +08001269 int wireless_mode = 0;
developer17038e62023-03-02 14:43:43 +08001270 char buf[MAX_BUF_SIZE] = {0};
1271 char chip_name[12];
1272 char card_profile[MAX_BUF_SIZE] = {0};
1273 char band_profile[MAX_BUF_SIZE] = {0};
1274 FILE* fp;
1275
1276 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1277
1278 memset(main_prefix, 0, sizeof(main_prefix));
1279 memset(ext_prefix, 0, sizeof(ext_prefix));
1280 memset(default_ssid, 0, sizeof(default_ssid));
developer745f0bd2023-03-06 14:32:53 +08001281 for (i = 0; i < MAX_NUM_RADIOS; i++)
1282 radio_band[i] = band_invalid;
developer17038e62023-03-02 14:43:43 +08001283
1284 if (wifi_getMaxRadioNumber(&max_radio_num) != RETURN_OK) {
1285 /* LOG */
1286 return;
1287 }
1288
1289 for (card_idx = 0; card_idx < 3; card_idx++) {
1290 snprintf(buf, sizeof(buf), "INDEX%d", card_idx);
1291 if (get_value(l1profile, buf, chip_name, sizeof(chip_name)) < 0) {
1292 break;
1293 }
1294 snprintf(buf, sizeof(buf), "INDEX%d_profile_path", card_idx);
1295 if (get_value(l1profile, buf, card_profile, sizeof(card_profile)) < 0) {
1296 break;
1297 }
1298 for (band_idx = 0; band_idx < 3; band_idx++) {
1299 snprintf(buf, sizeof(buf), "BN%d_profile_path", band_idx);
1300 if (get_value(card_profile, buf, band_profile, sizeof(band_profile)) < 0) {
1301 /* LOG */
1302 break;
1303 }
1304
1305 snprintf(buf, sizeof(buf), "INDEX%d_main_ifname", card_idx);
1306 if (get_value_by_idx(l1profile, buf, band_idx, main_prefix[phy_idx], IFNAMSIZ) < 0) {
1307 /* LOG */
1308 }
1309
1310 snprintf(buf, sizeof(buf), "INDEX%d_ext_ifname", card_idx);
1311 if (get_value_by_idx(l1profile, buf, band_idx, ext_prefix[phy_idx], IFNAMSIZ) < 0) {
1312 /* LOG */
1313 }
1314
1315 if (get_value(band_profile, "SSID1", default_ssid[phy_idx], sizeof(default_ssid[phy_idx])) < 0) {
1316 /* LOG */
1317 }
developer745f0bd2023-03-06 14:32:53 +08001318 if (get_value(band_profile, "WirelessMode", buf, sizeof(buf)) < 0) {
1319 /* LOG */
1320 }
1321
1322 wireless_mode = atoi(buf);
1323 switch (wireless_mode) {
1324 case 22:
1325 case 16:
1326 case 6:
1327 case 4:
1328 case 1:
1329 radio_band[phy_idx] = band_2_4;
1330 break;
1331 case 23:
1332 case 17:
1333 case 14:
1334 case 11:
1335 case 2:
1336 radio_band[phy_idx] = band_5;
1337 break;
1338 case 24:
1339 case 18:
1340 radio_band[phy_idx] = band_6;
1341 break;
1342 }
developer17038e62023-03-02 14:43:43 +08001343 phy_idx++;
1344 }
1345 }
1346
1347 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1348}
1349
1350static void
1351wifi_PrepareDefaultHostapdConfigs(void)
1352{
developer0132ed92023-03-21 13:48:53 +08001353 int radio_idx;
1354 int bss_idx;
1355 int ap_idx;
1356 int band_idx;
1357 char buf[MAX_BUF_SIZE] = {0};
1358 char config_file[MAX_BUF_SIZE] = {0};
1359 char ssid[MAX_BUF_SIZE] = {0};
1360 char interface[32] = {0};
1361 char ret_buf[MAX_BUF_SIZE] = {0};
1362 char psk_file[64] = {0};
1363 struct params params[3];
developer17038e62023-03-02 14:43:43 +08001364
developer0132ed92023-03-21 13:48:53 +08001365 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1366 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1367 band_idx = radio_index_to_band(radio_idx);
1368 if (band_idx < 0) {
1369 break;
1370 }
1371 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1372 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1373
1374 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1375 snprintf(buf, sizeof(buf), "cp /etc/hostapd-%s.conf %s", wifi_band_str[band_idx], config_file);
1376 _syscmd(buf, ret_buf, sizeof(ret_buf));
developer17038e62023-03-02 14:43:43 +08001377
developer0132ed92023-03-21 13:48:53 +08001378 if (bss_idx == 0) {
1379 snprintf(ssid, sizeof(ssid), "%s", default_ssid[radio_idx]);
1380 snprintf(interface, sizeof(interface), "%s", main_prefix[radio_idx]);
1381 } else {
1382 snprintf(ssid, sizeof(ssid), "%s_%d", default_ssid[radio_idx], bss_idx);
1383 snprintf(interface, sizeof(interface), "%s%d", ext_prefix[radio_idx], bss_idx);
1384 }
developer17038e62023-03-02 14:43:43 +08001385
developer0132ed92023-03-21 13:48:53 +08001386 /* fix wpa_psk_file path */
1387 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", ap_idx);
developer17038e62023-03-02 14:43:43 +08001388
developer0132ed92023-03-21 13:48:53 +08001389 params[0].name = "ssid";
1390 params[0].value = ssid;
1391 params[1].name = "interface";
1392 params[1].value = interface;
1393 params[2].name = "wpa_psk_file";
1394 params[2].value = psk_file;
developer17038e62023-03-02 14:43:43 +08001395
developer0132ed92023-03-21 13:48:53 +08001396 wifi_hostapdWrite(config_file, params, 3);
1397 }
1398 }
1399 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001400}
1401
1402static void
1403wifiBringUpInterfacesForRadio(int radio_idx)
1404{
developer0132ed92023-03-21 13:48:53 +08001405 int bss_idx;
1406 int ap_idx;
1407 int band_idx;
1408 char cmd[MAX_CMD_SIZE] = {0};
1409 char config_file[MAX_BUF_SIZE] = {0};
1410 char ret_buf[MAX_BUF_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001411 char inf_name[IF_NAME_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001412
1413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer8a3bbbf2023-03-15 17:47:23 +08001414
developered997d32023-04-18 22:45:39 +08001415 bss_idx = 0;
1416 /*TBD: we need refine setup flow and mbss flow*/
1417// for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer0132ed92023-03-21 13:48:53 +08001418 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1419
1420 snprintf(cmd, sizeof(cmd), "touch %s%d.psk", PSK_FILE, ap_idx);
1421 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1422
1423 memset(cmd, 0, MAX_CMD_SIZE);
1424 memset(ret_buf, 0, MAX_BUF_SIZE);
developer17038e62023-03-02 14:43:43 +08001425
developer0132ed92023-03-21 13:48:53 +08001426 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1427 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radio_idx, config_file);
1428 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer8a3bbbf2023-03-15 17:47:23 +08001429
1430 wifi_GetInterfaceName(ap_idx, inf_name);
1431
1432 memset(cmd, 0, MAX_CMD_SIZE);
1433 memset(ret_buf, 0, MAX_BUF_SIZE);
1434
1435 /* fix vap-status file */
1436 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=1/\" %s", inf_name, inf_name, VAP_STATUS_FILE);
1437 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developered997d32023-04-18 22:45:39 +08001438// }
1439
1440 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001441}
1442
1443static void
1444wifi_BringUpInterfaces(void)
1445{
1446 int radio_idx;
1447 int bss_idx;
1448 int ap_idx;
1449 int band_idx;
1450 char cmd[MAX_BUF_SIZE] = {0};
1451 char config_file[MAX_BUF_SIZE] = {0};
1452 char ret_buf[MAX_BUF_SIZE]={'\0'};
1453
1454 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1455 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1456 band_idx = radio_index_to_band(radio_idx);
1457 if (band_idx < 0) {
1458 break;
1459 }
1460 wifiBringUpInterfacesForRadio(radio_idx);
1461 }
1462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1463}
1464
1465static void
1466wifi_BringDownInterfacesForRadio(int radio_idx)
1467{
1468 int bss_idx;
1469 int ap_idx;
1470 int band_idx;
1471 char cmd[MAX_BUF_SIZE] = {0};
1472 char config_file[MAX_BUF_SIZE] = {0};
1473 char ret_buf[MAX_BUF_SIZE]={'\0'};
1474
1475 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001476
developer8a3bbbf2023-03-15 17:47:23 +08001477 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radio_idx]);
1478 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1479
1480
developer17038e62023-03-02 14:43:43 +08001481 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1482}
1483
1484
1485static void
1486wifi_BringDownInterfaces(void)
1487{
1488 int radio_idx;
1489 int bss_idx;
1490 int ap_idx;
1491 int band_idx;
1492 char cmd[MAX_BUF_SIZE] = {0};
1493 char config_file[MAX_BUF_SIZE] = {0};
1494 char ret_buf[MAX_BUF_SIZE]={'\0'};
1495
1496 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1497 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1498 band_idx = radio_index_to_band(radio_idx);
1499 if (band_idx < 0) {
1500 break;
1501 }
1502 wifi_BringDownInterfacesForRadio(radio_idx);
1503 }
1504 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1505}
1506
developer8a3bbbf2023-03-15 17:47:23 +08001507static void wifi_vap_status_reset()
1508{
1509 char cmd[MAX_CMD_SIZE] = {0};
1510 char ret_buf[MAX_BUF_SIZE] = {0};
1511 char radio_idx = 0;
1512 char bss_idx = 0;
developer8666b312023-03-24 14:05:31 +08001513
developer8a3bbbf2023-03-15 17:47:23 +08001514 if (access(VAP_STATUS_FILE, F_OK) != 0) {
1515 snprintf(cmd, MAX_CMD_SIZE, "touch %s", VAP_STATUS_FILE);
1516 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1517 } else {
1518 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", VAP_STATUS_FILE);
1519 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1520 }
1521
1522 memset(cmd, 0, MAX_CMD_SIZE);
1523 memset(ret_buf, 0, MAX_BUF_SIZE);
1524
1525 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
1526 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1527 snprintf(cmd, MAX_CMD_SIZE, "echo %s%d=0 >> %s", ext_prefix[radio_idx], bss_idx, VAP_STATUS_FILE);
1528 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1529 }
1530
1531}
developer17038e62023-03-02 14:43:43 +08001532
developer72fb0bb2023-01-11 09:46:29 +08001533// Initializes the wifi subsystem (all radios)
1534INT wifi_init() //RDKB
1535{
developer96b38512023-02-22 11:17:45 +08001536 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1537 //Not intitializing macfilter for Turris-Omnia Platform for now
1538 //macfilter_init();
developer17038e62023-03-02 14:43:43 +08001539 wifi_ParseProfile();
1540 wifi_PrepareDefaultHostapdConfigs();
1541 //system("/usr/sbin/iw reg set US");
1542 system("systemctl start hostapd.service");
1543 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001544
1545 wifi_vap_status_reset();
1546
developer17038e62023-03-02 14:43:43 +08001547 wifi_BringUpInterfaces();
developer96b38512023-02-22 11:17:45 +08001548
developer96b38512023-02-22 11:17:45 +08001549
1550 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001551
1552 return RETURN_OK;
1553}
1554
1555/* wifi_reset() function */
1556/**
1557* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
developer69b61b02023-03-07 17:17:44 +08001558* Implementation specifics may dictate what is actualy reset since
developer72fb0bb2023-01-11 09:46:29 +08001559* different hardware implementations may have different requirements.
1560* Parameters : None
1561*
1562* @return The status of the operation.
1563* @retval RETURN_OK if successful.
1564* @retval RETURN_ERR if any error is detected
1565*
1566* @execution Synchronous.
1567* @sideeffect None.
1568*
1569* @note This function must not suspend and must not invoke any blocking system
1570* calls. It should probably just send a message to a driver event handler task.
1571*
1572*/
1573INT wifi_reset()
1574{
developer17038e62023-03-02 14:43:43 +08001575
1576 wifi_BringDownInterfaces();
1577 sleep(2);
1578
developer96b38512023-02-22 11:17:45 +08001579 //TODO: resets the wifi subsystem, deletes all APs
1580 system("systemctl stop hostapd.service");
1581 sleep(2);
developer17038e62023-03-02 14:43:43 +08001582
developer96b38512023-02-22 11:17:45 +08001583 system("systemctl start hostapd.service");
1584 sleep(5);
developer17038e62023-03-02 14:43:43 +08001585
1586 wifi_PrepareDefaultHostapdConfigs();
1587 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001588
1589 wifi_vap_status_reset();
1590
developer17038e62023-03-02 14:43:43 +08001591 wifi_BringUpInterfaces();
1592
developer72fb0bb2023-01-11 09:46:29 +08001593 return RETURN_OK;
1594}
1595
1596/* wifi_down() function */
1597/**
1598* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
developer69b61b02023-03-07 17:17:44 +08001599* Implementation specifics may dictate some functionality since
developer72fb0bb2023-01-11 09:46:29 +08001600* different hardware implementations may have different requirements.
1601*
1602* @param None
1603*
1604* @return The status of the operation
1605* @retval RETURN_OK if successful
1606* @retval RETURN_ERR if any error is detected
1607*
1608* @execution Synchronous
1609* @sideeffect None
1610*
1611* @note This function must not suspend and must not invoke any blocking system
1612* calls. It should probably just send a message to a driver event handler task.
1613*
1614*/
1615INT wifi_down()
1616{
developer96b38512023-02-22 11:17:45 +08001617 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer17038e62023-03-02 14:43:43 +08001618 wifi_BringDownInterfaces();
1619 sleep(2);
1620
developer96b38512023-02-22 11:17:45 +08001621 system("systemctl stop hostapd.service");
1622 sleep(2);
developer72fb0bb2023-01-11 09:46:29 +08001623 return RETURN_OK;
1624}
1625
1626
1627/* wifi_createInitialConfigFiles() function */
1628/**
1629* @description This function creates wifi configuration files. The format
developer69b61b02023-03-07 17:17:44 +08001630* and content of these files are implementation dependent. This function call is
1631* used to trigger this task if necessary. Some implementations may not need this
1632* function. If an implementation does not need to create config files the function call can
developer72fb0bb2023-01-11 09:46:29 +08001633* do nothing and return RETURN_OK.
1634*
1635* @param None
1636*
1637* @return The status of the operation
1638* @retval RETURN_OK if successful
1639* @retval RETURN_ERR if any error is detected
1640*
1641* @execution Synchronous
1642* @sideeffect None
1643*
1644* @note This function must not suspend and must not invoke any blocking system
1645* calls. It should probably just send a message to a driver event handler task.
1646*
1647*/
1648INT wifi_createInitialConfigFiles()
1649{
1650 //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)
1651 return RETURN_OK;
1652}
1653
developer7e4a2a62023-04-06 19:56:03 +08001654/* outputs the country code to a max 64 character string */
developer72fb0bb2023-01-11 09:46:29 +08001655INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1656{
developer7e4a2a62023-04-06 19:56:03 +08001657 char interface_name[IF_NAME_SIZE] = {0};
1658 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer72fb0bb2023-01-11 09:46:29 +08001659
developer7e4a2a62023-04-06 19:56:03 +08001660 if (!output_string || (radioIndex >= MAX_NUM_RADIOS)) {
1661 printf("%s: input para error!!!\n", __func__);
1662 return RETURN_ERR;
1663 }
developer72fb0bb2023-01-11 09:46:29 +08001664
developer7e4a2a62023-04-06 19:56:03 +08001665 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK) {
1666 printf("%s: get inf_name error!!!\n", __func__);
1667 return RETURN_ERR;
1668 }
1669
1670 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i %s status driver | grep country | cut -d '=' -f2 | tr -d '\\n'",
1671 interface_name);
1672 _syscmd(cmd, buf, sizeof(buf));
1673
1674 if(strlen(buf))
1675 snprintf(output_string, 64, "%s", buf);
1676 else
1677 return RETURN_ERR;
1678
1679 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001680}
1681
1682INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1683{
developer7e4a2a62023-04-06 19:56:03 +08001684 /*Set wifi config. Wait for wifi reset to apply*/
1685 char str[MAX_BUF_SIZE] = {0};
1686 char cmd[MAX_CMD_SIZE] = {0};
1687 struct params params;
1688 char config_file[MAX_BUF_SIZE] = {0};
1689 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08001690
developer7e4a2a62023-04-06 19:56:03 +08001691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001692
developer7e4a2a62023-04-06 19:56:03 +08001693 if(NULL == CountryCode || strlen(CountryCode) >= 32 ) {
1694 printf("%s: input para error!!!\n", __func__);
1695 return RETURN_ERR;
1696 }
developer72fb0bb2023-01-11 09:46:29 +08001697
developer7e4a2a62023-04-06 19:56:03 +08001698 if (!strlen(CountryCode))
1699 strncpy(CountryCode, "US", sizeof("US")); /*default set the code to US*/
developer72fb0bb2023-01-11 09:46:29 +08001700
developer7e4a2a62023-04-06 19:56:03 +08001701 params.name = "country_code";
1702 params.value = CountryCode;
developer72fb0bb2023-01-11 09:46:29 +08001703
developer7e4a2a62023-04-06 19:56:03 +08001704 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1705 ret = wifi_hostapdWrite(config_file, &params, 1);
1706
1707 if (ret) {
1708 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n",
1709 __func__, ret);
1710 }
1711
1712 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1713
1714 if (ret) {
1715 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n",
1716 __func__, ret);
1717 }
1718
1719 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1720
1721 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001722}
1723
1724INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1725{
1726 char interface_name[16] = {0};
1727 char channel_util_file[64] = {0};
1728 char cmd[128] = {0};
1729 char buf[128] = {0};
1730 char line[128] = {0};
1731 char *param = NULL, *value = NULL;
1732 int read = 0;
1733 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1734 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1735 size_t len = 0;
1736 FILE *f = NULL;
1737
1738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1739
1740 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1741 return RETURN_ERR;
1742 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
1743 _syscmd(cmd, buf, sizeof(buf));
1744 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1745
1746 memset(cmd, 0, sizeof(cmd));
1747 memset(buf, 0, sizeof(buf));
1748 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
1749 if ((f = popen(cmd, "r")) == NULL) {
1750 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1751 return RETURN_ERR;
1752 }
1753
1754 read = getline(&line, &len, f);
1755 while (read != -1) {
1756 param = strtok(line, ":\t");
1757 value = strtok(NULL, " ");
1758 if(strstr(param, "frequency") != NULL) {
1759 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1760 }
1761 if(strstr(param, "noise") != NULL) {
1762 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1763 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1764 }
1765 if(strstr(param, "channel active time") != NULL) {
1766 ActiveTime = strtol(value, NULL, 10);
1767 }
1768 if(strstr(param, "channel busy time") != NULL) {
1769 BusyTime = strtol(value, NULL, 10);
1770 }
1771 if(strstr(param, "channel transmit time") != NULL) {
1772 TransmitTime = strtol(value, NULL, 10);
1773 }
1774 read = getline(&line, &len, f);
1775 }
1776 pclose(f);
1777
1778 // The file should store the last active, busy and transmit time
1779 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1780 f = fopen(channel_util_file, "r");
1781 if (f != NULL) {
1782 read = getline(&line, &len, f);
1783 preActiveTime = strtol(line, NULL, 10);
1784 read = getline(&line, &len, f);
1785 preBusyTime = strtol(line, NULL, 10);
1786 read = getline(&line, &len, f);
1787 preTransmitTime = strtol(line, NULL, 10);
1788 fclose(f);
1789 }
1790
1791 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1792 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1793
1794 f = fopen(channel_util_file, "w");
1795 if (f != NULL) {
1796 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1797 fclose(f);
1798 }
1799 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1800 return RETURN_OK;
1801}
1802
1803/**********************************************************************************
1804 *
1805 * Wifi radio level function prototypes
1806 *
1807**********************************************************************************/
1808
1809//Get the total number of radios in this wifi subsystem
1810INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1811{
1812 if (NULL == output)
1813 return RETURN_ERR;
1814 *output = MAX_NUM_RADIOS;
1815
1816 return RETURN_OK;
1817}
1818
developer69b61b02023-03-07 17:17:44 +08001819//Get the total number of SSID entries in this wifi subsystem
developer72fb0bb2023-01-11 09:46:29 +08001820INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1821{
1822 if (NULL == output)
1823 return RETURN_ERR;
1824 *output = MAX_APS;
1825
1826 return RETURN_OK;
1827}
1828
1829//Get the Radio enable config parameter
1830INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1831{
1832 char interface_name[16] = {0};
1833 char buf[128] = {0}, cmd[128] = {0};
1834
1835 if (NULL == output_bool)
1836 return RETURN_ERR;
1837
1838 *output_bool = FALSE;
1839 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
1840 return RETURN_ERR;
1841
1842 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1843 return RETURN_ERR;
1844 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1845 _syscmd(cmd, buf, sizeof(buf));
1846
1847 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1848 *output_bool = TRUE;
1849 return RETURN_OK;
1850}
1851
developere82c0ca2023-05-10 16:25:35 +08001852typedef long time_t;
1853static time_t radio_up_time[MAX_NUM_RADIOS];
1854
developer72fb0bb2023-01-11 09:46:29 +08001855INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1856{
1857 char interface_name[16] = {0};
1858 char cmd[MAX_CMD_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001859 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001860 int apIndex, ret;
developer69b61b02023-03-07 17:17:44 +08001861 int max_radio_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08001862 int phyId = 0;
1863
1864 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1865
1866 phyId = radio_index_to_phy(radioIndex);
1867
1868 wifi_getMaxRadioNumber(&max_radio_num);
1869
developer8a3bbbf2023-03-15 17:47:23 +08001870 if(enable == FALSE) {
developere82c0ca2023-05-10 16:25:35 +08001871 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radioIndex]);
developer8a3bbbf2023-03-15 17:47:23 +08001872 _syscmd(cmd, buf, sizeof(buf));
developere82c0ca2023-05-10 16:25:35 +08001873 if(strncmp(buf, "OK", 2))
1874 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08001875 } else {
developere82c0ca2023-05-10 16:25:35 +08001876 for (apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
developer72fb0bb2023-01-11 09:46:29 +08001877 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1878 return RETURN_ERR;
1879
developer8a3bbbf2023-03-15 17:47:23 +08001880 memset(cmd, 0, MAX_CMD_SIZE);
1881 memset(buf, 0, MAX_BUF_SIZE);
1882
developer72fb0bb2023-01-11 09:46:29 +08001883 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
1884 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08001885
1886 if(*buf == '1') {
1887
1888 memset(cmd, 0, MAX_CMD_SIZE);
1889 memset(buf, 0, MAX_BUF_SIZE);
1890
developer72fb0bb2023-01-11 09:46:29 +08001891 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1892 phyId, apIndex);
1893 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08001894
developer72fb0bb2023-01-11 09:46:29 +08001895 }
1896 }
developere82c0ca2023-05-10 16:25:35 +08001897 time(&radio_up_time[radioIndex]);
developer72fb0bb2023-01-11 09:46:29 +08001898 }
1899
1900 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1901 return RETURN_OK;
1902}
1903
1904//Get the Radio enable status
1905INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1906{
1907 if (NULL == output_bool)
1908 return RETURN_ERR;
1909
1910 return wifi_getRadioEnable(radioIndex, output_bool);
1911}
1912
1913//Get the Radio Interface name from platform, eg "wlan0"
1914INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1915{
1916 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
1917 return RETURN_ERR;
1918 return wifi_GetInterfaceName(radioIndex, output_string);
1919}
1920
1921//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1922//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.
1923INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1924{
1925 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1926 // For max bit rate, we should always choose the best MCS
1927 char mode[64] = {0};
1928 char channel_bandwidth_str[64] = {0};
1929 char *tmp = NULL;
1930 UINT mode_map = 0;
1931 UINT num_subcarrier = 0;
1932 UINT code_bits = 0;
1933 float code_rate = 0; // use max code rate
1934 int NSS = 0;
1935 UINT Symbol_duration = 0;
developer69b61b02023-03-07 17:17:44 +08001936 UINT GI_duration = 0;
developer72fb0bb2023-01-11 09:46:29 +08001937 wifi_band band = band_invalid;
1938 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1939 BOOL enable = FALSE;
1940 float bit_rate = 0;
developera1255e42023-05-13 17:45:02 +08001941 int ant_bitmap = 0;
developer72fb0bb2023-01-11 09:46:29 +08001942
1943 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1944 if (NULL == output_string)
1945 return RETURN_ERR;
1946
1947 wifi_getRadioEnable(radioIndex, &enable);
1948 if (enable == FALSE) {
1949 snprintf(output_string, 64, "0 Mb/s");
1950 return RETURN_OK;
1951 }
1952
1953 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1954 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1955 return RETURN_ERR;
1956 }
1957
1958 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1959 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1960 return RETURN_ERR;
1961 }
1962
1963 if (gi == wifi_guard_interval_3200)
1964 GI_duration = 32;
1965 else if (gi == wifi_guard_interval_1600)
1966 GI_duration = 16;
1967 else if (gi == wifi_guard_interval_800)
1968 GI_duration = 8;
1969 else // auto, 400
1970 GI_duration = 4;
1971
1972 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1973 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1974 return RETURN_ERR;
1975 }
1976
1977 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1978 strcpy(channel_bandwidth_str, "160");
1979
1980 if (mode_map & WIFI_MODE_AX) {
1981 if (strstr(channel_bandwidth_str, "160") != NULL)
1982 num_subcarrier = 1960;
1983 else if (strstr(channel_bandwidth_str, "80") != NULL)
1984 num_subcarrier = 980;
1985 else if (strstr(channel_bandwidth_str, "40") != NULL)
1986 num_subcarrier = 468;
1987 else if (strstr(channel_bandwidth_str, "20") != NULL)
1988 num_subcarrier = 234;
1989 code_bits = 10;
1990 code_rate = (float)5/6;
1991 Symbol_duration = 128;
developera1255e42023-05-13 17:45:02 +08001992 GI_duration = 8;/*HE no GI 400ns*/
developer72fb0bb2023-01-11 09:46:29 +08001993 } else if (mode_map & WIFI_MODE_AC) {
1994 if (strstr(channel_bandwidth_str, "160") != NULL)
1995 num_subcarrier = 468;
1996 else if (strstr(channel_bandwidth_str, "80") != NULL)
1997 num_subcarrier = 234;
1998 else if (strstr(channel_bandwidth_str, "40") != NULL)
1999 num_subcarrier = 108;
2000 else if (strstr(channel_bandwidth_str, "20") != NULL)
2001 num_subcarrier = 52;
2002 code_bits = 8;
2003 code_rate = (float)5/6;
2004 Symbol_duration = 32;
2005 } else if (mode_map & WIFI_MODE_N) {
2006 if (strstr(channel_bandwidth_str, "160") != NULL)
2007 num_subcarrier = 468;
2008 else if (strstr(channel_bandwidth_str, "80") != NULL)
2009 num_subcarrier = 234;
2010 else if (strstr(channel_bandwidth_str, "40") != NULL)
2011 num_subcarrier = 108;
2012 else if (strstr(channel_bandwidth_str, "20") != NULL)
2013 num_subcarrier = 52;
2014 code_bits = 6;
2015 code_rate = (float)3/4;
2016 Symbol_duration = 32;
2017 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
2018 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
2019 snprintf(output_string, 64, "65 Mb/s");
2020 return RETURN_OK;
2021 } else {
2022 snprintf(output_string, 64, "0 Mb/s");
2023 return RETURN_OK;
2024 }
2025
2026 // Spatial streams
developera1255e42023-05-13 17:45:02 +08002027 if (wifi_getRadioTxChainMask(radioIndex, &ant_bitmap) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +08002028 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
2029 return RETURN_ERR;
2030 }
developera1255e42023-05-13 17:45:02 +08002031 for (; ant_bitmap > 0; ant_bitmap >>= 1)
2032 NSS += ant_bitmap & 1;
developer72fb0bb2023-01-11 09:46:29 +08002033
2034 // multiple 10 is to align duration unit (0.1 us)
2035 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
2036 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
developera1255e42023-05-13 17:45:02 +08002037 WIFI_ENTRY_EXIT_DEBUG("%s:num_subcarrier=%d, code_bits=%d, code_rate=%.3f, nss=%d, symbol time=%u, %.1f Mb/s\n",
2038 __func__, num_subcarrier, code_bits, code_rate, NSS, Symbol_duration + GI_duration, bit_rate);
developer72fb0bb2023-01-11 09:46:29 +08002039 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2040
2041 return RETURN_OK;
2042}
2043#if 0
2044INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2045{
2046 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2047 char cmd[64];
2048 char buf[1024];
2049 int apIndex;
2050
developer69b61b02023-03-07 17:17:44 +08002051 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002052 return RETURN_ERR;
2053
2054 apIndex=(radioIndex==0)?0:1;
2055
2056 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
2057 _syscmd(cmd,buf, sizeof(buf));
2058
2059 snprintf(output_string, 64, "%s", buf);
2060 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2061 return RETURN_OK;
2062}
2063#endif
2064
2065
2066//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
2067//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.
2068INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
2069{
2070 wifi_band band = band_invalid;
2071
2072 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2073 if (NULL == output_string)
2074 return RETURN_ERR;
2075
2076 band = wifi_index_to_band(radioIndex);
2077
2078 memset(output_string, 0, 10);
2079 if (band == band_2_4)
2080 strcpy(output_string, "2.4GHz");
2081 else if (band == band_5)
2082 strcpy(output_string, "5GHz");
2083 else if (band == band_6)
2084 strcpy(output_string, "6GHz");
2085 else
2086 return RETURN_ERR;
2087 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2088
2089 return RETURN_OK;
2090#if 0
2091 char buf[MAX_BUF_SIZE]={'\0'};
2092 char str[MAX_BUF_SIZE]={'\0'};
2093 char cmd[MAX_CMD_SIZE]={'\0'};
2094 char *ch=NULL;
2095 char *ch2=NULL;
2096
2097 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2098 if (NULL == output_string)
2099 return RETURN_ERR;
2100
2101
2102 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2103
2104 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2105 {
2106 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2107 return RETURN_ERR;
2108 }
2109 ch=strchr(buf,'\n');
2110 *ch='\0';
2111 ch=strchr(buf,'=');
2112 if(ch==NULL)
2113 return RETURN_ERR;
2114
2115
2116 ch++;
2117
2118 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
2119 strcpy(buf,"0");
2120 if(strlen(ch) == 1)
2121 ch=strcat(buf,ch);
2122
2123
2124 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2125
2126 if(_syscmd(cmd,str,64) == RETURN_ERR)
2127 {
2128 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2129 return RETURN_ERR;
2130 }
2131
2132
2133 ch2=strchr(str,'\n');
2134 //replace \n with \0
2135 *ch2='\0';
2136 ch2=strchr(str,'=');
2137 if(ch2==NULL)
2138 {
2139 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2140 return RETURN_ERR;
2141 }
2142 else
2143 wifi_dbg_printf("%s",ch2+1);
2144
2145
2146 ch2++;
2147
2148
2149 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
2150
2151 memset(buf,'\0',sizeof(buf));
2152 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2153 {
2154 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2155 return RETURN_ERR;
2156 }
2157 if (strstr(buf,"2.4") != NULL )
2158 strcpy(output_string,"2.4GHz");
2159 else if(strstr(buf,"5.") != NULL )
2160 strcpy(output_string,"5GHz");
2161 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2162
2163 return RETURN_OK;
2164#endif
2165}
2166
2167//Get the frequency band at which the radio is operating, eg: "2.4GHz"
2168//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.
2169INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
2170{
2171 wifi_band band = band_invalid;
2172 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2173 if (NULL == output_string)
2174 return RETURN_ERR;
2175 band = wifi_index_to_band(radioIndex);
2176
developer69b61b02023-03-07 17:17:44 +08002177 if (band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08002178 snprintf(output_string, 64, "2.4GHz");
2179 else if (band == band_5)
developer69b61b02023-03-07 17:17:44 +08002180 snprintf(output_string, 64, "5GHz");
developer72fb0bb2023-01-11 09:46:29 +08002181 else if (band == band_6)
2182 snprintf(output_string, 64, "6GHz");
2183
2184 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2185
2186 return RETURN_OK;
2187#if 0
2188 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2189 char buf[MAX_BUF_SIZE]={'\0'};
2190 char str[MAX_BUF_SIZE]={'\0'};
2191 char cmd[MAX_CMD_SIZE]={'\0'};
2192 char *ch=NULL;
2193 char *ch2=NULL;
2194 char ch1[5]="0";
2195
2196 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2197
2198 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2199 {
2200 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2201 return RETURN_ERR;
2202 }
2203
2204 ch=strchr(buf,'\n');
2205 *ch='\0';
2206 ch=strchr(buf,'=');
2207 if(ch==NULL)
2208 return RETURN_ERR;
2209 ch++;
2210
2211 if(strlen(ch)==1)
2212 {
2213 strcat(ch1,ch);
2214
2215 }
2216 else
2217 {
2218 strcpy(ch1,ch);
2219 }
2220
2221
2222
2223 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2224 if(_syscmd(cmd,str,64) == RETURN_ERR)
2225 {
2226 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2227 return RETURN_ERR;
2228 }
2229
2230
2231 ch2=strchr(str,'\n');
2232 //replace \n with \0
2233 *ch2='\0';
2234 ch2=strchr(str,'=');
2235 if(ch2==NULL)
2236 {
2237 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2238 return RETURN_ERR;
2239 }
2240 else
2241 wifi_dbg_printf("%s",ch2+1);
2242 ch2++;
2243
2244
2245 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
2246 memset(buf,'\0',sizeof(buf));
2247 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2248 {
2249 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2250 return RETURN_ERR;
2251 }
2252
2253
2254 if(strstr(buf,"2.4")!=NULL)
2255 {
2256 strcpy(output_string,"2.4GHz");
2257 }
2258 if(strstr(buf,"5.")!=NULL)
2259 {
2260 strcpy(output_string,"5GHz");
2261 }
2262 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2263 return RETURN_OK;
2264#endif
2265}
2266
2267//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
2268//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.
2269INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
2270{
2271 char cmd[128]={0};
2272 char buf[128]={0};
2273 char temp_output[128] = {0};
2274 wifi_band band;
2275 int phyId = 0;
2276
2277 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002278 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002279 return RETURN_ERR;
2280
2281 band = wifi_index_to_band(radioIndex);
2282 if (band == band_2_4) {
2283 strcat(temp_output, "b,g,");
2284 } else if (band == band_5) {
2285 strcat(temp_output, "a,");
2286 }
2287 phyId = radio_index_to_phy(radioIndex);
2288 // ht capabilities
2289 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);
2290 _syscmd(cmd, buf, sizeof(buf));
2291 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
2292 strcat(temp_output, "n,");
2293 }
2294
2295 // vht capabilities
2296 if (band == band_5) {
2297 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
2298 _syscmd(cmd, buf, sizeof(buf));
2299 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
2300 strcat(temp_output, "ac,");
2301 }
2302 }
2303
2304 // he capabilities
2305 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);
2306 _syscmd(cmd, buf, sizeof(buf));
2307 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2308 strcat(temp_output, "ax,");
2309 }
2310
developere82c0ca2023-05-10 16:25:35 +08002311 // eht capabilities
2312 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);
2313 _syscmd(cmd, buf, sizeof(buf));
2314 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2315 strcat(temp_output, "be,");
2316 }
2317
developer72fb0bb2023-01-11 09:46:29 +08002318 // Remove the last comma
2319 if (strlen(temp_output) != 0)
2320 temp_output[strlen(temp_output)-1] = '\0';
2321 strncpy(output_string, temp_output, strlen(temp_output));
2322 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2323 return RETURN_OK;
2324}
2325
2326//Get the radio operating mode, and pure mode flag. eg: "ac"
2327//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.
2328INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
2329{
2330 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2331 if (NULL == output_string)
2332 return RETURN_ERR;
2333
2334 if (radioIndex == 0) {
2335 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
2336 *gOnly = FALSE;
2337 *nOnly = TRUE;
2338 *acOnly = FALSE;
2339 } else {
2340 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
2341 *gOnly = FALSE;
2342 *nOnly = FALSE;
2343 *acOnly = FALSE;
2344 }
2345 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2346
2347 return RETURN_OK;
2348#if 0
2349 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2350 char buf[64] = {0};
2351 char config_file[MAX_BUF_SIZE] = {0};
2352
developer69b61b02023-03-07 17:17:44 +08002353 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
developer72fb0bb2023-01-11 09:46:29 +08002354 return RETURN_ERR;
2355
2356 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2357 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
2358
2359 wifi_dbg_printf("\nhw_mode=%s\n",buf);
developer69b61b02023-03-07 17:17:44 +08002360 if (strlen(buf) == 0)
developer72fb0bb2023-01-11 09:46:29 +08002361 {
2362 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
2363 return RETURN_ERR;
2364 }
2365 if(strcmp(buf,"g")==0)
2366 {
2367 wifi_dbg_printf("\nG\n");
2368 *gOnly=TRUE;
2369 *nOnly=FALSE;
2370 *acOnly=FALSE;
2371 }
2372 else if(strcmp(buf,"n")==0)
2373 {
2374 wifi_dbg_printf("\nN\n");
2375 *gOnly=FALSE;
2376 *nOnly=TRUE;
2377 *acOnly=FALSE;
2378 }
2379 else if(strcmp(buf,"ac")==0)
2380 {
2381 wifi_dbg_printf("\nac\n");
2382 *gOnly=FALSE;
2383 *nOnly=FALSE;
2384 *acOnly=TRUE;
2385 }
2386 /* hostapd-5G.conf has "a" as hw_mode */
2387 else if(strcmp(buf,"a")==0)
2388 {
2389 wifi_dbg_printf("\na\n");
2390 *gOnly=FALSE;
2391 *nOnly=FALSE;
2392 *acOnly=FALSE;
2393 }
2394 else
2395 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
2396
2397 //for a,n mode
2398 if(radioIndex == 1)
2399 {
2400 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
2401 if(strcmp(buf,"1")==0)
2402 {
2403 strncpy(output_string, "n", 1);
2404 *nOnly=FALSE;
2405 }
2406 }
2407
2408 wifi_dbg_printf("\nReturning from getRadioStandard\n");
2409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2410 return RETURN_OK;
2411#endif
2412}
2413
2414INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
2415{
2416 char cmd[128] = {0};
2417 char buf[64] = {0};
2418 char config_file[64] = {0};
2419 wifi_band band;
2420
2421 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2422 if(NULL == output_string || NULL == pureMode)
2423 return RETURN_ERR;
2424
2425 // grep all of the ieee80211 protocol config set to 1
2426 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developera1255e42023-05-13 17:45:02 +08002427 //snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
2428 /*tr -d 'ieee80211' return unexpected result, if object is ieee80211be*/
2429 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | sed 's/ieee80211//g", config_file);
developer72fb0bb2023-01-11 09:46:29 +08002430 _syscmd(cmd, buf, sizeof(buf));
2431
2432 band = wifi_index_to_band(radioIndex);
2433 // puremode is a bit map
2434 *pureMode = 0;
2435 if (band == band_2_4) {
2436 strcat(output_string, "b,g");
2437 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
2438 if (strstr(buf, "n") != NULL) {
2439 strcat(output_string, ",n");
2440 *pureMode |= WIFI_MODE_N;
2441 }
2442 if (strstr(buf, "ax") != NULL) {
2443 strcat(output_string, ",ax");
2444 *pureMode |= WIFI_MODE_AX;
2445 }
developera1255e42023-05-13 17:45:02 +08002446 if (strstr(buf, "be") != NULL) {
2447 strcat(output_string, ",be");
2448 *pureMode |= WIFI_MODE_BE;
2449 }
developer72fb0bb2023-01-11 09:46:29 +08002450 } else if (band == band_5) {
2451 strcat(output_string, "a");
2452 *pureMode |= WIFI_MODE_A;
2453 if (strstr(buf, "n") != NULL) {
2454 strcat(output_string, ",n");
2455 *pureMode |= WIFI_MODE_N;
2456 }
2457 if (strstr(buf, "ac") != NULL) {
2458 strcat(output_string, ",ac");
2459 *pureMode |= WIFI_MODE_AC;
2460 }
2461 if (strstr(buf, "ax") != NULL) {
2462 strcat(output_string, ",ax");
2463 *pureMode |= WIFI_MODE_AX;
2464 }
developera1255e42023-05-13 17:45:02 +08002465 if (strstr(buf, "be") != NULL) {
2466 strcat(output_string, ",be");
2467 *pureMode |= WIFI_MODE_BE;
2468 }
developer72fb0bb2023-01-11 09:46:29 +08002469 } else if (band == band_6) {
2470 if (strstr(buf, "ax") != NULL) {
2471 strcat(output_string, "ax");
2472 *pureMode |= WIFI_MODE_AX;
2473 }
developera1255e42023-05-13 17:45:02 +08002474 if (strstr(buf, "be") != NULL) {
2475 strcat(output_string, ",be");
2476 *pureMode |= WIFI_MODE_BE;
2477 }
developer72fb0bb2023-01-11 09:46:29 +08002478 }
2479
2480 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2481 return RETURN_OK;
2482}
2483
2484// Set the radio operating mode, and pure mode flag.
2485INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2486{
developer69b61b02023-03-07 17:17:44 +08002487 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002488 if (strcmp (channelMode,"11A") == 0)
2489 {
2490 writeBandWidth(radioIndex,"20MHz");
2491 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2492 printf("\nChannel Mode is 802.11a (5GHz)\n");
2493 }
2494 else if (strcmp (channelMode,"11NAHT20") == 0)
2495 {
2496 writeBandWidth(radioIndex,"20MHz");
2497 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2498 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2499 }
2500 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2501 {
2502 writeBandWidth(radioIndex,"40MHz");
2503 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2504 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2505 }
2506 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2507 {
2508 writeBandWidth(radioIndex,"40MHz");
2509 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2510 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2511 }
2512 else if (strcmp (channelMode,"11ACVHT20") == 0)
2513 {
2514 writeBandWidth(radioIndex,"20MHz");
2515 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2516 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2517 }
2518 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2519 {
2520 writeBandWidth(radioIndex,"40MHz");
2521 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2522 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2523 }
2524 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2525 {
2526 writeBandWidth(radioIndex,"40MHz");
2527 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2528 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2529 }
2530 else if (strcmp (channelMode,"11ACVHT80") == 0)
2531 {
2532 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2533 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2534 }
2535 else if (strcmp (channelMode,"11ACVHT160") == 0)
2536 {
2537 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2538 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
developer69b61b02023-03-07 17:17:44 +08002539 }
developer72fb0bb2023-01-11 09:46:29 +08002540 else if (strcmp (channelMode,"11B") == 0)
2541 {
2542 writeBandWidth(radioIndex,"20MHz");
2543 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2544 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2545 }
2546 else if (strcmp (channelMode,"11G") == 0)
2547 {
2548 writeBandWidth(radioIndex,"20MHz");
2549 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2550 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2551 }
2552 else if (strcmp (channelMode,"11NGHT20") == 0)
2553 {
2554 writeBandWidth(radioIndex,"20MHz");
2555 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2556 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2557 }
2558 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2559 {
2560 writeBandWidth(radioIndex,"40MHz");
2561 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2562 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2563 }
2564 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2565 {
2566 writeBandWidth(radioIndex,"40MHz");
2567 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2568 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2569 }
developer69b61b02023-03-07 17:17:44 +08002570 else
developer72fb0bb2023-01-11 09:46:29 +08002571 {
2572 return RETURN_ERR;
2573 }
2574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2575
2576 return RETURN_OK;
2577}
2578
2579// Set the radio operating mode, and pure mode flag.
2580INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2581{
2582 int num_hostapd_support_mode = 3; // n, ac, ax
2583 struct params list[num_hostapd_support_mode];
2584 char config_file[64] = {0};
2585 char bandwidth[16] = {0};
2586 int mode_check_bit = 1 << 3; // n mode
developer69b61b02023-03-07 17:17:44 +08002587
developer72fb0bb2023-01-11 09:46:29 +08002588
2589 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2590 // Set radio mode
2591 list[0].name = "ieee80211n";
2592 list[1].name = "ieee80211ac";
2593 list[2].name = "ieee80211ax";
2594 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2595
2596 // check the bit map from n to ax, and set hostapd config
2597 if (pureMode & WIFI_MODE_N)
2598 list[0].value = "1";
2599 else
2600 list[0].value = "0";
2601 if (pureMode & WIFI_MODE_AC)
2602 list[1].value = "1";
2603 else
2604 list[1].value = "0";
2605 if (pureMode & WIFI_MODE_AX)
2606 list[2].value = "1";
2607 else
2608 list[2].value = "0";
2609 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2610
2611 if (channelMode == NULL || strlen(channelMode) == 0)
2612 return RETURN_OK;
2613 // Set bandwidth
2614 if (strstr(channelMode, "40") != NULL)
2615 strcpy(bandwidth, "40MHz");
2616 else if (strstr(channelMode, "80") != NULL)
2617 strcpy(bandwidth, "80MHz");
2618 else if (strstr(channelMode, "160") != NULL)
2619 strcpy(bandwidth, "160MHz");
2620 else // 11A, 11B, 11G....
2621 strcpy(bandwidth, "20MHz");
2622
2623 writeBandWidth(radioIndex, bandwidth);
2624 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2625
2626 wifi_reloadAp(radioIndex);
2627 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2628
2629 return RETURN_OK;
2630}
2631
2632INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2633
2634 char config_file[64] = {0};
2635 char buf[64] = {0};
2636 struct params params = {0};
2637 wifi_band band = band_invalid;
2638
2639 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2640
2641 band = wifi_index_to_band(radioIndex);
2642
2643 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
2644 return RETURN_ERR;
2645 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2646 return RETURN_ERR;
2647 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2648 return RETURN_ERR;
2649
2650 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2651 params.name = "hw_mode";
2652 params.value = hw_mode;
2653 wifi_hostapdWrite(config_file, &params, 1);
2654 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2655
2656 if (band == band_2_4) {
2657 if (strncmp(hw_mode, "b", 1) == 0) {
2658 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2659 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2660 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2661 snprintf(buf, sizeof(buf), "%s", "1,2");
2662 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2663 } else {
2664 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2665
2666 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2667 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2668 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2669 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2670 }
2671 }
2672
2673 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2674 return RETURN_OK;
2675}
2676
2677INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2678{
2679 char config_file[64] = {0};
2680 struct params params = {0};
2681 wifi_band band = band_invalid;
2682
2683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2684
2685 band = wifi_index_to_band(radioIndex);
2686 if (band != band_2_4)
2687 return RETURN_OK;
2688
2689 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2690 params.name = "noscan";
2691 params.value = noscan;
2692 wifi_hostapdWrite(config_file, &params, 1);
2693 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2694
2695 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2696 return RETURN_OK;
2697}
2698
2699//Get the list of supported channel. eg: "1-11"
2700//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.
2701INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2702{
2703 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002704 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002705 return RETURN_ERR;
2706 char cmd[256] = {0};
2707 char buf[128] = {0};
2708 BOOL dfs_enable = false;
2709 int phyId = 0;
2710
2711 // Parse possible channel number and separate them with commas.
2712 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2713 phyId = radio_index_to_phy(radioIndex);
2714 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
2715 if (dfs_enable)
2716 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);
developer69b61b02023-03-07 17:17:44 +08002717 else
developer72fb0bb2023-01-11 09:46:29 +08002718 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);
2719
2720 _syscmd(cmd,buf,sizeof(buf));
2721 strncpy(output_string, buf, sizeof(buf));
2722
2723 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2724 return RETURN_OK;
2725}
developer4903e3f2023-05-15 10:04:40 +08002726//Getting current radio extension channel
2727INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2728{
2729 CHAR buf[150] = {0};
2730 CHAR cmd[150] = {0};
2731 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2732 _syscmd(cmd, buf, sizeof(buf));
2733 if(NULL != strstr(buf,"HT40+"))
2734 strcpy(Value,"AboveControlChannel");
2735 else if(NULL != strstr(buf,"HT40-"))
2736 strcpy(Value,"BelowControlChannel");
2737 return RETURN_OK;
2738}
developer72fb0bb2023-01-11 09:46:29 +08002739//Get the list for used channel. eg: "1,6,9,11"
2740//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.
2741INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2742{
2743 char interface_name[16] = {0};
2744 char cmd[128] = {0};
2745 char buf[128] = {0};
2746 char config_file[64] = {0};
2747 int channel = 0;
2748 int freq = 0;
2749 int bandwidth = 0;
2750 int center_freq = 0;
2751 int center_channel = 0;
2752 int channel_delta = 0;
2753 wifi_band band = band_invalid;
2754
2755 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2756
2757 if (NULL == output_string)
2758 return RETURN_ERR;
2759
2760 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2761 return RETURN_ERR;
2762 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
2763 _syscmd(cmd, buf, sizeof(buf));
2764 if (strlen(buf) == 0) {
2765 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2766 return RETURN_ERR;
2767 }
2768 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2769
2770 if (bandwidth == 20) {
2771 snprintf(output_string, 256, "%d", channel);
2772 return RETURN_OK;
2773 }
2774
2775 center_channel = ieee80211_frequency_to_channel(center_freq);
2776
2777 band = wifi_index_to_band(radioIndex);
2778 if (band == band_2_4 && bandwidth == 40) {
2779 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2780 memset(buf, 0, sizeof(buf));
2781 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2782
2783 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
2784 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2785 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
2786 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2787 } else {
2788 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2789 return RETURN_ERR;
2790 }
2791 } else if (band == band_5 || band == band_6){
2792 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
developer40ba1762023-05-13 11:03:49 +08002793 // example: bandwidth 80: center is 42 (5210), channels are "36,40,44,48" (5170-5250). The delta should be 6.
developer72fb0bb2023-01-11 09:46:29 +08002794 channel_delta = (bandwidth-20)/10;
developer40ba1762023-05-13 11:03:49 +08002795 memset(output_string, 0, 256);
2796 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2797 // If i is not the last channel, we add a comma.
2798 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2799 strncat(output_string, buf, strlen(buf));
2800 }
developer72fb0bb2023-01-11 09:46:29 +08002801 } else
2802 return RETURN_ERR;
2803
2804 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2805 return RETURN_OK;
2806}
2807
developer69b61b02023-03-07 17:17:44 +08002808//Get the running channel number
developer72fb0bb2023-01-11 09:46:29 +08002809INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2810{
2811 char channel_str[16] = {0};
2812 char config_file[128] = {0};
2813
2814 if (output_ulong == NULL)
2815 return RETURN_ERR;
2816
2817 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2818 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
2819
2820 *output_ulong = strtoul(channel_str, NULL, 10);
2821
2822 return RETURN_OK;
2823}
2824
2825
2826INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2827{
2828 char cmd[1024] = {0}, buf[5] = {0};
2829 char interface_name[16] = {0};
2830
2831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2832 if (NULL == output_ulong)
2833 return RETURN_ERR;
2834
2835 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2836 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2837 return RETURN_ERR;
2838 _syscmd(cmd,buf,sizeof(buf));
2839 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2840 if (*output_ulong == 0) {
2841 return RETURN_ERR;
2842 }
2843
2844 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2845 return RETURN_OK;
2846}
2847
2848//Storing the previous channel value
2849INT wifi_storeprevchanval(INT radioIndex)
2850{
2851 char buf[256] = {0};
2852 char output[4]={'\0'};
2853 char config_file[MAX_BUF_SIZE] = {0};
2854 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2855 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2856 if(radioIndex == 0)
2857 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2858 else if(radioIndex == 1)
2859 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2860 system(buf);
2861 Radio_flag = FALSE;
2862 return RETURN_OK;
2863}
2864
2865//Set the running channel number
2866INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2867{
2868 // We only write hostapd config here
2869 char str_channel[8]={0};
2870 char *list_channel;
2871 char config_file[128] = {0};
2872 char possible_channels[256] = {0};
developer4903e3f2023-05-15 10:04:40 +08002873 char config_file_dat[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002874 int max_radio_num = 0;
2875 struct params list = {0};
developer4903e3f2023-05-15 10:04:40 +08002876 struct params dat = {0};
developer72fb0bb2023-01-11 09:46:29 +08002877
2878 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2879
2880 // Check valid
2881 sprintf(str_channel, "%lu", channel);
2882
2883 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2884 list_channel = strtok(possible_channels, ",");
2885 while(true)
2886 {
2887 if(list_channel == NULL) { // input not in the list
2888 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2889 return RETURN_ERR;
2890 }
2891 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2892 break;
2893 list_channel = strtok(NULL, ",");
2894 }
developer72fb0bb2023-01-11 09:46:29 +08002895 list.name = "channel";
2896 list.value = str_channel;
developer4903e3f2023-05-15 10:04:40 +08002897
2898 dat.name = "Channel";
2899 dat.value = str_channel;
developer72fb0bb2023-01-11 09:46:29 +08002900 wifi_getMaxRadioNumber(&max_radio_num);
2901 for(int i=0; i<=MAX_APS/max_radio_num;i++)
2902 {
2903 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2904 wifi_hostapdWrite(config_file, &list, 1);
2905 }
developer4903e3f2023-05-15 10:04:40 +08002906 sprintf(config_file_dat, "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
2907 wifi_datfileWrite(config_file_dat, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08002908 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2909 return RETURN_OK;
2910}
2911
2912INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2913{
2914 struct params list[2];
2915 char str_idx[16];
2916 char config_file[64];
2917 int max_num_radios = 0;
2918 wifi_band band = band_invalid;
2919
2920 band = wifi_index_to_band(radioIndex);
2921 if (band == band_2_4)
2922 return RETURN_OK;
2923
2924 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
2925 list[0].name = "vht_oper_centr_freq_seg0_idx";
2926 list[0].value = str_idx;
2927 list[1].name = "he_oper_centr_freq_seg0_idx";
2928 list[1].value = str_idx;
2929
2930 wifi_getMaxRadioNumber(&max_num_radios);
2931 for(int i=0; i<=MAX_APS/max_num_radios; i++)
2932 {
2933 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2934 if (band == band_6)
2935 wifi_hostapdWrite(config_file, &list[1], 1);
2936 else
2937 wifi_hostapdWrite(config_file, list, 2);
2938 }
2939
2940 return RETURN_OK;
2941}
2942
2943//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2944//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2945INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2946{
2947 //Set to wifi config only. Wait for wifi reset to apply.
2948 char buf[256] = {0};
2949 char str_channel[256] = {0};
2950 int count = 0;
2951 ULONG Value = 0;
2952 FILE *fp = NULL;
2953 if(enable == TRUE)
2954 {
2955 wifi_setRadioChannel(radioIndex,Value);
2956 }
2957 return RETURN_OK;
2958}
2959
2960INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2961{
2962 if (output_bool == NULL)
2963 return RETURN_ERR;
2964
2965 *output_bool = TRUE;
2966
2967 return RETURN_OK;
2968}
2969
2970INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2971{
developer69b61b02023-03-07 17:17:44 +08002972 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08002973 return RETURN_ERR;
2974 *output_bool=FALSE;
2975 return RETURN_OK;
2976}
2977
2978INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2979{
developer69b61b02023-03-07 17:17:44 +08002980 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08002981 return RETURN_ERR;
2982 *output_bool=FALSE;
2983 return RETURN_OK;
2984}
2985
2986INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2987{
2988 //Set to wifi config only. Wait for wifi reset to apply.
2989 return RETURN_OK;
2990}
2991
2992INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2993{
2994 return RETURN_OK;
2995}
2996
2997INT wifi_factoryResetAP(int apIndex)
2998{
2999 char ap_config_file[64] = {0};
3000 char cmd[128] = {0};
3001
3002 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3003
3004 wifi_setApEnable(apIndex, FALSE);
3005 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
3006 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
3007 wifi_setApEnable(apIndex, TRUE);
3008
3009 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3010
3011 return RETURN_OK;
3012}
3013
3014//To set Band Steering AP group
3015//To-do
3016INT wifi_setBandSteeringApGroup(char *ApGroup)
3017{
3018 return RETURN_OK;
3019}
3020
3021INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
3022{
3023 char config_file[128] = {'\0'};
3024 char buf[128] = {'\0'};
3025
3026 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3027 if (dtimInterval == NULL)
3028 return RETURN_ERR;
3029
3030 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
3031 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
3032
3033 if (strlen(buf) == 0) {
3034 *dtimInterval = 2;
3035 } else {
3036 *dtimInterval = strtoul(buf, NULL, 10);
3037 }
3038
3039 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3040 return RETURN_OK;
3041}
3042
3043INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
3044{
3045 struct params params={0};
3046 char config_file[MAX_BUF_SIZE] = {'\0'};
3047 char buf[MAX_BUF_SIZE] = {'\0'};
3048
3049 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3050 if (dtimInterval < 1 || dtimInterval > 255) {
3051 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
3052 return RETURN_ERR;
3053 }
developer69b61b02023-03-07 17:17:44 +08003054
developer72fb0bb2023-01-11 09:46:29 +08003055 params.name = "dtim_period";
3056 snprintf(buf, sizeof(buf), "%d", dtimInterval);
3057 params.value = buf;
3058
3059 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
3060 wifi_hostapdWrite(config_file, &params, 1);
3061 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3062
3063 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3064 return RETURN_OK;
3065}
3066
3067//Check if the driver support the Dfs
3068INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
3069{
3070 wifi_band band = band_invalid;
developer69b61b02023-03-07 17:17:44 +08003071 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003072 return RETURN_ERR;
3073 *output_bool=FALSE;
3074
3075 band = wifi_index_to_band(radioIndex);
3076 if (band == band_5)
3077 *output_bool = TRUE;
3078 return RETURN_OK;
3079}
3080
3081//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.
3082//The value of this parameter is a comma seperated list of channel number
3083INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
3084{
developer69b61b02023-03-07 17:17:44 +08003085 if (NULL == output_pool)
developer72fb0bb2023-01-11 09:46:29 +08003086 return RETURN_ERR;
3087 if (radioIndex==1)
developer69b61b02023-03-07 17:17:44 +08003088 return RETURN_OK;//TODO need to handle for 5GHz band, i think
developer72fb0bb2023-01-11 09:46:29 +08003089 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
3090
3091 return RETURN_OK;
3092}
3093
3094INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
3095{
3096 //Set to wifi config. And apply instantly.
3097 return RETURN_OK;
3098}
3099
3100INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
3101{
developer69b61b02023-03-07 17:17:44 +08003102 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
developer72fb0bb2023-01-11 09:46:29 +08003103 return RETURN_ERR;
3104 *output_interval_seconds=1800;
3105 *output_dwell_milliseconds=40;
3106
3107 return RETURN_OK;
3108}
3109
3110INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
3111{
3112 //Set to wifi config. And apply instantly.
3113 return RETURN_OK;
3114}
3115
3116INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
3117{
3118 if (output_bool == NULL)
3119 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08003120 *output_bool = true;
3121 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003122}
3123
3124INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
3125{
3126 return RETURN_OK;
3127}
3128
3129//Get the Dfs enable status
3130INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
3131{
3132 char buf[16] = {0};
3133 FILE *f = NULL;
developer4903e3f2023-05-15 10:04:40 +08003134 char config_file_dat[128] = {0};
3135 char dfs_key[16] = "IEEE80211H";
developer72fb0bb2023-01-11 09:46:29 +08003136
3137 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3138
3139 if (output_bool == NULL)
3140 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08003141 *output_bool = TRUE; // default
developer4903e3f2023-05-15 10:04:40 +08003142 sprintf(config_file_dat, "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
3143
3144 wifi_datfileRead(config_file_dat, dfs_key, buf, sizeof(buf));
3145
3146 if (strncmp(buf, "0", 1) == 0)
3147 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08003148 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3149 return RETURN_OK;
3150}
3151
3152//Set the Dfs enable status
3153INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
3154{
3155 char config_file[128] = {0};
3156 FILE *f = NULL;
developer4903e3f2023-05-15 10:04:40 +08003157 struct params params = {0};
3158 struct params dat = {0};
developer72fb0bb2023-01-11 09:46:29 +08003159
3160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3161
3162 f = fopen(DFS_ENABLE_FILE, "w");
3163 if (f == NULL)
3164 return RETURN_ERR;
3165 fprintf(f, "%d", enable);
3166 fclose(f);
3167
3168 params.name = "acs_exclude_dfs";
3169 params.value = enable?"0":"1";
developer4903e3f2023-05-15 10:04:40 +08003170
developer72fb0bb2023-01-11 09:46:29 +08003171 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3172 wifi_hostapdWrite(config_file, &params, 1);
3173 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
developer72fb0bb2023-01-11 09:46:29 +08003174 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
3175
developer4903e3f2023-05-15 10:04:40 +08003176 dat.name = "IEEE80211H";
3177 dat.value = enable?"0":"1";
3178 wifi_datfileWrite(radioIndex, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08003179 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3180 return RETURN_OK;
3181}
3182
3183//Check if the driver support the AutoChannelRefreshPeriod
3184INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
3185{
developer69b61b02023-03-07 17:17:44 +08003186 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003187 return RETURN_ERR;
3188 *output_bool=FALSE; //not support
3189
3190 return RETURN_OK;
3191}
3192
3193//Get the ACS refresh period in seconds
3194INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
3195{
developer69b61b02023-03-07 17:17:44 +08003196 if (NULL == output_ulong)
developer72fb0bb2023-01-11 09:46:29 +08003197 return RETURN_ERR;
3198 *output_ulong=300;
3199
3200 return RETURN_OK;
3201}
3202
3203//Set the ACS refresh period in seconds
3204INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
3205{
3206 return RETURN_ERR;
3207}
3208
3209//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
3210//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.
3211INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
3212{
developer8666b312023-03-24 14:05:31 +08003213 char cmd[MAX_CMD_SIZE] = {0}, buf[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003214 char extchannel[128] = {0};
developer8666b312023-03-24 14:05:31 +08003215 char interface_name[64] = {0};
3216 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08003217 BOOL radio_enable = FALSE;
3218 wifi_band band;
3219
3220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3221
3222 if (NULL == output_string)
3223 return RETURN_ERR;
3224
3225 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
3226 return RETURN_ERR;
3227
3228 if (radio_enable != TRUE)
3229 return RETURN_OK;
3230
developer8666b312023-03-24 14:05:31 +08003231 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3232 return RETURN_ERR;
3233 /*IW command get BW320 to do*/
3234 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
3235 ret = _syscmd(cmd, buf, sizeof(buf));
3236 len = strlen(buf);
3237 if((ret != 0) || (len == 0))
3238 {
3239 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
3240 return RETURN_ERR;
3241 }
3242
developer72fb0bb2023-01-11 09:46:29 +08003243 band = wifi_index_to_band(radioIndex);
developer8666b312023-03-24 14:05:31 +08003244 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
developer72fb0bb2023-01-11 09:46:29 +08003245 wifi_getRadioExtChannel(radioIndex, extchannel);
developer8666b312023-03-24 14:05:31 +08003246 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
3247 snprintf(buf, sizeof(buf), "40");
developer72fb0bb2023-01-11 09:46:29 +08003248 }
developer8666b312023-03-24 14:05:31 +08003249 snprintf(output_string, 64, "%sMHz", buf);
developer72fb0bb2023-01-11 09:46:29 +08003250 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3251
3252 return RETURN_OK;
3253}
developer72fb0bb2023-01-11 09:46:29 +08003254//Set the Operating Channel Bandwidth.
3255INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
3256{
3257 char config_file[128];
3258 char set_value[16];
3259 struct params params[2];
3260 int max_radio_num = 0;
3261
3262 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3263
3264 if(NULL == bandwidth)
3265 return RETURN_ERR;
3266
3267 if(strstr(bandwidth,"160") != NULL)
3268 strcpy(set_value, "2");
3269 else if(strstr(bandwidth,"80") != NULL)
3270 strcpy(set_value, "1");
3271 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
3272 strcpy(set_value, "0");
3273 else
3274 {
3275 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
3276 return RETURN_ERR;
3277 }
3278
3279 params[0].name = "vht_oper_chwidth";
3280 params[0].value = set_value;
3281 params[1].name = "he_oper_chwidth";
3282 params[1].value = set_value;
3283
3284 wifi_getMaxRadioNumber(&max_radio_num);
3285 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3286 {
3287 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
3288 wifi_hostapdWrite(config_file, params, 2);
3289 }
3290
3291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3292 return RETURN_OK;
3293}
3294
developer4903e3f2023-05-15 10:04:40 +08003295
developer72fb0bb2023-01-11 09:46:29 +08003296
3297//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
3298//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.
3299INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
3300{
3301 char config_file[64] = {0};
3302 char mode_str[16] = {0};
3303 char buf[64] = {0};
3304 wifi_band band;
developer4903e3f2023-05-15 10:04:40 +08003305 ULONG channel = 0, centr_channel = 0;
developer72fb0bb2023-01-11 09:46:29 +08003306 UINT mode_map = 0;
3307
3308 if (output_string == NULL)
3309 return RETURN_ERR;
3310
3311 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
3312
3313 band = wifi_index_to_band(radioIndex);
3314 if (band == band_invalid)
3315 return RETURN_ERR;
3316
3317 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3318
3319 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08003320 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developer72fb0bb2023-01-11 09:46:29 +08003321 // 2G band or ac and ax mode is disable, we will check ht_capab
3322 wifi_halgetRadioExtChannel(config_file, output_string);
developer23e71282023-01-18 10:25:19 +08003323 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08003324 snprintf(output_string, 64, "Auto");
3325 } else {
3326 // 5G and 6G band with ac or ax mode.
3327 wifi_getRadioChannel(radioIndex, &channel);
3328 if (mode_map&WIFI_MODE_AX)
3329 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
3330 else
3331 wifi_hostapdRead(config_file, "vht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
3332 centr_channel = strtol(buf, NULL, 10);
3333 if (centr_channel > channel)
3334 snprintf(output_string, 64, "AboveControlChannel");
3335 else
3336 snprintf(output_string, 64, "BelowControlChannel");
3337 }
3338
3339 return RETURN_OK;
3340}
3341
3342//Set the extension channel.
3343INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer69b61b02023-03-07 17:17:44 +08003344{
developer72fb0bb2023-01-11 09:46:29 +08003345 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3346 struct params params={0};
3347 char config_file[64] = {0};
3348 char ext_channel[128]={0};
3349 char buf[128] = {0};
3350 char cmd[128] = {0};
3351 int max_radio_num =0, ret = 0, bandwidth = 0;
3352 unsigned long channel = 0, centr_channel = 0;
3353 bool stbcEnable = FALSE;
3354 params.name = "ht_capab";
3355 wifi_band band;
3356
3357 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3358 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
3359 _syscmd(cmd, buf, sizeof(buf));
3360 if (strlen(buf) != 0)
3361 stbcEnable = TRUE;
3362 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
3363 return RETURN_ERR;
3364 bandwidth = strtol(buf, NULL, 10);
3365 // TDK expected to get error with 20MHz
3366 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
3367 return RETURN_ERR;
3368
3369 band = wifi_index_to_band(radioIndex);
3370 if (band == band_invalid)
3371 return RETURN_ERR;
3372
3373 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
3374 return RETURN_ERR;
3375
3376 if (band == band_5) {
3377 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
3378 centr_channel = util_unii_5g_centerfreq(buf, channel);
3379 if (centr_channel == 0)
3380 return RETURN_ERR;
3381 }
3382
3383 if(NULL!= strstr(string,"Above")) {
3384 if ((band == band_2_4 && channel > 9) || (band == band_5 && channel > centr_channel))
3385 return RETURN_ERR;
3386 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
3387 } else if(NULL!= strstr(string,"Below")) {
3388 if ((band == band_2_4 && channel < 5) || (band == band_5 && channel < centr_channel))
3389 return RETURN_ERR;
3390 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
3391 } else {
3392 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
3393 }
3394
3395 params.value = ext_channel;
3396
3397 wifi_getMaxRadioNumber(&max_radio_num);
3398 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3399 {
3400 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
3401 wifi_hostapdWrite(config_file, &params, 1);
3402 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
3403 }
3404
3405 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3406 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3407 return RETURN_OK;
3408}
3409
3410//Get the guard interval value. eg "400nsec" or "800nsec"
3411//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.
3412INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3413{
3414 wifi_guard_interval_t GI;
3415
3416 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3417
3418 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
3419 return RETURN_ERR;
3420
3421 if (GI == wifi_guard_interval_400)
3422 strcpy(output_string, "400nsec");
3423 else if (GI == wifi_guard_interval_800)
3424 strcpy(output_string, "800nsec");
3425 else if (GI == wifi_guard_interval_1600)
3426 strcpy(output_string, "1600nsec");
3427 else if (GI == wifi_guard_interval_3200)
3428 strcpy(output_string, "3200nsec");
3429 else
3430 strcpy(output_string, "Auto");
3431
3432 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3433 return RETURN_OK;
3434}
3435
3436//Set the guard interval value.
3437INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3438{
3439 wifi_guard_interval_t GI;
3440 int ret = 0;
3441
3442 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3443
3444 if (strcmp(string, "400nsec") == 0)
3445 GI = wifi_guard_interval_400;
3446 else if (strcmp(string , "800nsec") == 0)
3447 GI = wifi_guard_interval_800;
3448 else if (strcmp(string , "1600nsec") == 0)
3449 GI = wifi_guard_interval_1600;
3450 else if (strcmp(string , "3200nsec") == 0)
3451 GI = wifi_guard_interval_3200;
3452 else
3453 GI = wifi_guard_interval_auto;
3454
3455 ret = wifi_setGuardInterval(radioIndex, GI);
3456
3457 if (ret == RETURN_ERR) {
3458 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3459 return RETURN_ERR;
3460 }
3461
3462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3463 return RETURN_OK;
3464}
3465
3466//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3467INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3468{
3469 char buf[32]={0};
3470 char mcs_file[64] = {0};
3471 char cmd[64] = {0};
3472 int mode_bitmap = 0;
3473
3474 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3475 if(output_int == NULL)
3476 return RETURN_ERR;
3477 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3478
3479 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3480 _syscmd(cmd, buf, sizeof(buf));
3481 if (strlen(buf) > 0)
3482 *output_int = strtol(buf, NULL, 10);
3483 else {
3484 // output the max MCS for the current radio mode
3485 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3486 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3487 return RETURN_ERR;
3488 }
3489 if (mode_bitmap & WIFI_MODE_AX) {
3490 *output_int = 11;
3491 } else if (mode_bitmap & WIFI_MODE_AC) {
3492 *output_int = 9;
3493 } else if (mode_bitmap & WIFI_MODE_N) {
3494 *output_int = 7;
3495 }
3496 }
3497 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3498
3499 return RETURN_OK;
3500}
3501
3502//Set the Modulation Coding Scheme index
3503INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3504{
developera1255e42023-05-13 17:45:02 +08003505 /*Only HE mode can specify MCS capability. We don't support MCS in HT mode,
3506 because that would be ambiguous (MCS code 8~11 refer to 2 NSS in HT but 1 NSS in HE adn VHT).*/
developer72fb0bb2023-01-11 09:46:29 +08003507 char config_file[64] = {0};
3508 char set_value[16] = {0};
3509 char mcs_file[32] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003510 struct params set_config = {0};
3511 FILE *f = NULL;
developera1255e42023-05-13 17:45:02 +08003512 INT nss = 0;
3513 int ant_bitmap = 0;
3514 unsigned short cal_value = 0;
3515 UCHAR tval = 0, i = 0;
developer72fb0bb2023-01-11 09:46:29 +08003516
3517 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3518
3519 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3520
3521 // -1 means auto
3522 if (MCS > 15 || MCS < -1) {
3523 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3524 return RETURN_ERR;
3525 }
developera1255e42023-05-13 17:45:02 +08003526 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);/*nss is a bit map value,1111*/
3527 for(; ant_bitmap > 0; ant_bitmap >>= 1)
3528 nss += 1;
3529 //printf("%s:nss = %d\n", __func__, nss);
3530 /*16-bit combination of 2-bit values of Max HE-MCS For 1..8 SS;each 2-bit value have following meaning:
3531 0 = HE-MCS 0-7, 1 = HE-MCS 0-9, 2 = HE-MCS 0-11, 3 = not supported*/
developer72fb0bb2023-01-11 09:46:29 +08003532 if (MCS > 9 || MCS == -1)
developera1255e42023-05-13 17:45:02 +08003533 tval = 2;/*one stream value*/
developer72fb0bb2023-01-11 09:46:29 +08003534 else if (MCS > 7)
developera1255e42023-05-13 17:45:02 +08003535 tval = 1;
developer72fb0bb2023-01-11 09:46:29 +08003536 else
developera1255e42023-05-13 17:45:02 +08003537 tval = 0;
3538 for (i = 0; i < nss; i++)
3539 cal_value |= (tval << (2*i));
3540 snprintf(set_value, sizeof(set_value), "%x", cal_value);
3541 WIFI_ENTRY_EXIT_DEBUG("%s:set=%s, cal=%x\n", __func__, set_value, cal_value);
3542 set_config.name = "he_basic_mcs_nss_set";/*He capability in beacon or response*/
developer72fb0bb2023-01-11 09:46:29 +08003543 set_config.value = set_value;
3544
3545 wifi_hostapdWrite(config_file, &set_config, 1);
3546 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3547
3548 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3549 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3550 f = fopen(mcs_file, "w");
3551 if (f == NULL) {
3552 fprintf(stderr, "%s: fopen failed\n", __func__);
3553 return RETURN_ERR;
3554 }
3555 fprintf(f, "%d", MCS);
3556 fclose(f);
3557
3558 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3559 return RETURN_OK;
3560}
3561
3562//Get supported Transmit Power list, eg : "0,25,50,75,100"
3563//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.
3564INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3565{
3566 if (NULL == output_list)
3567 return RETURN_ERR;
3568 snprintf(output_list, 64,"0,25,50,75,100");
3569 return RETURN_OK;
3570}
3571
3572//Get current Transmit Power in dBm units.
3573//The transmite power level is in units of full power for this radio.
3574INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3575{
3576 char interface_name[16] = {0};
3577 char cmd[128]={0};
3578 char buf[16]={0};
developera1255e42023-05-13 17:45:02 +08003579 char pwr_file[128]={0};
3580
developer72fb0bb2023-01-11 09:46:29 +08003581 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3582
3583 if(output_ulong == NULL)
3584 return RETURN_ERR;
3585
3586 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3587 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08003588/*
developer72fb0bb2023-01-11 09:46:29 +08003589 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
3590 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08003591 *output_ulong = strtol(buf, NULL, 10);
developera1255e42023-05-13 17:45:02 +08003592*/
3593 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
3594 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", pwr_file);
3595 _syscmd(cmd, buf, sizeof(buf));
3596 if (strlen(buf) > 0)
3597 *output_ulong = strtol(buf, NULL, 10);
3598 else
3599 *output_ulong = 100;
developer72fb0bb2023-01-11 09:46:29 +08003600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3601 return RETURN_OK;
3602}
3603
3604//Set Transmit Power
3605//The transmite power level is in units of full power for this radio.
3606INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3607{
3608 char interface_name[16] = {0};
3609 char *support;
3610 char cmd[128]={0};
3611 char buf[128]={0};
3612 char txpower_str[64] = {0};
developera1255e42023-05-13 17:45:02 +08003613 char pwr_file[128]={0};
3614 FILE *f = NULL;
developer72fb0bb2023-01-11 09:46:29 +08003615
3616 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3617
3618 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3619 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08003620 // Get the Tx power supported list and check that is the input in the list
3621 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3622 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3623 support = strtok(buf, ",");
3624 while(true)
3625 {
3626 if(support == NULL) { // input not in the list
3627 wifi_dbg_printf("Input value is invalid.\n");
3628 return RETURN_ERR;
3629 }
3630 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3631 break;
3632 }
3633 support = strtok(NULL, ",");
3634 }
3635 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr PercentageCtrl=1\n", interface_name);
3636 _syscmd(cmd, buf, sizeof(buf));
3637 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr PowerDropCtrl=%lu\n", interface_name, TransmitPower);
3638 _syscmd(cmd, buf, sizeof(buf));
3639 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
3640 f = fopen(pwr_file, "w");
3641 if (f == NULL) {
3642 fprintf(stderr, "%s: fopen failed\n", __func__);
3643 return RETURN_ERR;
3644 }
3645 fprintf(f, "%d", TransmitPower);
3646 fclose(f);
3647/* snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08003648 _syscmd(cmd, buf, sizeof(buf));
3649 maximum_tx = strtol(buf, NULL, 10);
3650
3651 // Get the Tx power supported list and check that is the input in the list
3652 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3653 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3654 support = strtok(buf, ",");
3655 while(true)
3656 {
3657 if(support == NULL) { // input not in the list
3658 wifi_dbg_printf("Input value is invalid.\n");
3659 return RETURN_ERR;
3660 }
3661 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3662 break;
3663 }
3664 support = strtok(NULL, ",");
3665 }
3666 txpower = TransmitPower*maximum_tx/100;
3667 phyId = radio_index_to_phy(radioIndex);
3668 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
3669 _syscmd(cmd, buf, sizeof(buf));
3670 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera1255e42023-05-13 17:45:02 +08003671*/
3672 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003673}
3674
3675//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3676INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3677{
developer69b61b02023-03-07 17:17:44 +08003678 if (NULL == Supported)
developer72fb0bb2023-01-11 09:46:29 +08003679 return RETURN_ERR;
3680 *Supported = TRUE;
3681
3682 return RETURN_OK;
3683}
3684
3685//Get 80211h feature enable
3686INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3687{
3688 char buf[64]={'\0'};
3689 char config_file[64] = {'\0'};
3690
3691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3692 if(enable == NULL)
3693 return RETURN_ERR;
3694
3695 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3696 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
3697
3698 if (strncmp(buf, "1", 1) == 0)
3699 *enable = TRUE;
3700 else
3701 *enable = FALSE;
3702
3703 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3704 return RETURN_OK;
3705}
3706
3707//Set 80211h feature enable
3708INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3709{
3710 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3711 struct params params={'\0'};
3712 char config_file[MAX_BUF_SIZE] = {0};
3713
3714 params.name = "ieee80211h";
3715
3716 if (enable) {
3717 params.value = "1";
3718 } else {
3719 params.value = "0";
3720 }
3721
3722 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3723 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08003724
developer72fb0bb2023-01-11 09:46:29 +08003725 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3726 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3727 return RETURN_OK;
3728}
3729
3730//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.
3731INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3732{
3733 if (NULL == output)
3734 return RETURN_ERR;
3735 *output=100;
3736
3737 return RETURN_OK;
3738}
3739
3740//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.
3741INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3742{
3743 if (NULL == output)
3744 return RETURN_ERR;
3745 *output = -99;
3746
3747 return RETURN_OK;
3748}
3749
3750INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3751{
3752 return RETURN_ERR;
3753}
3754
3755
3756//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3757INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3758{
3759 char interface_name[16] = {0};
3760 char cmd[MAX_BUF_SIZE]={'\0'};
3761 char buf[MAX_CMD_SIZE]={'\0'};
3762
3763 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3764 if(output == NULL)
3765 return RETURN_ERR;
3766
3767 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3768 return RETURN_ERR;
3769 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
3770 _syscmd(cmd, buf, sizeof(buf));
3771 *output = atoi(buf);
3772
3773 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3774 return RETURN_OK;
3775}
developer69b61b02023-03-07 17:17:44 +08003776
developer72fb0bb2023-01-11 09:46:29 +08003777INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3778{
3779 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3780 struct params params={'\0'};
3781 char buf[MAX_BUF_SIZE] = {'\0'};
3782 char config_file[MAX_BUF_SIZE] = {'\0'};
3783
3784 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3785 return RETURN_ERR;
3786
3787 params.name = "beacon_int";
3788 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3789 params.value = buf;
3790
3791 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3792 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08003793
developer72fb0bb2023-01-11 09:46:29 +08003794 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3795 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3796 return RETURN_OK;
3797}
3798
3799//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.
3800INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3801{
3802 //TODO: need to revisit below implementation
3803 char *temp;
3804 char temp_output[128] = {0};
3805 char temp_TransmitRates[64] = {0};
3806 char config_file[64] = {0};
3807
3808 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3809 if (NULL == output)
3810 return RETURN_ERR;
3811 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3812 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
developer69b61b02023-03-07 17:17:44 +08003813
developer72fb0bb2023-01-11 09:46:29 +08003814 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3815 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3816 } else {
3817 temp = strtok(temp_TransmitRates," ");
3818 while(temp!=NULL)
3819 {
3820 // Convert 100 kbps to Mbps
3821 temp[strlen(temp)-1]=0;
3822 if((temp[0]=='5') && (temp[1]=='\0'))
3823 {
3824 temp="5.5";
3825 }
3826 strcat(temp_output,temp);
3827 temp = strtok(NULL," ");
3828 if(temp!=NULL)
3829 {
3830 strcat(temp_output,",");
3831 }
3832 }
3833 strcpy(output,temp_output);
3834 }
3835 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3836 return RETURN_OK;
3837}
3838
3839INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3840{
3841 char *temp;
3842 char temp1[128];
3843 char temp_output[128];
3844 char temp_TransmitRates[128];
3845 char set[128];
3846 char sub_set[128];
3847 int set_count=0,subset_count=0;
3848 int set_index=0,subset_index=0;
3849 char *token;
3850 int flag=0, i=0;
3851 struct params params={'\0'};
3852 char config_file[MAX_BUF_SIZE] = {0};
3853 wifi_band band = wifi_index_to_band(radioIndex);
3854
3855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3856 if(NULL == TransmitRates)
3857 return RETURN_ERR;
3858 strcpy(sub_set,TransmitRates);
3859
3860 //Allow only supported Data transmit rate to be set
3861 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3862 token = strtok(sub_set,",");
3863 while( token != NULL ) /* split the basic rate to be set, by comma */
3864 {
3865 sub_set[subset_count]=atoi(token);
3866 subset_count++;
3867 token=strtok(NULL,",");
3868 }
3869 token=strtok(set,",");
3870 while(token!=NULL) /* split the supported rate by comma */
3871 {
3872 set[set_count]=atoi(token);
3873 set_count++;
3874 token=strtok(NULL,",");
3875 }
3876 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3877 {
3878 for(set_index=0;set_index < set_count;set_index++)
3879 {
3880 flag=0;
3881 if(sub_set[subset_index]==set[set_index])
3882 break;
3883 else
3884 flag=1; /* No match found */
3885 }
3886 if(flag==1)
3887 return RETURN_ERR; //If value not found return Error
3888 }
3889 strcpy(temp_TransmitRates,TransmitRates);
3890
3891 for(i=0;i<strlen(temp_TransmitRates);i++)
3892 {
3893 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3894 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
3895 {
3896 continue;
3897 }
3898 else
3899 {
3900 return RETURN_ERR;
3901 }
3902 }
3903 strcpy(temp_output,"");
3904 temp = strtok(temp_TransmitRates,",");
3905 while(temp!=NULL)
3906 {
3907 strcpy(temp1,temp);
3908 if(band == band_5)
3909 {
3910 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
3911 {
3912 return RETURN_ERR;
3913 }
3914 }
3915
3916 if(strcmp(temp,"5.5")==0)
3917 {
3918 strcpy(temp1,"55");
3919 }
3920 else
3921 {
3922 strcat(temp1,"0");
3923 }
3924 strcat(temp_output,temp1);
3925 temp = strtok(NULL,",");
3926 if(temp!=NULL)
3927 {
3928 strcat(temp_output," ");
3929 }
3930 }
3931 strcpy(TransmitRates,temp_output);
3932
3933 params.name= "basic_rates";
3934 params.value =TransmitRates;
3935
3936 wifi_dbg_printf("\n%s:",__func__);
3937 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3938 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3939 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3940 wifi_hostapdWrite(config_file,&params,1);
3941 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3942 return RETURN_OK;
3943}
3944
3945//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3946INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3947{
3948 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3949 FILE *fp = NULL;
3950 char path[256] = {0}, output_string[256] = {0};
3951 int count = 0;
3952 char *interface = NULL;
3953
3954 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3955 if (fp == NULL)
3956 {
3957 printf("Failed to run command in Function %s\n", __FUNCTION__);
3958 return RETURN_ERR;
3959 }
3960 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3961 {
3962 interface = strchr(path, '=');
3963
3964 if (interface != NULL)
3965 {
3966 strcpy(output_string, interface + 1);
3967 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3968 interface_name[count] = output_string[count];
3969
3970 interface_name[count] = '\0';
3971 }
3972 }
3973 pclose(fp);
3974 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3975 return RETURN_OK;
3976}
3977
3978INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3979{
3980 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3981 output_struct->radio_BytesSent = 0;
3982 output_struct->radio_BytesReceived = 0;
3983 output_struct->radio_PacketsSent = 0;
3984 output_struct->radio_PacketsReceived = 0;
3985 output_struct->radio_ErrorsSent = 0;
3986 output_struct->radio_ErrorsReceived = 0;
3987 output_struct->radio_DiscardPacketsSent = 0;
3988 output_struct->radio_DiscardPacketsReceived = 0;
3989 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3990 return RETURN_OK;
3991}
3992
3993
3994INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3995{
3996 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3997 CHAR buf[MAX_CMD_SIZE] = {0};
3998 CHAR Value[MAX_BUF_SIZE] = {0};
3999 FILE *fp = NULL;
4000
4001 if (ifname == NULL || strlen(ifname) <= 1)
4002 return RETURN_OK;
4003
4004 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
4005 system(buf);
4006
4007 fp = fopen("/tmp/Radio_Stats.txt", "r");
4008 if(fp == NULL)
4009 {
4010 printf("/tmp/Radio_Stats.txt not exists \n");
4011 return RETURN_ERR;
4012 }
4013 fclose(fp);
4014
4015 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4016 File_Reading(buf, Value);
4017 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
4018
4019 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4020 File_Reading(buf, Value);
4021 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
4022
4023 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4024 File_Reading(buf, Value);
4025 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
4026
4027 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4028 File_Reading(buf, Value);
4029 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
4030
4031 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4032 File_Reading(buf, Value);
4033 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
4034
4035 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4036 File_Reading(buf, Value);
4037 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
4038
4039 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4040 File_Reading(buf, Value);
4041 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
4042
4043 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4044 File_Reading(buf, Value);
4045 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
4046
4047 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4048 return RETURN_OK;
4049}
4050
4051INT GetIfacestatus(CHAR *interface_name, CHAR *status)
4052{
developer7e4a2a62023-04-06 19:56:03 +08004053 CHAR buf[MAX_CMD_SIZE] = {0};
4054 INT count = 0;
developer72fb0bb2023-01-11 09:46:29 +08004055
developer7e4a2a62023-04-06 19:56:03 +08004056 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4057
4058 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL) {
4059 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
4060 File_Reading(buf, status);
4061 }
4062
4063 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4064 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004065}
4066
4067//Get detail radio traffic static info
4068INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
4069{
4070
developer69b61b02023-03-07 17:17:44 +08004071#if 0
4072 //ifconfig radio_x
developer72fb0bb2023-01-11 09:46:29 +08004073 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
4074 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
4075 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
4076 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
4077
4078 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
4079 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
4080 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.
4081 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.
4082
developer69b61b02023-03-07 17:17:44 +08004083 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
developer72fb0bb2023-01-11 09:46:29 +08004084 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].
4085 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
4086 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.
4087 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
4088 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
4089 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
4090 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
4091 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
4092
4093 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
4094 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
4095 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
4096 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.
4097
4098 return RETURN_OK;
4099#endif
4100
4101 CHAR interface_name[64] = {0};
4102 BOOL iface_status = FALSE;
4103 wifi_radioTrafficStats2_t radioTrafficStats = {0};
4104
4105 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4106 if (NULL == output_struct)
4107 return RETURN_ERR;
4108
4109 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4110 return RETURN_ERR;
4111
4112 wifi_getApEnable(radioIndex, &iface_status);
4113
4114 if (iface_status == TRUE)
4115 wifi_halGetIfStats(interface_name, &radioTrafficStats);
4116 else
4117 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
4118
4119 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
4120 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
4121 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
4122 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
4123 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
4124 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
4125 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
4126 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
4127
4128 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
4129 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].
4130 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
4131 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.
4132 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
4133 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
4134 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
4135 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
4136 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
4137
4138 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
4139 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
4140 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
4141 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.
4142
4143 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4144
4145 return RETURN_OK;
4146}
4147
4148//Set radio traffic static Measureing rules
4149INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
4150{
4151 //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
4152 // Else, save the MeasuringRate and MeasuringInterval for future usage
4153
4154 return RETURN_OK;
4155}
4156
4157//To start or stop RadioTrafficStats
4158INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
4159{
4160 //zqiu: If the RadioTrafficStats process running
4161 // if(enable)
4162 // return RETURN_OK.
4163 // else
4164 // Stop RadioTrafficStats process
developer69b61b02023-03-07 17:17:44 +08004165 // Else
developer72fb0bb2023-01-11 09:46:29 +08004166 // if(enable)
4167 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
4168 // else
4169 // return RETURN_OK.
4170
4171 return RETURN_OK;
4172}
4173
4174//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
4175INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
4176{
4177 //zqiu: Please ignor signalIndex.
developer69b61b02023-03-07 17:17:44 +08004178 if (NULL == SignalLevel)
developer72fb0bb2023-01-11 09:46:29 +08004179 return RETURN_ERR;
4180 *SignalLevel=(radioIndex==0)?-19:-19;
4181
4182 return RETURN_OK;
4183}
4184
4185//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4186INT wifi_applyRadioSettings(INT radioIndex)
4187{
4188 return RETURN_OK;
4189}
4190
4191//Get the radio index assocated with this SSID entry
4192INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
4193{
4194 if(NULL == radioIndex)
4195 return RETURN_ERR;
4196 int max_radio_num = 0;
4197 wifi_getMaxRadioNumber(&max_radio_num);
4198 *radioIndex = ssidIndex%max_radio_num;
4199 return RETURN_OK;
4200}
4201
4202//Device.WiFi.SSID.{i}.Enable
4203//Get SSID enable configuration parameters (not the SSID enable status)
4204INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
4205{
developer69b61b02023-03-07 17:17:44 +08004206 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08004207 return RETURN_ERR;
4208
4209 return wifi_getApEnable(ssidIndex, output_bool);
4210}
4211
4212//Device.WiFi.SSID.{i}.Enable
4213//Set SSID enable configuration parameters
4214INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
4215{
4216 return wifi_setApEnable(ssidIndex, enable);
4217}
4218
4219//Device.WiFi.SSID.{i}.Status
4220//Get the SSID enable status
4221INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
4222{
4223 char cmd[MAX_CMD_SIZE]={0};
4224 char buf[MAX_BUF_SIZE]={0};
4225 BOOL output_bool;
4226
4227 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4228 if (NULL == output_string)
4229 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08004230
developer72fb0bb2023-01-11 09:46:29 +08004231 wifi_getApEnable(ssidIndex,&output_bool);
4232 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
4233
4234 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4235 return RETURN_OK;
4236}
4237
4238// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
4239INT wifi_getSSIDName(INT apIndex, CHAR *output)
4240{
4241 char config_file[MAX_BUF_SIZE] = {0};
4242
developer69b61b02023-03-07 17:17:44 +08004243 if (NULL == output)
developer72fb0bb2023-01-11 09:46:29 +08004244 return RETURN_ERR;
4245
4246 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4247 wifi_hostapdRead(config_file,"ssid",output,32);
4248
4249 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
4250 return RETURN_OK;
4251}
4252
developer69b61b02023-03-07 17:17:44 +08004253// Set a max 32 byte string and sets an internal variable to the SSID name
developer72fb0bb2023-01-11 09:46:29 +08004254INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
4255{
4256 char str[MAX_BUF_SIZE]={'\0'};
4257 char cmd[MAX_CMD_SIZE]={'\0'};
4258 struct params params;
4259 char config_file[MAX_BUF_SIZE] = {0};
4260
4261 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4262 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
4263 return RETURN_ERR;
4264
4265 params.name = "ssid";
4266 params.value = ssid_string;
4267 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4268 wifi_hostapdWrite(config_file, &params, 1);
4269 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4270 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4271
4272 return RETURN_OK;
4273}
4274
4275//Get the BSSID
4276INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
4277{
developer7e4a2a62023-04-06 19:56:03 +08004278 char cmd[MAX_CMD_SIZE] = {0};
4279 char inf_name[IF_NAME_SIZE] = {0};
4280 char conf_file[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004281
developer7e4a2a62023-04-06 19:56:03 +08004282 if (!output_string)
developer72fb0bb2023-01-11 09:46:29 +08004283 return RETURN_ERR;
4284
developer7e4a2a62023-04-06 19:56:03 +08004285 wifi_GetInterfaceName(ssidIndex, inf_name);
4286
4287 if(ssidIndex >= 0 && ssidIndex < MAX_APS) {
4288 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep bssid | cut -d '=' -f2 | tr -d '\\n'", inf_name);
developer72fb0bb2023-01-11 09:46:29 +08004289 _syscmd(cmd, output_string, 64);
developer7e4a2a62023-04-06 19:56:03 +08004290 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004291 }
developer7e4a2a62023-04-06 19:56:03 +08004292
developer72fb0bb2023-01-11 09:46:29 +08004293 strncpy(output_string, "\0", 1);
4294
4295 return RETURN_ERR;
4296}
4297
4298//Get the MAC address associated with this Wifi SSID
4299INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
4300{
4301 wifi_getBaseBSSID(ssidIndex,output_string);
4302 return RETURN_OK;
4303}
4304
4305//Get the basic SSID traffic static info
4306//Apply SSID and AP (in the case of Acess Point devices) to the hardware
4307//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4308INT wifi_applySSIDSettings(INT ssidIndex)
4309{
4310 char interface_name[16] = {0};
4311 BOOL status = false;
4312 char cmd[MAX_CMD_SIZE] = {0};
4313 char buf[MAX_CMD_SIZE] = {0};
4314 int apIndex, ret;
4315 int max_radio_num = 0;
4316 int radioIndex = 0;
4317
4318 wifi_getMaxRadioNumber(&max_radio_num);
4319
4320 radioIndex = ssidIndex % max_radio_num;
4321
4322 wifi_getApEnable(ssidIndex,&status);
4323 // Do not apply when ssid index is disabled
4324 if (status == false)
4325 return RETURN_OK;
4326
4327 /* Doing full remove and add for ssid Index
4328 * Not all hostapd options are supported with reload
4329 * for example macaddr_acl
4330 */
4331 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
4332 return RETURN_ERR;
4333
4334 ret = wifi_setApEnable(ssidIndex,true);
4335
4336 /* Workaround for hostapd issue with multiple bss definitions
4337 * when first created interface will be removed
4338 * then all vaps other vaps on same phy are removed
4339 * after calling setApEnable to false readd all enabled vaps */
4340 for(int i=0; i < MAX_APS/max_radio_num; i++) {
4341 apIndex = max_radio_num*i+radioIndex;
4342 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4343 return RETURN_ERR;
4344 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
4345 _syscmd(cmd, buf, sizeof(buf));
4346 if(*buf == '1')
4347 wifi_setApEnable(apIndex, true);
4348 }
4349
4350 return ret;
4351}
4352
4353struct channels_noise {
4354 int channel;
4355 int noise;
4356};
4357
4358// Return noise array for each channel
4359int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
4360{
4361 char interface_name[16] = {0};
4362 FILE *f = NULL;
4363 char cmd[128] = {0};
4364 char line[256] = {0};
4365 size_t len = 0;
4366 ssize_t read = 0;
4367 int tmp = 0, arr_index = -1;
4368
4369 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4370 return RETURN_ERR;
4371 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
4372
4373 if ((f = popen(cmd, "r")) == NULL) {
4374 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4375 return RETURN_ERR;
4376 }
developer69b61b02023-03-07 17:17:44 +08004377
developer72fb0bb2023-01-11 09:46:29 +08004378 while(fgets(line, sizeof(line), f) != NULL) {
4379 if(arr_index < channels_num){
4380 sscanf(line, "%d", &tmp);
4381 if (tmp > 0) { // channel frequency, the first line must be frequency
4382 arr_index++;
4383 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
4384 } else { // noise
4385 channels_noise_arr[arr_index].noise = tmp;
4386 }
4387 }else{
4388 break;
4389 }
4390 }
4391 pclose(f);
4392 return RETURN_OK;
4393}
4394
4395//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
4396//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
developer69b61b02023-03-07 17:17:44 +08004397INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
developer72fb0bb2023-01-11 09:46:29 +08004398{
4399 int index = -1;
4400 wifi_neighbor_ap2_t *scan_array = NULL;
4401 char cmd[256]={0};
4402 char buf[128]={0};
4403 char file_name[32] = {0};
4404 char filter_SSID[32] = {0};
4405 char line[256] = {0};
4406 char interface_name[16] = {0};
4407 char *ret = NULL;
4408 int freq=0;
4409 FILE *f = NULL;
4410 size_t len=0;
4411 int channels_num = 0;
4412 int vht_channel_width = 0;
4413 int get_noise_ret = RETURN_ERR;
4414 bool filter_enable = false;
4415 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
4416 int phyId = 0;
4417
4418 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
4419
4420 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4421 return RETURN_ERR;
4422
4423 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4424 f = fopen(file_name, "r");
4425 if (f != NULL) {
4426 fgets(filter_SSID, sizeof(file_name), f);
4427 if (strlen(filter_SSID) != 0)
4428 filter_enable = true;
4429 fclose(f);
4430 }
4431
4432 phyId = radio_index_to_phy(radioIndex);
4433 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
4434 _syscmd(cmd, buf, sizeof(buf));
4435 channels_num = strtol(buf, NULL, 10);
4436
4437
4438
4439 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4440 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
4441 fprintf(stderr, "cmd: %s\n", cmd);
4442 if ((f = popen(cmd, "r")) == NULL) {
4443 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4444 return RETURN_ERR;
4445 }
developer69b61b02023-03-07 17:17:44 +08004446
developer72fb0bb2023-01-11 09:46:29 +08004447 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4448 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08004449
developer72fb0bb2023-01-11 09:46:29 +08004450 ret = fgets(line, sizeof(line), f);
4451 while (ret != NULL) {
4452 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08004453 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
developer72fb0bb2023-01-11 09:46:29 +08004454 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4455 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
4456
4457 if (!filter_BSS) {
4458 index++;
4459 wifi_neighbor_ap2_t *tmp;
4460 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4461 if (tmp == NULL) { // no more memory to use
4462 index--;
4463 wifi_dbg_printf("%s: realloc failed\n", __func__);
4464 break;
4465 }
4466 scan_array = tmp;
4467 }
4468 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4469
4470 filter_BSS = false;
4471 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4472 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4473 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4474 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4475 } else if (strstr(line, "freq") != NULL) {
4476 sscanf(line," freq: %d", &freq);
4477 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4478
4479 if (freq >= 2412 && freq <= 2484) {
4480 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4481 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4482 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4483 }
4484 else if (freq >= 5160 && freq <= 5805) {
4485 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4486 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4487 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4488 }
4489
4490 scan_array[index].ap_Noise = 0;
4491 if (get_noise_ret == RETURN_OK) {
4492 for (int i = 0; i < channels_num; i++) {
4493 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4494 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4495 break;
4496 }
4497 }
4498 }
4499 } else if (strstr(line, "beacon interval") != NULL) {
4500 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4501 } else if (strstr(line, "signal") != NULL) {
4502 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4503 } else if (strstr(line,"SSID") != NULL) {
4504 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4505 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4506 filter_BSS = true;
4507 }
4508 } else if (strstr(line, "Supported rates") != NULL) {
4509 char SRate[80] = {0}, *tmp = NULL;
4510 memset(buf, 0, sizeof(buf));
4511 strcpy(SRate, line);
4512 tmp = strtok(SRate, ":");
4513 tmp = strtok(NULL, ":");
4514 strcpy(buf, tmp);
4515 memset(SRate, 0, sizeof(SRate));
4516
4517 tmp = strtok(buf, " \n");
4518 while (tmp != NULL) {
4519 strcat(SRate, tmp);
4520 if (SRate[strlen(SRate) - 1] == '*') {
4521 SRate[strlen(SRate) - 1] = '\0';
4522 }
4523 strcat(SRate, ",");
4524
4525 tmp = strtok(NULL, " \n");
4526 }
4527 SRate[strlen(SRate) - 1] = '\0';
4528 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4529 } else if (strstr(line, "DTIM") != NULL) {
4530 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4531 } else if (strstr(line, "VHT capabilities") != NULL) {
4532 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4533 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4534 } else if (strstr(line, "HT capabilities") != NULL) {
4535 strcat(scan_array[index].ap_SupportedStandards, ",n");
4536 strcpy(scan_array[index].ap_OperatingStandards, "n");
4537 } else if (strstr(line, "VHT operation") != NULL) {
4538 ret = fgets(line, sizeof(line), f);
4539 sscanf(line," * channel width: %d", &vht_channel_width);
4540 if(vht_channel_width == 1) {
4541 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4542 } else {
4543 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4544 }
4545 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4546 continue;
4547 } else if (strstr(line, "HT operation") != NULL) {
4548 ret = fgets(line, sizeof(line), f);
4549 sscanf(line," * secondary channel offset: %s", &buf);
4550 if (!strcmp(buf, "above")) {
4551 //40Mhz +
4552 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4553 }
4554 else if (!strcmp(buf, "below")) {
4555 //40Mhz -
4556 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4557 } else {
4558 //20Mhz
4559 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4560 }
4561 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4562 continue;
4563 } else if (strstr(line, "HE capabilities") != NULL) {
4564 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4565 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4566 ret = fgets(line, sizeof(line), f);
4567 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4568 if (strstr(line, "HE40/2.4GHz") != NULL)
4569 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
4570 else
4571 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
4572 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
4573 if (strstr(line, "HE80/5GHz") != NULL) {
4574 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4575 ret = fgets(line, sizeof(line), f);
4576 } else
4577 continue;
4578 if (strstr(line, "HE160/5GHz") != NULL)
4579 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
4580 }
4581 continue;
4582 } else if (strstr(line, "WPA") != NULL) {
4583 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4584 } else if (strstr(line, "RSN") != NULL) {
4585 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4586 } else if (strstr(line, "Group cipher") != NULL) {
4587 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4588 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4589 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4590 }
4591 }
4592 ret = fgets(line, sizeof(line), f);
4593 }
4594
4595 if (!filter_BSS) {
4596 *output_array_size = index + 1;
4597 } else {
4598 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4599 *output_array_size = index;
4600 }
4601 *neighbor_ap_array = scan_array;
4602 pclose(f);
4603 free(channels_noise_arr);
4604 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4605 return RETURN_OK;
4606}
4607
4608//>> Deprecated: used for old RDKB code.
4609INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4610{
4611 INT status = RETURN_ERR;
4612
4613 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4614 output_struct->wifi_PLCPErrorCount = 0;
4615 output_struct->wifi_FCSErrorCount = 0;
4616 output_struct->wifi_InvalidMACCount = 0;
4617 output_struct->wifi_PacketsOtherReceived = 0;
4618 output_struct->wifi_Noise = 0;
4619 status = RETURN_OK;
4620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4621 return status;
4622}
4623
4624INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4625{
4626 char interface_name[16] = {0};
4627 char cmd[128] = {0};
4628 char buf[1280] = {0};
4629 char *pos = NULL;
4630
4631 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4632 if (NULL == output_struct)
4633 return RETURN_ERR;
4634
4635 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4636 return RETURN_ERR;
4637
4638 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4639
4640 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
4641 _syscmd(cmd, buf, sizeof(buf));
4642
4643 pos = buf;
4644 if ((pos = strstr(pos, "RX packets:")) == NULL)
4645 return RETURN_ERR;
4646 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4647
4648 if ((pos = strstr(pos, "TX packets:")) == NULL)
4649 return RETURN_ERR;
4650 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4651
4652 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4653 return RETURN_ERR;
4654 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4655
4656 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4657 return RETURN_ERR;
4658 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4659
4660 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
4661 _syscmd(cmd, buf, sizeof(buf));
4662 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4663
4664#if 0
4665 //TODO: need to revisit below implementation
4666 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4667 char interface_name[MAX_BUF_SIZE] = {0};
4668 char interface_status[MAX_BUF_SIZE] = {0};
4669 char Value[MAX_BUF_SIZE] = {0};
4670 char buf[MAX_CMD_SIZE] = {0};
4671 char cmd[MAX_CMD_SIZE] = {0};
4672 FILE *fp = NULL;
4673
4674 if (NULL == output_struct) {
4675 return RETURN_ERR;
4676 }
4677
4678 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4679
4680 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4681 {
4682 if(apIndex == 0) //private_wifi for 2.4G
4683 {
4684 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4685 }
4686 else if(apIndex == 1) //private_wifi for 5G
4687 {
4688 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4689 }
4690 else if(apIndex == 4) //public_wifi for 2.4G
4691 {
4692 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4693 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4694 {
4695 return RETURN_ERR;
4696 }
4697 if(buf[0] == '#')//tp-link
4698 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4699 else//tenda
4700 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
4701 }
4702 else if(apIndex == 5) //public_wifi for 5G
4703 {
4704 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4705 }
4706
4707 GetIfacestatus(interface_name, interface_status);
4708
4709 if(0 != strcmp(interface_status, "1"))
4710 return RETURN_ERR;
4711
4712 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4713 system(cmd);
4714
4715 fp = fopen("/tmp/SSID_Stats.txt", "r");
4716 if(fp == NULL)
4717 {
4718 printf("/tmp/SSID_Stats.txt not exists \n");
4719 return RETURN_ERR;
4720 }
4721 fclose(fp);
4722
4723 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4724 File_Reading(buf, Value);
4725 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4726
4727 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4728 File_Reading(buf, Value);
4729 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4730
4731 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4732 File_Reading(buf, Value);
4733 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4734
4735 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4736 File_Reading(buf, Value);
4737 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4738
4739 /* There is no specific parameter from caller to associate the value wifi_Associations */
4740 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4741 //_syscmd(cmd, buf, sizeof(buf));
4742 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4743 }
4744#endif
4745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4746 return RETURN_OK;
4747}
4748
4749INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4750{
4751 char interface_name[MAX_BUF_SIZE] = {0};
4752 char interface_status[MAX_BUF_SIZE] = {0};
4753 char Value[MAX_BUF_SIZE] = {0};
4754 char buf[MAX_CMD_SIZE] = {0};
4755 char cmd[MAX_CMD_SIZE] = {0};
4756 FILE *fp = NULL;
4757
4758 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4759 if (NULL == output_struct)
4760 return RETURN_ERR;
4761
4762 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4763
4764 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
4765 return RETURN_ERR;
4766 GetIfacestatus(interface_name, interface_status);
4767
4768 if(0 != strcmp(interface_status, "1"))
4769 return RETURN_ERR;
4770
4771 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4772 system(cmd);
4773
4774 fp = fopen("/tmp/SSID_Stats.txt", "r");
4775 if(fp == NULL)
4776 {
4777 printf("/tmp/SSID_Stats.txt not exists \n");
4778 return RETURN_ERR;
4779 }
4780 fclose(fp);
4781
4782 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4783 File_Reading(buf, Value);
4784 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4785
4786 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4787 File_Reading(buf, Value);
4788 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4789
4790 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4791 File_Reading(buf, Value);
4792 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4793
4794 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4795 File_Reading(buf, Value);
4796 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4797
4798 output_struct->wifi_UnicastPacketsSent = 0;
4799 output_struct->wifi_UnicastPacketsReceived = 0;
4800 output_struct->wifi_MulticastPacketsSent = 0;
4801 output_struct->wifi_MulticastPacketsReceived = 0;
4802 output_struct->wifi_BroadcastPacketsSent = 0;
4803 output_struct->wifi_BroadcastPacketsRecevied = 0;
4804 output_struct->wifi_UnknownPacketsReceived = 0;
4805
4806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4807 return RETURN_OK;
4808}
4809
4810INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4811{
4812 INT status = RETURN_ERR;
4813
4814 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4815 //Below values should get updated from hal
4816 output_struct->wifi_RetransCount=0;
4817 output_struct->wifi_FailedRetransCount=0;
4818 output_struct->wifi_RetryCount=0;
4819 output_struct->wifi_MultipleRetryCount=0;
4820 output_struct->wifi_ACKFailureCount=0;
4821 output_struct->wifi_AggregatedPacketCount=0;
4822
4823 status = RETURN_OK;
4824 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4825
4826 return status;
4827}
4828
4829INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4830{
4831 INT status = RETURN_ERR;
4832 UINT index;
4833 wifi_neighbor_ap_t *pt=NULL;
4834
4835 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4836 *output_array_size=2;
4837 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4838 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4839 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4840 strcpy(pt->ap_Radio,"");
4841 strcpy(pt->ap_SSID,"");
4842 strcpy(pt->ap_BSSID,"");
4843 strcpy(pt->ap_Mode,"");
4844 pt->ap_Channel=1;
4845 pt->ap_SignalStrength=0;
4846 strcpy(pt->ap_SecurityModeEnabled,"");
4847 strcpy(pt->ap_EncryptionMode,"");
4848 strcpy(pt->ap_OperatingFrequencyBand,"");
4849 strcpy(pt->ap_SupportedStandards,"");
4850 strcpy(pt->ap_OperatingStandards,"");
4851 strcpy(pt->ap_OperatingChannelBandwidth,"");
4852 pt->ap_BeaconPeriod=1;
4853 pt->ap_Noise=0;
4854 strcpy(pt->ap_BasicDataTransferRates,"");
4855 strcpy(pt->ap_SupportedDataTransferRates,"");
4856 pt->ap_DTIMPeriod=1;
4857 pt->ap_ChannelUtilization = 1;
4858 }
4859
4860 status = RETURN_OK;
4861 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4862
4863 return status;
4864}
4865
4866//----------------- AP HAL -------------------------------
4867
4868//>> Deprecated: used for old RDKB code.
4869INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4870{
4871 if (NULL == output_ulong || NULL == output_struct)
4872 return RETURN_ERR;
4873 *output_ulong = 0;
4874 *output_struct = NULL;
4875 return RETURN_OK;
4876}
4877
4878#ifdef HAL_NETLINK_IMPL
4879static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4880 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4881 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4882 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4883 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4884 char mac_addr[20];
4885 static int count=0;
4886 int rate=0;
4887
4888 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4889
4890 nla_parse(tb,
4891 NL80211_ATTR_MAX,
4892 genlmsg_attrdata(gnlh, 0),
4893 genlmsg_attrlen(gnlh, 0),
4894 NULL);
4895
4896 if(!tb[NL80211_ATTR_STA_INFO]) {
4897 fprintf(stderr, "sta stats missing!\n");
4898 return NL_SKIP;
4899 }
4900
4901
4902 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4903 fprintf(stderr, "failed to parse nested attributes!\n");
4904 return NL_SKIP;
4905 }
4906
4907 //devIndex starts from 1
4908 if( ++count == out->wifi_devIndex )
4909 {
4910 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4911 //Getting the mac addrress
4912 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4913
4914 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4915 fprintf(stderr, "failed to parse nested rate attributes!");
4916 return NL_SKIP;
4917 }
4918
4919 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4920 if(rinfo[NL80211_RATE_INFO_BITRATE])
4921 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4922 out->wifi_devTxRate = rate/10;
4923 }
4924
4925 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4926 fprintf(stderr, "failed to parse nested rate attributes!");
4927 return NL_SKIP;
4928 }
4929
4930 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4931 if(rinfo[NL80211_RATE_INFO_BITRATE])
4932 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4933 out->wifi_devRxRate = rate/10;
4934 }
4935 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4936 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4937
4938 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4939 count = 0; //starts the count for next cycle
4940 return NL_STOP;
4941 }
4942
4943 return NL_SKIP;
4944
4945}
4946#endif
4947
4948INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4949{
4950#ifdef HAL_NETLINK_IMPL
4951 Netlink nl = {0};
4952 char if_name[10] = {0};
4953 char interface_name[16] = {0};
4954
4955 wifi_device_info_t info = {0};
4956 info.wifi_devIndex = devIndex;
4957
4958 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4959 return RETURN_ERR;
4960
4961 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4962
4963 nl.id = initSock80211(&nl);
4964
4965 if (nl.id < 0) {
4966 fprintf(stderr, "Error initializing netlink \n");
4967 return -1;
4968 }
4969
4970 struct nl_msg* msg = nlmsg_alloc();
4971
4972 if (!msg) {
4973 fprintf(stderr, "Failed to allocate netlink message.\n");
4974 nlfree(&nl);
4975 return -2;
4976 }
4977
4978 genlmsg_put(msg,
4979 NL_AUTO_PORT,
4980 NL_AUTO_SEQ,
4981 nl.id,
4982 0,
4983 NLM_F_DUMP,
4984 NL80211_CMD_GET_STATION,
4985 0);
4986
4987 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4988 nl_send_auto(nl.socket, msg);
4989 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4990 nl_recvmsgs(nl.socket, nl.cb);
4991 nlmsg_free(msg);
4992 nlfree(&nl);
4993
4994 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4995 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4996 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4997 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4998 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4999 return RETURN_OK;
5000#else
5001 //iw utility to retrieve station information
5002#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
5003#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
5004#define MACFILE "/tmp/wifi_AssoMac.txt"
5005#define TXRATEFILE "/tmp/wifi_txrate.txt"
5006#define RXRATEFILE "/tmp/wifi_rxrate.txt"
5007 FILE *file = NULL;
5008 char if_name[10] = {'\0'};
5009 char pipeCmd[256] = {'\0'};
5010 char line[256] = {0};
5011 char interface_name[16] = {0};
5012 int count = 0, device = 0;
5013
5014 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5015 return RETURN_ERR;
5016
5017 snprintf(if_name,sizeof(if_name),"%s", interface_name);
5018
5019 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
5020 file = popen(pipeCmd, "r");
5021
5022 if(file == NULL)
5023 return RETURN_ERR; //popen failed
5024
5025 fgets(line, sizeof line, file);
5026 device = atoi(line);
5027 pclose(file);
5028
5029 if(device == 0)
5030 return RETURN_ERR; //No devices are connected
5031
5032 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
5033 system(pipeCmd);
5034
5035 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
5036
5037 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
5038
5039 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
5040
5041 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
5042
5043 //devIndex starts from 1, ++count
5044 if((file = fopen(SIGNALFILE, "r")) != NULL )
5045 {
5046 for(count =0;fgets(line, sizeof line, file) != NULL;)
5047 {
5048 if (++count == devIndex)
5049 {
5050 output_struct->wifi_devSignalStrength = atoi(line);
5051 break;
5052 }
5053 }
5054 fclose(file);
5055 }
5056 else
5057 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
5058
5059 if((file = fopen(MACFILE, "r")) != NULL )
5060 {
5061 for(count =0;fgets(line, sizeof line, file) != NULL;)
5062 {
5063 if (++count == devIndex)
5064 {
5065 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]);
5066 break;
5067 }
5068 }
5069 fclose(file);
5070 }
5071 else
5072 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
5073
5074 if((file = fopen(TXRATEFILE, "r")) != NULL )
5075 {
5076 for(count =0;fgets(line, sizeof line, file) != NULL;)
5077 {
5078 if (++count == devIndex)
5079 {
5080 output_struct->wifi_devTxRate = atoi(line);
5081 break;
5082 }
5083 }
5084 fclose(file);
5085 }
5086 else
5087 fprintf(stderr,"fopen wifi_txrate.txt failed");
5088
5089 if((file = fopen(RXRATEFILE, "r")) != NULL)
5090 {
5091 for(count =0;fgets(line, sizeof line, file) != NULL;)
5092 {
5093 if (++count == devIndex)
5094 {
5095 output_struct->wifi_devRxRate = atoi(line);
5096 break;
5097 }
5098 }
5099 fclose(file);
5100 }
5101 else
5102 fprintf(stderr,"fopen wifi_rxrate.txt failed");
5103
5104 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
5105
5106 return RETURN_OK;
5107#endif
5108}
5109
5110INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
5111{
5112 if (NULL == device)
5113 return RETURN_ERR;
5114 return RETURN_OK;
5115}
5116//<<
5117
5118
5119//--------------wifi_ap_hal-----------------------------
5120//enables CTS protection for the radio used by this AP
5121INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
5122{
5123 //save config and Apply instantly
5124 return RETURN_ERR;
5125}
5126
5127// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
5128INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
5129{
5130 char config_file[64] = {'\0'};
5131 char buf[64] = {'\0'};
5132 struct params list;
5133
5134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5135 list.name = "ht_coex";
5136 snprintf(buf, sizeof(buf), "%d", enable);
5137 list.value = buf;
5138
5139 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5140 wifi_hostapdWrite(config_file, &list, 1);
5141 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5142
5143 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5144
5145 return RETURN_OK;
5146}
5147
5148//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
5149INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
5150{
5151 char config_file[MAX_BUF_SIZE] = {'\0'};
5152 char buf[MAX_BUF_SIZE] = {'\0'};
5153 struct params list;
5154
5155 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5156 if (threshold < 256 || threshold > 2346 )
5157 return RETURN_ERR;
5158 list.name = "fragm_threshold";
5159 snprintf(buf, sizeof(buf), "%d", threshold);
5160 list.value = buf;
5161
5162 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5163 wifi_hostapdWrite(config_file, &list, 1);
5164 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5165
5166 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5167
5168 return RETURN_OK;
5169}
5170
5171// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
5172INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
5173{
5174 char config_file[64] = {'\0'};
5175 char cmd[512] = {'\0'};
5176 char buf[512] = {'\0'};
5177 char stbc_config[16] = {'\0'};
5178 wifi_band band;
5179 int iterator = 0;
5180 BOOL current_stbc = FALSE;
5181 int ant_count = 0;
5182 int ant_bitmap = 0;
5183 struct params list;
developera1255e42023-05-13 17:45:02 +08005184 char dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08005185
5186 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5187
5188 band = wifi_index_to_band(radioIndex);
5189 if (band == band_invalid)
5190 return RETURN_ERR;
5191
5192 if (band == band_2_4)
5193 iterator = 1;
developera1255e42023-05-13 17:45:02 +08005194 else if ((band == band_5) || (band == band_6))
developer72fb0bb2023-01-11 09:46:29 +08005195 iterator = 2;
5196 else
5197 return RETURN_OK;
5198
5199 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
5200 for (; ant_bitmap > 0; ant_bitmap >>= 1)
5201 ant_count += ant_bitmap & 1;
5202
5203 if (ant_count == 1 && STBC_Enable == TRUE) {
5204 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
5205 return RETURN_OK;
5206 }
5207
5208 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5209
5210 // set ht and vht config
5211 for (int i = 0; i < iterator; i++) {
5212 memset(stbc_config, 0, sizeof(stbc_config));
5213 memset(cmd, 0, sizeof(cmd));
5214 memset(buf, 0, sizeof(buf));
5215 list.name = (i == 0)?"ht_capab":"vht_capab";
5216 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
5217 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
5218 _syscmd(cmd, buf, sizeof(buf));
5219 if (strlen(buf) != 0)
5220 current_stbc = TRUE;
5221 if (current_stbc == STBC_Enable)
5222 continue;
5223
5224 if (STBC_Enable == TRUE) {
5225 // Append the STBC flags in capab config
5226 memset(cmd, 0, sizeof(cmd));
5227 if (i == 0)
5228 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
5229 else
5230 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
5231 _syscmd(cmd, buf, sizeof(buf));
5232 } else if (STBC_Enable == FALSE) {
5233 // Remove the STBC flags and remain other flags in capab
5234 memset(cmd, 0, sizeof(cmd));
5235 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5236 _syscmd(cmd, buf, sizeof(buf));
5237 memset(cmd, 0, sizeof(cmd));
5238 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
5239 _syscmd(cmd, buf, sizeof(buf));
5240 }
5241 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
5242 list.value = buf;
5243 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
5244 }
developera1255e42023-05-13 17:45:02 +08005245 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5246 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_STBC=.*/HT_STBC=%d/g' %s", STBC_Enable, dat_file);
5247 _syscmd(cmd, buf, sizeof(buf));
5248 if ((band == band_5) || (band == band_6)) {
5249 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^VHT_STBC=.*/VHT_STBC=%d/g' %s", STBC_Enable, dat_file);
5250 _syscmd(cmd, buf, sizeof(buf));
5251 }
5252 /*wifi_reloadAp(radioIndex);
5253 the caller do this.*/
developer72fb0bb2023-01-11 09:46:29 +08005254
5255 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5256 return RETURN_OK;
5257}
5258
5259// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
5260INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
5261{
5262 char cmd[128] = {0};
5263 char buf[128] = {0};
5264 char interface_name[16] = {0};
5265
5266 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5267
5268 if(output_bool == NULL)
5269 return RETURN_ERR;
5270
5271 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5272 return RETURN_ERR;
5273
5274 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
5275 _syscmd(cmd, buf, sizeof(buf));
5276
5277 if (strncmp(buf, "1", 1) == 0)
5278 *output_bool = TRUE;
5279 else
5280 *output_bool = FALSE;
5281
5282 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5283 return RETURN_OK;
5284}
5285
5286// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
5287INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
5288{
5289 char config_file[128] = {0};
5290 struct params list = {0};
5291 BOOL enable;
5292
5293 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5294
5295 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
5296 return RETURN_ERR;
5297
5298 if (amsduEnable == enable)
5299 return RETURN_OK;
5300
5301 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5302 list.name = "amsdu";
5303 list.value = amsduEnable? "1":"0";
5304 wifi_hostapdWrite(config_file, &list, 1);
5305 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
5306 wifi_reloadAp(radioIndex);
5307
5308 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5309 return RETURN_OK;
5310}
5311
5312//P2 // outputs the number of Tx streams
5313INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
5314{
5315 char buf[8] = {0};
5316 char cmd[128] = {0};
5317 int phyId = 0;
5318
5319 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5320
5321 phyId = radio_index_to_phy(radioIndex);
5322 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
5323 _syscmd(cmd, buf, sizeof(buf));
5324
5325 *output_int = (INT)strtol(buf, NULL, 16);
5326
5327 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5328
5329 return RETURN_OK;
5330}
5331
5332INT fitChainMask(INT radioIndex, int antcount)
5333{
5334 char buf[128] = {0};
5335 char cmd[128] = {0};
5336 char config_file[64] = {0};
5337 wifi_band band;
5338 struct params list[2] = {0};
5339
5340 band = wifi_index_to_band(radioIndex);
5341 if (band == band_invalid)
5342 return RETURN_ERR;
5343
5344 list[0].name = "he_mu_beamformer";
5345 list[1].name = "he_su_beamformer";
5346
5347 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5348 if (antcount == 1) {
5349 // remove config about multiple antennas
5350 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5351 _syscmd(cmd, buf, sizeof(buf));
5352
5353 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
5354 _syscmd(cmd, buf, sizeof(buf));
5355
5356 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
5357 _syscmd(cmd, buf, sizeof(buf));
5358
5359 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
5360 _syscmd(cmd, buf, sizeof(buf));
5361
5362 list[0].value = "0";
5363 list[1].value = "0";
5364 } else {
5365 // 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.
5366 if (band == band_2_4 || band == band_5) {
5367 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5368 _syscmd(cmd, buf, sizeof(buf));
5369 if (strlen(buf) > 0) {
5370 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
5371 _syscmd(cmd, buf, sizeof(buf));
5372 }
5373 }
5374 if (band == band_5) {
5375 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5376 _syscmd(cmd, buf, sizeof(buf));
5377 if (strlen(buf) > 0) {
5378 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
5379 _syscmd(cmd, buf, sizeof(buf));
5380 }
5381 }
5382
5383 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
5384 _syscmd(cmd, buf, sizeof(buf));
5385 if (strlen(buf) == 0) {
5386 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
5387 _syscmd(cmd, buf, sizeof(buf));
5388 }
5389
5390 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
5391 _syscmd(cmd, buf, sizeof(buf));
5392 if (strlen(buf) == 0) {
5393 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
5394 _syscmd(cmd, buf, sizeof(buf));
5395 }
5396
5397 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
5398 _syscmd(cmd, buf, sizeof(buf));
5399 if (strlen(buf) == 0) {
5400 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
5401 } else {
5402 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
5403 }
5404 _syscmd(cmd, buf, sizeof(buf));
5405
5406 list[0].value = "1";
5407 list[1].value = "1";
5408 }
5409 wifi_hostapdWrite(config_file, list, 2);
5410}
5411
5412//P2 // sets the number of Tx streams to an enviornment variable
5413INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5414{
5415 char cmd[128] = {0};
5416 char buf[128] = {0};
5417 int phyId = 0;
5418 int cur_mask = 0;
developera1255e42023-05-13 17:45:02 +08005419 int antcountmsk = 0;
5420 INT cur_nss = 0;
5421 UCHAR dat_file[64] = {0};
5422 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08005423
5424 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5425
5426 if (numStreams <= 0) {
5427 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
5428 return RETURN_ERR;
5429 }
5430
developera1255e42023-05-13 17:45:02 +08005431 wifi_getRadioTxChainMask(radioIndex, &cur_mask);//this is mask value
5432 for(; cur_mask > 0; cur_mask >>= 1)//convert to number of streams.
5433 cur_nss += 1;
5434 WIFI_ENTRY_EXIT_DEBUG("%s:cur_nss=%d, new_nss=%d\n", __func__, cur_nss, numStreams);
5435 if (cur_nss == numStreams)
developer72fb0bb2023-01-11 09:46:29 +08005436 return RETURN_OK;
5437
5438 wifi_setRadioEnable(radioIndex, FALSE);
5439
5440 phyId = radio_index_to_phy(radioIndex);
developera1255e42023-05-13 17:45:02 +08005441 //iw need mask value.
5442 for (;numStreams > 0; numStreams--)
5443 antcountmsk |= 0x1 << (numStreams - 1);
5444 snprintf(cmd, sizeof(cmd), "iw phy%d set antenna 0x%x 2>&1", phyId, antcountmsk);
developer72fb0bb2023-01-11 09:46:29 +08005445 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005446 if (strlen(buf) > 0) {
5447 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5448 return RETURN_ERR;
5449 }
developera1255e42023-05-13 17:45:02 +08005450 band = wifi_index_to_band(radioIndex);
5451 if (band == band_invalid) {
5452 printf("%s:Band Error\n", __func__);
5453 return RETURN_ERR;
5454 }
5455 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5456 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_TxStream=.*/HT_TxStream=%d/g' %s", numStreams, dat_file);
5457 _syscmd(cmd, buf, sizeof(buf));
5458 if (strlen(buf) > 0) {
5459 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5460 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08005461 }
developera1255e42023-05-13 17:45:02 +08005462 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_RxStream=.*/HT_RxStream=%d/g' %s", numStreams, dat_file);
5463 _syscmd(cmd, buf, sizeof(buf));
5464 if (strlen(buf) > 0) {
5465 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5466 return RETURN_ERR;
5467 }
5468 fitChainMask(radioIndex, numStreams);
developer72fb0bb2023-01-11 09:46:29 +08005469 wifi_setRadioEnable(radioIndex, TRUE);
5470
5471 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5472 return RETURN_OK;
5473}
5474
5475//P2 // outputs the number of Rx streams
5476INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5477{
5478 char buf[8] = {0};
5479 char cmd[128] = {0};
5480 int phyId = 0;
5481
5482 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5483
5484 phyId = radio_index_to_phy(radioIndex);
5485 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5486 _syscmd(cmd, buf, sizeof(buf));
5487
5488 *output_int = (INT)strtol(buf, NULL, 16);
5489
5490 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5491
5492 return RETURN_OK;
5493}
5494
5495//P2 // sets the number of Rx streams to an enviornment variable
5496INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5497{
5498 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5499 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5500 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5501 return RETURN_ERR;
5502 }
5503 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5504 return RETURN_ERR;
5505}
5506
5507//Get radio RDG enable setting
5508INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5509{
5510 if (NULL == output_bool)
5511 return RETURN_ERR;
5512 *output_bool = TRUE;
5513 return RETURN_OK;
5514}
5515
5516//Get radio RDG enable setting
5517INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5518{
5519 if (NULL == output_bool)
5520 return RETURN_ERR;
5521 *output_bool = TRUE;
5522 return RETURN_OK;
5523}
5524
5525//Set radio RDG enable setting
5526INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5527{
5528 return RETURN_ERR;
5529}
5530
5531//Get radio ADDBA enable setting
5532INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5533{
5534 if (NULL == output_bool)
5535 return RETURN_ERR;
5536 *output_bool = TRUE;
5537 return RETURN_OK;
5538}
5539
5540//Set radio ADDBA enable setting
5541INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5542{
5543 return RETURN_ERR;
5544}
5545
5546//Get radio auto block ack enable setting
5547INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5548{
5549 if (NULL == output_bool)
5550 return RETURN_ERR;
5551 *output_bool = TRUE;
5552 return RETURN_OK;
5553}
5554
5555//Set radio auto block ack enable setting
5556INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5557{
5558 return RETURN_ERR;
5559}
5560
5561//Get radio 11n pure mode enable support
5562INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5563{
5564 if (NULL == output_bool)
5565 return RETURN_ERR;
5566 *output_bool = TRUE;
5567 return RETURN_OK;
5568}
5569
5570//Get radio 11n pure mode enable setting
5571INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5572{
5573 if (NULL == output_bool)
5574 return RETURN_ERR;
5575 *output_bool = TRUE;
5576 return RETURN_OK;
5577}
5578
5579//Set radio 11n pure mode enable setting
5580INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5581{
5582 return RETURN_ERR;
5583}
5584
5585//Get radio IGMP snooping enable setting
5586INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5587{
5588 char interface_name[16] = {0};
5589 char cmd[128]={0};
5590 char buf[4]={0};
5591 bool bridge = FALSE, mac80211 = FALSE;
5592 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5593
5594 if(output_bool == NULL)
5595 return RETURN_ERR;
5596
5597 *output_bool = FALSE;
5598
5599 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5600 _syscmd(cmd, buf, sizeof(buf));
5601 if (strncmp(buf, "1", 1) == 0)
5602 bridge = TRUE;
5603
5604 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5605 return RETURN_ERR;
5606 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
5607 _syscmd(cmd, buf, sizeof(buf));
5608 if (strncmp(buf, "1", 1) == 0)
5609 mac80211 = TRUE;
5610
5611 if (bridge && mac80211)
5612 *output_bool = TRUE;
5613
5614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5615 return RETURN_OK;
5616}
5617
5618//Set radio IGMP snooping enable setting
5619INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5620{
5621 char interface_name[16] = {0};
5622 char cmd[128]={0};
5623 char buf[4]={0};
5624 int max_num_radios =0;
5625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5626
5627 // bridge
5628 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
5629 _syscmd(cmd, buf, sizeof(buf));
5630
5631 wifi_getMaxRadioNumber(&max_num_radios);
5632 // mac80211
5633 for (int i = 0; i < max_num_radios; i++) {
5634 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
5635 return RETURN_ERR;
5636 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
5637 _syscmd(cmd, buf, sizeof(buf));
5638 }
5639 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5640 return RETURN_OK;
5641}
5642
5643//Get the Reset count of radio
developer69b61b02023-03-07 17:17:44 +08005644INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
developer72fb0bb2023-01-11 09:46:29 +08005645{
developer69b61b02023-03-07 17:17:44 +08005646 if (NULL == output_int)
developer72fb0bb2023-01-11 09:46:29 +08005647 return RETURN_ERR;
5648 *output_int = (radioIndex==0)? 1: 3;
5649
5650 return RETURN_OK;
5651}
5652
5653
5654//---------------------------------------------------------------------------------------------------
5655//
5656// Additional Wifi AP level APIs used for Access Point devices
5657//
5658//---------------------------------------------------------------------------------------------------
5659
5660// creates a new ap and pushes these parameters to the hardware
5661INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5662{
5663 // Deprecated when use hal version 3, use wifi_createVap() instead.
5664 return RETURN_OK;
5665}
5666
5667// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5668INT wifi_deleteAp(INT apIndex)
5669{
developer7e4a2a62023-04-06 19:56:03 +08005670 char interface_name[16] = {0};
5671 char buf[MAX_BUF_SIZE];
5672 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08005673
developer7e4a2a62023-04-06 19:56:03 +08005674 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5675 return RETURN_ERR;
developer8a3bbbf2023-03-15 17:47:23 +08005676
developer7e4a2a62023-04-06 19:56:03 +08005677 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
5678 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005679
developer7e4a2a62023-04-06 19:56:03 +08005680 wifi_removeApSecVaribles(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005681
developer7e4a2a62023-04-06 19:56:03 +08005682 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005683}
5684
5685// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5686INT wifi_getApName(INT apIndex, CHAR *output_string)
5687{
developer7e4a2a62023-04-06 19:56:03 +08005688 char interface_name[IF_NAME_SIZE] = {0};
5689 char radio_idx = 0;
5690 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08005691
developer7e4a2a62023-04-06 19:56:03 +08005692 if(!output_string)
5693 return RETURN_ERR;
5694
5695 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
5696 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
5697
5698 snprintf(output_string, IF_NAME_SIZE, "%s%d", ext_prefix[radio_idx], bss_idx); // For wifiagent generating data model.
5699 } else
5700 snprintf(output_string, IF_NAME_SIZE, "%s", interface_name);
5701
5702 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005703}
5704
5705// Outputs the index number in that corresponds to the SSID string
5706INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5707{
developer7e4a2a62023-04-06 19:56:03 +08005708 char cmd [128] = {0};
5709 char buf[32] = {0};
5710 char ap_idx = 0;
5711 char *apIndex_str = NULL;
5712 char radio_idx = 0;
5713 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08005714
developer7e4a2a62023-04-06 19:56:03 +08005715 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'",
5716 inputSsidString);
5717 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005718
developer7e4a2a62023-04-06 19:56:03 +08005719 if (strlen(buf)) {
5720 apIndex_str = strtok(buf, "\n");
5721 *output_int = strtoul(apIndex_str, NULL, 10);
5722 return RETURN_OK;
5723 }
developer72fb0bb2023-01-11 09:46:29 +08005724
developer7e4a2a62023-04-06 19:56:03 +08005725 /* If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.*/
5726 if (strstr(inputSsidString, PREFIX_WIFI6G)) {
5727 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI6G));
5728 radio_idx = 2;
5729 } else if (strstr(inputSsidString, PREFIX_WIFI5G)) {
5730 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI5G));
5731 radio_idx = 1;
5732 } else if (strstr(inputSsidString, PREFIX_WIFI2G)) {
5733 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI2G));
5734 radio_idx = 0;
5735 } else {
5736 printf("%s: hostapd conf not find, unknow inf(%s), return ERROR!!!(%d).\n",
5737 __func__, inputSsidString, ap_idx);
5738 *output_int = -1;
5739 return RETURN_ERR;
5740 }
5741
5742 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
5743
5744 if (ap_idx >= 0 && ap_idx < MAX_VAP) {
5745 printf("%s: hostapd conf not find, inf(%s), use inf idx(%d).\n",
5746 __func__, inputSsidString, ap_idx);
5747 *output_int = ap_idx;
5748 return RETURN_OK;
5749 }
5750
5751 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08005752}
5753
5754INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5755{
5756 return wifi_getIndexFromName(inputSsidString, output_int);
5757}
5758
5759// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5760INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5761{
5762 char buf[MAX_BUF_SIZE] = {0};
5763 char cmd[MAX_CMD_SIZE] = {0};
5764 char config_file[MAX_BUF_SIZE] = {0};
5765
5766 if(NULL == output_string)
5767 return RETURN_ERR;
5768
5769 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5770 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5771 if((strcmp(buf,"3")==0))
5772 snprintf(output_string, 32, "WPAand11i");
5773 else if((strcmp(buf,"2")==0))
5774 snprintf(output_string, 32, "11i");
5775 else if((strcmp(buf,"1")==0))
5776 snprintf(output_string, 32, "WPA");
5777 else
5778 snprintf(output_string, 32, "None");
5779
5780 return RETURN_OK;
5781}
5782
5783// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5784INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5785{
5786 char config_file[MAX_BUF_SIZE] = {0};
5787 struct params list;
5788
5789 if (NULL == beaconTypeString)
5790 return RETURN_ERR;
5791 list.name = "wpa";
5792 list.value = "0";
5793
5794 if((strcmp(beaconTypeString,"WPAand11i")==0))
5795 list.value="3";
5796 else if((strcmp(beaconTypeString,"11i")==0))
5797 list.value="2";
5798 else if((strcmp(beaconTypeString,"WPA")==0))
5799 list.value="1";
5800
5801 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5802 wifi_hostapdWrite(config_file, &list, 1);
5803 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5804 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5805 return RETURN_OK;
5806}
5807
5808// sets the beacon interval on the hardware for this AP
5809INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5810{
5811 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5812 struct params params={'\0'};
5813 char buf[MAX_BUF_SIZE] = {'\0'};
5814 char config_file[MAX_BUF_SIZE] = {'\0'};
5815
5816 params.name = "beacon_int";
5817 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5818 params.value = buf;
5819
5820 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5821 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08005822
developer72fb0bb2023-01-11 09:46:29 +08005823 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5824 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5825 return RETURN_OK;
5826}
5827
5828INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5829{
5830 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5831 return RETURN_ERR;
5832 return RETURN_OK;
5833}
5834
5835// Get the packet size threshold supported.
5836INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5837{
5838 //save config and apply instantly
5839 if (NULL == output_bool)
5840 return RETURN_ERR;
5841 *output_bool = TRUE;
5842 return RETURN_OK;
5843}
5844
5845// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5846INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5847{
developer72fb0bb2023-01-11 09:46:29 +08005848 char buf[16] = {0};
5849 char config_file[128] = {0};
5850 struct params param = {0};
5851
5852 if (threshold > 65535) {
5853 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5854 return RETURN_ERR;
5855 }
5856
developer23e71282023-01-18 10:25:19 +08005857 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005858 snprintf(buf, sizeof(buf), "%u", threshold);
5859 param.name = "rts_threshold";
5860 param.value = buf;
5861 wifi_hostapdWrite(config_file, &param, 1);
5862 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5863 wifi_reloadAp(apIndex);
5864
5865 return RETURN_OK;
5866}
5867
5868// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5869INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5870{
5871 if (NULL == output_string)
5872 return RETURN_ERR;
5873 snprintf(output_string, 32, "TKIPandAESEncryption");
5874 return RETURN_OK;
5875
5876}
5877
5878// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5879INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5880{
5881 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5882 char *param_name = NULL;
5883 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
5884
5885 if(NULL == output_string)
5886 return RETURN_ERR;
5887
5888 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5889 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5890
5891 if(strcmp(buf,"0")==0)
5892 {
5893 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5894 snprintf(output_string, 32, "None");
5895 return RETURN_OK;
5896 }
5897 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5898 param_name = "rsn_pairwise";
5899 else if((strcmp(buf,"1")==0))
5900 param_name = "wpa_pairwise";
5901 else
5902 return RETURN_ERR;
5903 memset(output_string,'\0',32);
5904 wifi_hostapdRead(config_file,param_name,output_string,32);
5905 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5906 param_name = "wpa_pairwise";
5907 memset(output_string, '\0', 32);
5908 wifi_hostapdRead(config_file, param_name, output_string, 32);
5909 }
5910 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5911
5912 if(strcmp(output_string,"TKIP") == 0)
5913 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5914 else if(strcmp(output_string,"CCMP") == 0)
5915 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5916 else if(strcmp(output_string,"TKIP CCMP") == 0)
5917 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5918
5919 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5920 return RETURN_OK;
5921}
5922
5923// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5924INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5925{
5926 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5927 struct params params={'\0'};
5928 char output_string[32];
5929 char config_file[MAX_BUF_SIZE] = {0};
5930
5931 memset(output_string,'\0',32);
5932 wifi_getApWpaEncryptionMode(apIndex,output_string);
5933
5934 if(strcmp(encMode, "TKIPEncryption") == 0)
5935 params.value = "TKIP";
5936 else if(strcmp(encMode,"AESEncryption") == 0)
5937 params.value = "CCMP";
5938 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5939 params.value = "TKIP CCMP";
5940
5941 if((strcmp(output_string,"WPAand11i")==0))
5942 {
5943 params.name = "wpa_pairwise";
5944 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5945 wifi_hostapdWrite(config_file, &params, 1);
5946 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5947
5948 params.name = "rsn_pairwise";
5949 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5950 wifi_hostapdWrite(config_file, &params, 1);
5951 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5952
5953 return RETURN_OK;
5954 }
5955 else if((strcmp(output_string,"11i")==0))
5956 {
5957 params.name = "rsn_pairwise";
5958 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5959 wifi_hostapdWrite(config_file, &params, 1);
5960 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5961 return RETURN_OK;
5962 }
5963 else if((strcmp(output_string,"WPA")==0))
5964 {
5965 params.name = "wpa_pairwise";
5966 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5967 wifi_hostapdWrite(config_file, &params, 1);
5968 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5969 return RETURN_OK;
5970 }
5971
5972 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5973 return RETURN_OK;
5974}
5975
5976// deletes internal security varable settings for this ap
5977INT wifi_removeApSecVaribles(INT apIndex)
5978{
5979 //TODO: remove the entry in hostapd config file
5980 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
5981 //_syscmd(cmd, buf, sizeof(buf));
5982
5983 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
5984 //_syscmd(cmd, buf, sizeof(buf));
5985 return RETURN_ERR;
5986}
5987
5988// changes the hardware settings to disable encryption on this ap
5989INT wifi_disableApEncryption(INT apIndex)
5990{
5991 //Apply instantly
5992 return RETURN_ERR;
5993}
5994
5995// set the authorization mode on this ap
5996// mode mapping as: 1: open, 2: shared, 4:auto
5997INT wifi_setApAuthMode(INT apIndex, INT mode)
5998{
5999 struct params params={0};
6000 char config_file[64] = {0};
6001 int ret;
6002
6003 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6004
6005 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
6006 params.name = "auth_algs";
6007
6008 if (mode & 1 && mode & 2)
6009 params.value = "3";
6010 else if (mode & 2)
6011 params.value = "2";
6012 else if (mode & 1)
6013 params.value = "1";
6014 else
6015 params.value = "0";
6016
6017 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6018 wifi_hostapdWrite(config_file, &params, 1);
6019 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6020 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6021
6022 return RETURN_OK;
6023}
6024
6025// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
6026INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
6027{
6028 //save to wifi config, and wait for wifi restart to apply
6029 struct params params={'\0'};
6030 char config_file[MAX_BUF_SIZE] = {0};
6031 int ret;
6032
6033 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6034 if(authMode == NULL)
6035 return RETURN_ERR;
6036
6037 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
6038 params.name = "wpa_key_mgmt";
6039
6040 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
6041 params.value = "WPA-PSK";
6042 else if(strcmp(authMode,"EAPAuthentication") == 0)
6043 params.value = "WPA-EAP";
6044 else if (strcmp(authMode, "SAEAuthentication") == 0)
6045 params.value = "SAE";
6046 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
6047 params.value = "WPA-EAP-SUITE-B-192";
6048 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
6049 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08006050 else if (strcmp(authMode, "Enhanced_Open") == 0)
6051 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08006052 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
6053 return RETURN_OK; //This is taken careof in beaconType
6054
6055 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6056 ret=wifi_hostapdWrite(config_file,&params,1);
6057 if(!ret)
6058 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
6059 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6060
6061 return ret;
6062}
6063
6064// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
6065INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
6066{
6067 //save to wifi config, and wait for wifi restart to apply
6068 char BeaconType[50] = {0};
6069 char config_file[MAX_BUF_SIZE] = {0};
6070
6071 *authMode = 0;
6072 wifi_getApBeaconType(apIndex,BeaconType);
6073 printf("%s____%s \n",__FUNCTION__,BeaconType);
6074
6075 if(strcmp(BeaconType,"None") == 0)
6076 strcpy(authMode,"None");
6077 else
6078 {
6079 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6080 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
6081 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
6082 if(strcmp(authMode,"WPA-PSK") == 0)
6083 strcpy(authMode,"SharedAuthentication");
6084 else if(strcmp(authMode,"WPA-EAP") == 0)
6085 strcpy(authMode,"EAPAuthentication");
6086 }
6087
6088 return RETURN_OK;
6089}
6090
6091// Outputs the number of stations associated per AP
6092INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
6093{
6094 char interface_name[16] = {0};
6095 char cmd[128]={0};
6096 char buf[128]={0};
6097 BOOL status = false;
6098
6099 if(apIndex > MAX_APS)
6100 return RETURN_ERR;
6101
6102 wifi_getApEnable(apIndex,&status);
6103 if (!status)
6104 return RETURN_OK;
6105
6106 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
6107 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6108 return RETURN_ERR;
6109 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
6110 _syscmd(cmd, buf, sizeof(buf));
6111 sscanf(buf,"%lu", output_ulong);
6112
6113 return RETURN_OK;
6114}
6115
6116// manually removes any active wi-fi association with the device specified on this ap
6117INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
6118{
developer7e4a2a62023-04-06 19:56:03 +08006119 char inf_name[16] = {0};
6120 char cmd[MAX_CMD_SIZE] = {0};
6121 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006122
developer7e4a2a62023-04-06 19:56:03 +08006123 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08006124 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08006125
6126 snprintf(cmd, sizeof(cmd),"hostapd_cli -i %s disassociate %s", inf_name, client_mac);
6127 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006128
6129 return RETURN_OK;
6130}
6131
6132// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
6133INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
6134{
developer7e4a2a62023-04-06 19:56:03 +08006135 int max_radio_num = 0;
6136
6137 if(NULL == output_int)
6138 return RETURN_ERR;
6139
6140 wifi_getMaxRadioNumber(&max_radio_num);
6141 *output_int = apIndex % max_radio_num;
6142
6143 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006144}
6145
6146// sets the radio index for the specific ap
6147INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
6148{
6149 //set to config only and wait for wifi reset to apply settings
6150 return RETURN_ERR;
6151}
6152
6153// Get the ACL MAC list per AP
6154INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
6155{
developer7e4a2a62023-04-06 19:56:03 +08006156 char cmd[MAX_CMD_SIZE] = {0};
6157 char buf[MAX_BUF_SIZE] = {0};
6158 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006159
developer7e4a2a62023-04-06 19:56:03 +08006160 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6161 return RETURN_ERR;
6162
6163 /* mwctl acl del sta */
6164 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | grep ':'", inf_name);
6165 _syscmd(cmd, buf, sizeof(buf));
6166
6167 memcpy(macArray, buf, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08006168
6169 return RETURN_OK;
6170}
6171
6172INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
6173{
developer72fb0bb2023-01-11 09:46:29 +08006174
developer7e4a2a62023-04-06 19:56:03 +08006175 wifi_getApAclDevices(apIndex, macArray, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08006176
6177 return RETURN_OK;
6178}
6179
6180
6181// Get the list of stations associated per AP
6182INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
6183{
developer7e4a2a62023-04-06 19:56:03 +08006184 char interface_name[IF_NAME_SIZE] = {0};
6185 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08006186
developer7e4a2a62023-04-06 19:56:03 +08006187 if(apIndex > 3) //Currently supporting apIndex upto 3
6188 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006189
developer7e4a2a62023-04-06 19:56:03 +08006190 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6191 return RETURN_ERR;
6192
6193 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s list_sta", interface_name);
6194 _syscmd(cmd, macArray, buf_size);
6195 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006196}
6197
6198// adds the mac address to the filter list
6199//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
6200INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
6201{
developer7e4a2a62023-04-06 19:56:03 +08006202 char cmd[MAX_CMD_SIZE] = {0};
6203 char buf[MAX_BUF_SIZE] = {0};
6204 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006205
developer7e4a2a62023-04-06 19:56:03 +08006206 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6207 return RETURN_ERR;
6208
6209 if (!DeviceMacAddress)
6210 return RETURN_ERR;
6211
6212 /* mwctl acl add sta */
6213 snprintf(cmd, sizeof(cmd), "mwctl %s acl add=%s", inf_name, DeviceMacAddress);
6214 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006215
6216 return RETURN_OK;
6217}
6218
6219// deletes the mac address from the filter list
6220//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
6221INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
6222{
developer7e4a2a62023-04-06 19:56:03 +08006223 char cmd[MAX_CMD_SIZE] = {0};
6224 char buf[MAX_BUF_SIZE] = {0};
6225 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006226
developer7e4a2a62023-04-06 19:56:03 +08006227 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6228 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006229
developer7e4a2a62023-04-06 19:56:03 +08006230 if (!DeviceMacAddress)
6231 return RETURN_ERR;
6232
6233 /* mwctl acl del sta */
6234 snprintf(cmd, sizeof(cmd), "mwctl %s acl del=%s", inf_name, DeviceMacAddress);
6235 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006236
6237 return RETURN_OK;
6238}
6239
6240// outputs the number of devices in the filter list
6241INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
6242{
developer7e4a2a62023-04-06 19:56:03 +08006243 char cmd[MAX_CMD_SIZE] = {0};
6244 char buf[MAX_BUF_SIZE] = {0};
6245 char inf_name[IF_NAME_SIZE] = {0};
6246 char sta_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08006247
developer72fb0bb2023-01-11 09:46:29 +08006248 if(output_uint == NULL)
6249 return RETURN_ERR;
6250
developer7e4a2a62023-04-06 19:56:03 +08006251 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6252 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006253
developer7e4a2a62023-04-06 19:56:03 +08006254 /* mwctl acl get sta num */
6255 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | wc -l | tr -d '\\n'", inf_name);
6256 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006257
developer7e4a2a62023-04-06 19:56:03 +08006258 if (atoi(buf) > 1)
6259 *output_uint = atoi(buf) - 1; /*except the line of acl_policy*/
6260 else {
6261 *output_uint = 0;
6262 printf("%s: acl get wrong return content!!!\n", __func__);
6263 }
6264
6265 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006266}
6267
6268INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
6269{
6270 char cmd[128]={'\0'};
6271 char buf[128]={'\0'};
6272
6273 if(strcmp(action,"DENY")==0)
6274 {
6275 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
6276 system(buf);
6277 return RETURN_OK;
6278 }
6279
6280 if(strcmp(action,"ALLOW")==0)
6281 {
6282 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
6283 system(buf);
6284 return RETURN_OK;
6285 }
6286
6287 return RETURN_ERR;
6288
6289}
6290
6291// enable kick for devices on acl black list
6292INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
6293{
6294 char aclArray[512] = {0}, *acl = NULL;
6295 char assocArray[512] = {0}, *asso = NULL;
6296
6297 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
6298 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
6299
developer7e4a2a62023-04-06 19:56:03 +08006300 /* if there are no devices connected there is nothing to do */
developer72fb0bb2023-01-11 09:46:29 +08006301 if (strlen(assocArray) < 17)
6302 return RETURN_OK;
6303
developer7e4a2a62023-04-06 19:56:03 +08006304 if (enable == TRUE) {
6305 /* kick off the MAC which is in ACL array (deny list) */
6306 acl = strtok(aclArray, "\n");
developer72fb0bb2023-01-11 09:46:29 +08006307 while (acl != NULL) {
6308 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
6309 wifi_kickApAssociatedDevice(apIndex, acl);
6310
developer7e4a2a62023-04-06 19:56:03 +08006311 acl = strtok(NULL, "\n");
developer72fb0bb2023-01-11 09:46:29 +08006312 }
6313 wifi_setApMacAddressControlMode(apIndex, 2);
developer7e4a2a62023-04-06 19:56:03 +08006314 } else
developer72fb0bb2023-01-11 09:46:29 +08006315 wifi_setApMacAddressControlMode(apIndex, 0);
developer72fb0bb2023-01-11 09:46:29 +08006316
developer72fb0bb2023-01-11 09:46:29 +08006317 return RETURN_OK;
6318}
6319
6320INT wifi_setPreferPrivateConnection(BOOL enable)
6321{
6322 return RETURN_OK;
6323}
6324
6325// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
6326INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
6327{
developer7e4a2a62023-04-06 19:56:03 +08006328 char inf_name[IF_NAME_SIZE] = {0};
6329 char cmd[MAX_CMD_SIZE] = {0};
6330 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006331
developer7e4a2a62023-04-06 19:56:03 +08006332 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6333 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006334
developer7e4a2a62023-04-06 19:56:03 +08006335 /*mwctl set acl policy*/
6336 snprintf(cmd, sizeof(cmd), "mwctl %s acl policy=%d", inf_name, filterMode);
6337 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006338
developer7e4a2a62023-04-06 19:56:03 +08006339 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006340}
6341
6342// 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.
6343INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6344{
6345 return RETURN_ERR;
6346}
6347
6348// gets the vlan ID for this ap from an internal enviornment variable
6349INT wifi_getApVlanID(INT apIndex, INT *output_int)
6350{
6351 if(apIndex==0)
6352 {
6353 *output_int=100;
6354 return RETURN_OK;
6355 }
6356
6357 return RETURN_ERR;
6358}
6359
6360// sets the vlan ID for this ap to an internal enviornment variable
6361INT wifi_setApVlanID(INT apIndex, INT vlanId)
6362{
6363 //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)
6364 return RETURN_ERR;
6365}
6366
6367// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6368INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6369{
6370 snprintf(bridgeName, 32, "brlan0");
6371 snprintf(IP, 32, "10.0.0.1");
6372 snprintf(subnet, 32, "255.255.255.0");
6373
6374 return RETURN_OK;
6375}
6376
6377//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6378INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6379{
6380 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6381 return RETURN_ERR;
6382}
6383
6384// reset the vlan configuration for this ap
6385INT wifi_resetApVlanCfg(INT apIndex)
6386{
6387 char original_config_file[64] = {0};
6388 char current_config_file[64] = {0};
6389 char buf[64] = {0};
6390 char cmd[64] = {0};
6391 char vlan_file[64] = {0};
6392 char vlan_tagged_interface[16] = {0};
6393 char vlan_bridge[16] = {0};
6394 char vlan_naming[16] = {0};
6395 struct params list[4] = {0};
6396 wifi_band band;
developera1255e42023-05-13 17:45:02 +08006397 char interface_name[16] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006398
6399 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006400 band = wifi_index_to_band(apIndex);
6401 if (band == band_2_4)
developera1255e42023-05-13 17:45:02 +08006402 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-2G.conf");
developer72fb0bb2023-01-11 09:46:29 +08006403 else if (band == band_5)
developera1255e42023-05-13 17:45:02 +08006404 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-5G.conf");
developer72fb0bb2023-01-11 09:46:29 +08006405 else if (band == band_6)
developera1255e42023-05-13 17:45:02 +08006406 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-6G.conf");
developer72fb0bb2023-01-11 09:46:29 +08006407
6408 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6409
6410 if (strlen(vlan_file) == 0)
6411 strcpy(vlan_file, VLAN_FILE);
6412
6413 // The file should exist or this vap would not work.
6414 if (access(vlan_file, F_OK) != 0) {
developera1255e42023-05-13 17:45:02 +08006415 snprintf(cmd, sizeof(cmd), "touch %s", vlan_file);
developer72fb0bb2023-01-11 09:46:29 +08006416 _syscmd(cmd, buf, sizeof(buf));
6417 }
6418 list[0].name = "vlan_file";
6419 list[0].value = vlan_file;
6420
6421 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6422 list[1].name = "vlan_tagged_interface";
6423 list[1].value = vlan_tagged_interface;
6424
6425 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6426 list[2].name = "vlan_bridge";
6427 list[2].value = vlan_bridge;
6428
6429 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6430 list[3].name = "vlan_naming";
6431 list[3].value = vlan_naming;
6432
developera1255e42023-05-13 17:45:02 +08006433 snprintf(current_config_file, sizeof(current_config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006434 wifi_hostapdWrite(current_config_file, list, 4);
6435 //Reapply vlan settings
6436 // wifi_pushBridgeInfo(apIndex);
6437
6438 // restart this ap
6439 wifi_setApEnable(apIndex, FALSE);
6440 wifi_setApEnable(apIndex, TRUE);
developera1255e42023-05-13 17:45:02 +08006441 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6442 return RETURN_ERR;
6443 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_tag 0\n", interface_name);
6444 _syscmd(cmd, buf, sizeof(buf));
6445 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_priority 0\n", interface_name);
6446 _syscmd(cmd, buf, sizeof(buf));
6447 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_id 0\n", interface_name);
6448 _syscmd(cmd, buf, sizeof(buf));
6449 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_en 0\n", interface_name);
6450 _syscmd(cmd, buf, sizeof(buf));
6451 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_policy 0:4\n", interface_name);
6452 _syscmd(cmd, buf, sizeof(buf));
6453 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_policy 1:0\n", interface_name);
6454 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6456
6457 return RETURN_OK;
6458}
6459
6460// 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.
6461INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6462{
6463 return RETURN_ERR;
6464}
6465
6466// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6467INT wifi_startHostApd()
6468{
6469 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6470 system("systemctl start hostapd.service");
6471 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6472 return RETURN_OK;
6473 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6474}
6475
6476// stops hostapd
developer69b61b02023-03-07 17:17:44 +08006477INT wifi_stopHostApd()
developer72fb0bb2023-01-11 09:46:29 +08006478{
6479 char cmd[128] = {0};
6480 char buf[128] = {0};
6481
6482 sprintf(cmd,"systemctl stop hostapd");
6483 _syscmd(cmd, buf, sizeof(buf));
6484
6485 return RETURN_OK;
6486}
6487
6488// restart hostapd dummy function
6489INT wifi_restartHostApd()
6490{
6491 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6492 system("systemctl restart hostapd-global");
6493 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6494
6495 return RETURN_OK;
6496}
6497
6498static int align_hostapd_config(int index)
6499{
6500 ULONG lval;
6501 wifi_getRadioChannel(index%2, &lval);
6502 wifi_setRadioChannel(index%2, lval);
6503 return RETURN_OK;
6504}
6505
6506// sets the AP enable status variable for the specified ap.
6507INT wifi_setApEnable(INT apIndex, BOOL enable)
6508{
developer7e4a2a62023-04-06 19:56:03 +08006509 char interface_name[16] = {0};
6510 char config_file[MAX_BUF_SIZE] = {0};
6511 char cmd[MAX_CMD_SIZE] = {0};
6512 char buf[MAX_BUF_SIZE] = {0};
6513 BOOL status;
6514 int max_radio_num = 0;
6515 int phyId = 0;
developer72fb0bb2023-01-11 09:46:29 +08006516
developer7e4a2a62023-04-06 19:56:03 +08006517 wifi_getApEnable(apIndex, &status);
developer72fb0bb2023-01-11 09:46:29 +08006518
developer7e4a2a62023-04-06 19:56:03 +08006519 wifi_getMaxRadioNumber(&max_radio_num);
6520 if (enable == status)
6521 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006522
developer7e4a2a62023-04-06 19:56:03 +08006523 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6524 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006525
developer7e4a2a62023-04-06 19:56:03 +08006526 if (enable == TRUE) {
6527 int radioIndex = apIndex % max_radio_num;
6528 phyId = radio_index_to_phy(radioIndex);
developer8a3bbbf2023-03-15 17:47:23 +08006529
developer7e4a2a62023-04-06 19:56:03 +08006530 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
6531 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
6532 _syscmd(cmd, buf, sizeof(buf));
6533 } else {
6534 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
6535 _syscmd(cmd, buf, sizeof(buf));
6536 }
6537 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
6538 interface_name, interface_name, enable, VAP_STATUS_FILE);
6539 _syscmd(cmd, buf, sizeof(buf));
6540 //Wait for wifi up/down to apply
6541 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006542}
6543
6544// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6545INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6546{
developer7e4a2a62023-04-06 19:56:03 +08006547 char interface_name[IF_NAME_SIZE] = {0};
6548 char cmd[MAX_CMD_SIZE] = {0};
6549 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006550
developer7e4a2a62023-04-06 19:56:03 +08006551 if ((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6552 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006553
developer7e4a2a62023-04-06 19:56:03 +08006554 *output_bool = 0;
developer72fb0bb2023-01-11 09:46:29 +08006555
developer7e4a2a62023-04-06 19:56:03 +08006556 if ((apIndex >= 0) && (apIndex < MAX_APS)) {
6557 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
6558 *output_bool = FALSE;
6559 return RETURN_OK;
6560 }
6561 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s 2> /dev/null | grep UP", interface_name);
6562 *output_bool = _syscmd(cmd, buf, sizeof(buf)) ? 0 : 1;
6563 }
developer72fb0bb2023-01-11 09:46:29 +08006564
developer7e4a2a62023-04-06 19:56:03 +08006565 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006566}
6567
developer69b61b02023-03-07 17:17:44 +08006568// Outputs the AP "Enabled" "Disabled" status from driver
6569INT wifi_getApStatus(INT apIndex, CHAR *output_string)
developer72fb0bb2023-01-11 09:46:29 +08006570{
developer7e4a2a62023-04-06 19:56:03 +08006571 char cmd[128] = {0};
6572 char buf[128] = {0};
6573 BOOL output_bool;
developer72fb0bb2023-01-11 09:46:29 +08006574
developer7e4a2a62023-04-06 19:56:03 +08006575 if (!output_string) {
6576 printf("%s: null pointer!", __func__);
6577 return RETURN_ERR;
6578 }
developer72fb0bb2023-01-11 09:46:29 +08006579
developer7e4a2a62023-04-06 19:56:03 +08006580 wifi_getApEnable(apIndex, &output_bool);
developer72fb0bb2023-01-11 09:46:29 +08006581
developer7e4a2a62023-04-06 19:56:03 +08006582 if(output_bool == 1)
6583 snprintf(output_string, 32, "Up");
6584 else
6585 snprintf(output_string, 32, "Disable");
6586
6587 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006588}
6589
6590//Indicates whether or not beacons include the SSID name.
6591// outputs a 1 if SSID on the AP is enabled, else outputs 0
6592INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6593{
6594 //get the running status
6595 char config_file[MAX_BUF_SIZE] = {0};
6596 char buf[16] = {0};
6597
6598 if (!output)
6599 return RETURN_ERR;
6600
6601 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6602 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6603 // default is enable
6604 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6605 *output = TRUE;
6606
6607 return RETURN_OK;
6608}
6609
6610// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6611INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6612{
6613 //store the config, apply instantly
6614 char config_file[MAX_BUF_SIZE] = {0};
6615 struct params list;
6616
6617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6618 list.name = "ignore_broadcast_ssid";
6619 list.value = enable?"0":"1";
6620
6621 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6622 wifi_hostapdWrite(config_file, &list, 1);
6623 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6624 //TODO: call hostapd_cli for dynamic_config_control
6625 wifi_reloadAp(apIndex);
6626 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6627
6628 return RETURN_OK;
6629}
6630
6631//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6632INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6633{
6634 //get the running status
6635 if(!output_uint)
6636 return RETURN_ERR;
6637 *output_uint=16;
6638 return RETURN_OK;
6639}
6640
6641INT wifi_setApRetryLimit(INT apIndex, UINT number)
6642{
6643 //apply instantly
6644 return RETURN_ERR;
6645}
6646
6647//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6648INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6649{
6650 if(!output)
6651 return RETURN_ERR;
6652 *output=TRUE;
6653 return RETURN_OK;
6654}
6655
6656//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6657INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6658{
6659 //get the running status from driver
6660 char cmd[128] = {0};
6661 char buf[128] = {0};
6662 int max_radio_num = 0, radioIndex = 0;
6663 int phyId = 0;
6664
6665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6666
6667 wifi_getMaxRadioNumber(&max_radio_num);
6668 radioIndex = apIndex % max_radio_num;
6669 phyId = radio_index_to_phy(radioIndex);
6670 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
6671 _syscmd(cmd,buf, sizeof(buf));
6672
6673 if (strlen(buf) > 0)
6674 *output = true;
6675
6676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6677
6678 return RETURN_OK;
6679}
6680
6681//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6682INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6683{
6684 //get the running status from driver
6685 if(!output)
6686 return RETURN_ERR;
6687
6688 char config_file[MAX_BUF_SIZE] = {0};
6689 char buf[16] = {0};
6690
6691 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6692 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
6693 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6694 *output = TRUE;
6695 else
6696 *output = FALSE;
6697
6698 return RETURN_OK;
6699}
6700
6701// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6702INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6703{
6704 //Save config and apply instantly.
6705 char config_file[MAX_BUF_SIZE] = {0};
6706 struct params list;
6707
6708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6709 list.name = "wmm_enabled";
6710 list.value = enable?"1":"0";
6711
6712 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6713 wifi_hostapdWrite(config_file, &list, 1);
6714 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6715 wifi_reloadAp(apIndex);
6716 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6717
6718 return RETURN_OK;
6719}
6720
6721//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.
6722INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6723{
6724 //get the running status from driver
6725 if(!output)
6726 return RETURN_ERR;
6727
6728 char config_file[128] = {0};
6729 char buf[16] = {0};
6730
6731 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6732 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6733 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6734 *output = TRUE;
6735 else
6736 *output = FALSE;
6737
6738 return RETURN_OK;
6739}
6740
6741// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6742INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6743{
6744 //save config and apply instantly.
6745 char config_file[MAX_BUF_SIZE] = {0};
6746 struct params list;
6747
6748 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6749 list.name = "uapsd_advertisement_enabled";
6750 list.value = enable?"1":"0";
6751
6752 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6753 wifi_hostapdWrite(config_file, &list, 1);
6754 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developere82c0ca2023-05-10 16:25:35 +08006755 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006756 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6757
6758 return RETURN_OK;
6759}
6760
6761// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
6762INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6763{
6764 char interface_name[16] = {0};
6765 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6766 char cmd[128] = {0};
6767 char buf[128] = {0};
6768 char ack_filepath[128] = {0};
6769 uint16_t bitmap = 0;
6770 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6771 FILE *f = NULL;
6772
6773 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6774
6775 // Get current setting
6776 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6777 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6778 _syscmd(cmd, buf, sizeof(buf));
6779 if (strlen(buf) > 0)
6780 bitmap = strtoul(buf, NULL, 10);
6781
6782 bitmap = strtoul(buf, NULL, 10);
6783
6784 if (ackPolicy == TRUE) { // True, unset this class
6785 bitmap &= ~class_map[class];
6786 } else { // False, set this class
6787 bitmap |= class_map[class];
6788 }
6789
6790 f = fopen(ack_filepath, "w");
6791 if (f == NULL) {
6792 fprintf(stderr, "%s: fopen failed\n", __func__);
6793 return RETURN_ERR;
6794 }
6795 fprintf(f, "%hu", bitmap);
6796 fclose(f);
6797
6798 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6799 return RETURN_ERR;
6800 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
6801 _syscmd(cmd, buf, sizeof(buf));
6802
6803 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6804 return RETURN_OK;
6805}
6806
6807//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.
6808INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6809{
6810 //get the running status from driver
6811 if(!output_uint)
6812 return RETURN_ERR;
6813
6814 char output[16]={'\0'};
6815 char config_file[MAX_BUF_SIZE] = {0};
6816
6817 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6818 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6819 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6820 else {
6821 int device_num = atoi(output);
6822 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6823 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6824 return RETURN_ERR;
6825 }
6826 else {
6827 *output_uint = device_num;
6828 }
6829 }
6830
6831 return RETURN_OK;
6832}
6833
6834INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6835{
6836 //store to wifi config, apply instantly
6837 char str[MAX_BUF_SIZE]={'\0'};
6838 char cmd[MAX_CMD_SIZE]={'\0'};
6839 struct params params;
6840 char config_file[MAX_BUF_SIZE] = {0};
6841
6842 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6843 if (number > MAX_ASSOCIATED_STA_NUM) {
6844 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6845 return RETURN_ERR;
6846 }
6847 sprintf(str, "%d", number);
6848 params.name = "max_num_sta";
6849 params.value = str;
6850
6851 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6852 int ret = wifi_hostapdWrite(config_file, &params, 1);
6853 if (ret) {
6854 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6855 ,__func__, ret);
6856 }
6857
6858 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6859 if (ret) {
6860 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6861 ,__func__, ret);
6862 }
6863 wifi_reloadAp(apIndex);
6864 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6865
6866 return RETURN_OK;
6867}
6868
6869//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.
6870INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6871{
6872 //get the current threshold
6873 if(!output_uint)
6874 return RETURN_ERR;
6875 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6876 if (*output_uint == 0)
6877 *output_uint = 50;
6878 return RETURN_OK;
6879}
6880
6881INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6882{
6883 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
6884 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6885 return RETURN_OK;
6886 return RETURN_ERR;
6887}
6888
6889//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.
6890INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6891{
6892 if(!output_uint)
6893 return RETURN_ERR;
6894 *output_uint = 3;
6895 return RETURN_OK;
6896}
6897
6898//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6899INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6900{
6901 if(!output_uint)
6902 return RETURN_ERR;
6903 *output_uint = 3;
6904 return RETURN_OK;
6905}
6906
6907//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.
6908INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6909{
6910 if(!output_in_seconds)
6911 return RETURN_ERR;
6912 *output_in_seconds = 0;
6913 return RETURN_OK;
6914}
6915
6916//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
6917INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6918{
6919 if(!output || apIndex>=MAX_APS)
6920 return RETURN_ERR;
6921 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
6922 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
6923 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08006924}
developer72fb0bb2023-01-11 09:46:29 +08006925
6926//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6927INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6928{
6929 char config_file[128] = {0};
6930 char wpa[16] = {0};
6931 char key_mgmt[64] = {0};
6932 char buf[16] = {0};
6933 if (!output)
6934 return RETURN_ERR;
6935
6936 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6937 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6938
6939 strcpy(output, "None");//Copying "None" to output string for default case
6940 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6941 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
6942 if (!strcmp(wpa, "1"))
6943 snprintf(output, 32, "WPA-Personal");
6944 else if (!strcmp(wpa, "2"))
6945 snprintf(output, 32, "WPA2-Personal");
6946 else if (!strcmp(wpa, "3"))
6947 snprintf(output, 32, "WPA-WPA2-Personal");
6948
6949 } else if (strstr(key_mgmt, "WPA-EAP")) {
6950 if (!strcmp(wpa, "1"))
6951 snprintf(output, 32, "WPA-Enterprise");
6952 else if (!strcmp(wpa, "2"))
6953 snprintf(output, 32, "WPA2-Enterprise");
6954 else if (!strcmp(wpa, "3"))
6955 snprintf(output, 32, "WPA-WPA2-Enterprise");
6956 } else if (strstr(key_mgmt, "SAE")) {
6957 if (strstr(key_mgmt, "WPA-PSK") == NULL)
6958 snprintf(output, 32, "WPA3-Personal");
6959 else
6960 snprintf(output, 32, "WPA3-Personal-Transition");
6961 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6962 snprintf(output, 32, "WPA3-Enterprise");
6963 }
6964
6965 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6966 return RETURN_OK;
6967#if 0
6968 //TODO: need to revisit below implementation
6969 char securityType[32], authMode[32];
6970 int enterpriseMode=0;
6971
6972 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6973 if(!output)
6974 return RETURN_ERR;
6975
6976 wifi_getApBeaconType(apIndex, securityType);
6977 strcpy(output,"None");//By default, copying "None" to output string
6978 if (strncmp(securityType,"None", strlen("None")) == 0)
6979 return RETURN_OK;
6980
6981 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6982 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6983
6984 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6985 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6986 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6987 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6988 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6989 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6990 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6991
6992 return RETURN_OK;
6993#endif
6994}
developer69b61b02023-03-07 17:17:44 +08006995
developer72fb0bb2023-01-11 09:46:29 +08006996INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6997{
6998 char securityType[32];
6999 char authMode[32];
7000
7001 //store settings and wait for wifi up to apply
7002 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7003 if(!encMode)
7004 return RETURN_ERR;
7005
7006 if (strcmp(encMode, "None")==0)
7007 {
7008 strcpy(securityType,"None");
7009 strcpy(authMode,"None");
7010 }
7011 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
7012 {
7013 strcpy(securityType,"WPAand11i");
7014 strcpy(authMode,"PSKAuthentication");
7015 }
7016 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
7017 {
7018 strcpy(securityType,"WPAand11i");
7019 strcpy(authMode,"EAPAuthentication");
7020 }
7021 else if (strcmp(encMode, "WPA-Personal")==0)
7022 {
7023 strcpy(securityType,"WPA");
7024 strcpy(authMode,"PSKAuthentication");
7025 }
7026 else if (strcmp(encMode, "WPA-Enterprise")==0)
7027 {
7028 strcpy(securityType,"WPA");
7029 strcpy(authMode,"EAPAuthentication");
7030 }
7031 else if (strcmp(encMode, "WPA2-Personal")==0)
7032 {
7033 strcpy(securityType,"11i");
7034 strcpy(authMode,"PSKAuthentication");
7035 }
7036 else if (strcmp(encMode, "WPA2-Enterprise")==0)
7037 {
7038 strcpy(securityType,"11i");
7039 strcpy(authMode,"EAPAuthentication");
7040 }
7041 else if (strcmp(encMode, "WPA3-Personal") == 0)
7042 {
7043 strcpy(securityType,"11i");
7044 strcpy(authMode,"SAEAuthentication");
7045 }
7046 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
7047 {
7048 strcpy(securityType, "11i");
7049 strcpy(authMode, "PSK-SAEAuthentication");
7050 }
7051 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
7052 {
7053 strcpy(securityType,"11i");
7054 strcpy(authMode,"EAP_192-bit_Authentication");
7055 }
developer3086e2f2023-01-17 09:40:01 +08007056 else if (strcmp(encMode, "OWE") == 0)
7057 {
7058 strcpy(securityType,"11i");
7059 strcpy(authMode,"Enhanced_Open");
7060 }
developer72fb0bb2023-01-11 09:46:29 +08007061 else
7062 {
7063 strcpy(securityType,"None");
7064 strcpy(authMode,"None");
7065 }
7066 wifi_setApBeaconType(apIndex, securityType);
7067 wifi_setApBasicAuthenticationMode(apIndex, authMode);
7068 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7069
7070 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007071}
developer72fb0bb2023-01-11 09:46:29 +08007072
7073
7074//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
7075// output_string must be pre-allocated as 64 character string by caller
7076// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
7077INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
7078{
7079 char buf[16] = {0};
7080 char config_file[MAX_BUF_SIZE] = {0};
7081
7082 if(output_string==NULL)
7083 return RETURN_ERR;
7084
7085 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7086 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7087
7088 if(strcmp(buf,"0")==0)
7089 {
7090 printf("wpa_mode is %s ......... \n",buf);
7091 return RETURN_ERR;
7092 }
7093
7094 wifi_dbg_printf("\nFunc=%s\n",__func__);
7095 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7096 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
7097 wifi_dbg_printf("\noutput_string=%s\n",output_string);
7098
7099 return RETURN_OK;
7100}
7101
7102// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
7103// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
7104INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
7105{
7106 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
7107 struct params params={'\0'};
7108 int ret;
7109 char config_file[MAX_BUF_SIZE] = {0};
7110
7111 if(NULL == preSharedKey)
7112 return RETURN_ERR;
7113
7114 params.name = "wpa_passphrase";
7115
7116 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
7117 {
7118 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
7119 return RETURN_ERR;
7120 }
7121 params.value = preSharedKey;
7122 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7123 ret = wifi_hostapdWrite(config_file, &params, 1);
7124 if(!ret)
7125 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
7126 return ret;
7127 //TODO: call hostapd_cli for dynamic_config_control
7128}
7129
7130//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
7131// outputs the passphrase, maximum 63 characters
7132INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
7133{
7134 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
7135
7136 wifi_dbg_printf("\nFunc=%s\n",__func__);
7137 if (NULL == output_string)
7138 return RETURN_ERR;
7139
7140 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7141 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7142 if(strcmp(buf,"0")==0)
7143 {
7144 printf("wpa_mode is %s ......... \n",buf);
7145 return RETURN_ERR;
7146 }
7147
7148 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
7149 wifi_dbg_printf("\noutput_string=%s\n",output_string);
7150
7151 return RETURN_OK;
7152}
7153
7154// sets the passphrase enviornment variable, max 63 characters
7155INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
7156{
7157 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
7158 struct params params={'\0'};
7159 char config_file[MAX_BUF_SIZE] = {0};
7160 int ret;
7161
7162 if(NULL == passPhrase)
7163 return RETURN_ERR;
7164
7165 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
7166 {
7167 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
7168 return RETURN_ERR;
7169 }
7170 params.name = "wpa_passphrase";
7171 params.value = passPhrase;
7172 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7173 ret=wifi_hostapdWrite(config_file,&params,1);
7174 if(!ret)
7175 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7176
7177 return ret;
7178}
7179
7180//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.
7181INT wifi_setApSecurityReset(INT apIndex)
7182{
7183 char original_config_file[64] = {0};
7184 char current_config_file[64] = {0};
7185 char buf[64] = {0};
7186 char cmd[64] = {0};
7187 char wpa[4] = {0};
7188 char wpa_psk[64] = {0};
7189 char wpa_passphrase[64] = {0};
7190 char wpa_psk_file[128] = {0};
7191 char wpa_key_mgmt[64] = {0};
7192 char wpa_pairwise[32] = {0};
7193 wifi_band band;
7194 struct params list[6];
7195
7196 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7197
7198 band = wifi_index_to_band(apIndex);
7199 if (band == band_2_4)
7200 sprintf(original_config_file, "/etc/hostapd-2G.conf");
7201 else if (band == band_5)
7202 sprintf(original_config_file, "/etc/hostapd-5G.conf");
7203 else if (band == band_6)
7204 sprintf(original_config_file, "/etc/hostapd-6G.conf");
7205 else
7206 return RETURN_ERR;
7207
7208 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
7209 list[0].name = "wpa";
7210 list[0].value = wpa;
developer69b61b02023-03-07 17:17:44 +08007211
developer72fb0bb2023-01-11 09:46:29 +08007212 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
7213 list[1].name = "wpa_psk";
7214 list[1].value = wpa_psk;
7215
7216 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
7217 list[2].name = "wpa_passphrase";
7218 list[2].value = wpa_passphrase;
7219
7220 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
7221
7222 if (strlen(wpa_psk_file) == 0)
7223 strcpy(wpa_psk_file, PSK_FILE);
7224
7225 if (access(wpa_psk_file, F_OK) != 0) {
7226 sprintf(cmd, "touch %s", wpa_psk_file);
7227 _syscmd(cmd, buf, sizeof(buf));
7228 }
7229 list[3].name = "wpa_psk_file";
7230 list[3].value = wpa_psk_file;
7231
7232 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
7233 list[4].name = "wpa_key_mgmt";
7234 list[4].value = wpa_key_mgmt;
7235
7236 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
7237 list[5].name = "wpa_pairwise";
7238 list[5].value = wpa_pairwise;
7239
7240 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7241 wifi_hostapdWrite(current_config_file, list, 6);
7242
7243 wifi_setApEnable(apIndex, FALSE);
7244 wifi_setApEnable(apIndex, TRUE);
7245
7246 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7247 return RETURN_OK;
7248}
7249
7250//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).
7251INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7252{
7253 char config_file[64] = {0};
7254 char buf[64] = {0};
7255 char cmd[256] = {0};
7256
7257 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7258
7259 if(!IP_output || !Port_output || !RadiusSecret_output)
7260 return RETURN_ERR;
7261
7262 // Read the first matched config
7263 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7264 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7265 _syscmd(cmd, buf, sizeof(buf));
7266 strncpy(IP_output, buf, 64);
7267
7268 memset(buf, 0, sizeof(buf));
7269 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7270 _syscmd(cmd, buf, sizeof(buf));
7271 *Port_output = atoi(buf);
7272
7273 memset(buf, 0, sizeof(buf));
7274 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7275 _syscmd(cmd, buf, sizeof(buf));
7276 strncpy(RadiusSecret_output, buf, 64);
7277
7278 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7279 return RETURN_OK;
7280}
7281
7282INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7283{
7284 char config_file[64] = {0};
7285 char port_str[8] = {0};
7286 char cmd[256] = {0};
7287 char buf[128] = {0};
7288
7289 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7290
7291 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7292
7293 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7294 _syscmd(cmd, buf, sizeof(buf));
7295 memset(cmd, 0, sizeof(cmd));
7296
7297 snprintf(port_str, sizeof(port_str), "%d", port);
7298 if (strlen(buf) == 0)
7299 // Append
7300 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7301 "auth_server_addr=%s\\n"
7302 "auth_server_port=%s\\n"
7303 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7304 else {
7305 // Delete the three lines setting after the "# radius 1" comment
7306 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7307 _syscmd(cmd, buf, sizeof(buf));
7308 memset(cmd, 0, sizeof(cmd));
7309 // Use "# radius 1" comment to find the location to insert the radius setting
7310 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7311 "# radius 1\\n"
7312 "auth_server_addr=%s\\n"
7313 "auth_server_port=%s\\n"
7314 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7315 }
7316 if(_syscmd(cmd, buf, sizeof(buf))) {
7317 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7318 return RETURN_ERR;
7319 }
7320
7321 wifi_reloadAp(apIndex);
7322 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7323 return RETURN_OK;
7324}
7325
7326INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7327{
7328 char config_file[64] = {0};
7329 char buf[64] = {0};
7330 char cmd[256] = {0};
7331
7332 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7333
7334 if(!IP_output || !Port_output || !RadiusSecret_output)
7335 return RETURN_ERR;
7336
7337 // Read the second matched config
7338 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7339 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7340 _syscmd(cmd, buf, sizeof(buf));
7341 strncpy(IP_output, buf, 64);
7342
7343 memset(buf, 0, sizeof(buf));
7344 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7345 _syscmd(cmd, buf, sizeof(buf));
7346 *Port_output = atoi(buf);
7347
7348 memset(buf, 0, sizeof(buf));
7349 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7350 _syscmd(cmd, buf, sizeof(buf));
7351 strncpy(RadiusSecret_output, buf, 64);
7352
7353 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7354 return RETURN_OK;
7355}
7356
7357INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7358{
7359 char config_file[64] = {0};
7360 char port_str[8] = {0};
7361 char cmd[256] = {0};
7362 char buf[128] = {0};
7363
7364 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7365
7366 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7367
7368 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7369 _syscmd(cmd, buf, sizeof(buf));
7370 memset(cmd, 0, sizeof(cmd));
7371
7372 snprintf(port_str, sizeof(port_str), "%d", port);
7373 if (strlen(buf) == 0)
7374 // Append
7375 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7376 "auth_server_addr=%s\\n"
7377 "auth_server_port=%s\\n"
7378 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7379 else {
7380 // Delete the three lines setting after the "# radius 2" comment
7381 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7382 _syscmd(cmd, buf, sizeof(buf));
7383 memset(cmd, 0, sizeof(cmd));
7384 // Use "# radius 2" comment to find the location to insert the radius setting
7385 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7386 "# radius 2\\n"
7387 "auth_server_addr=%s\\n"
7388 "auth_server_port=%s\\n"
7389 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7390 }
7391 if(_syscmd(cmd, buf, sizeof(buf))) {
7392 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7393 return RETURN_ERR;
7394 }
7395
7396 wifi_reloadAp(apIndex);
7397 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7398 return RETURN_OK;
7399}
7400
7401//RadiusSettings
7402INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7403{
7404 if(!output)
7405 return RETURN_ERR;
7406
7407 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
developer69b61b02023-03-07 17:17:44 +08007408 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7409 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7410 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7411 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
developer72fb0bb2023-01-11 09:46:29 +08007412 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.
developer69b61b02023-03-07 17:17:44 +08007413 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7414 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7415 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
developer72fb0bb2023-01-11 09:46:29 +08007416 //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.
7417
7418 return RETURN_OK;
7419}
7420
7421INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7422{
7423 //store the paramters, and apply instantly
7424 return RETURN_ERR;
7425}
7426
7427//Device.WiFi.AccessPoint.{i}.WPS.Enable
7428//Enables or disables WPS functionality for this access point.
7429// outputs the WPS enable state of this ap in output_bool
7430INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7431{
7432 char interface_name[16] = {0};
7433 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
7434 if(!output_bool)
7435 return RETURN_ERR;
7436 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7437 return RETURN_ERR;
7438 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
7439 _syscmd(cmd, buf, sizeof(buf));
7440 if(strstr(buf, "configured"))
7441 *output_bool=TRUE;
7442 else
7443 *output_bool=FALSE;
7444
7445 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007446}
developer72fb0bb2023-01-11 09:46:29 +08007447
7448//Device.WiFi.AccessPoint.{i}.WPS.Enable
7449// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7450INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7451{
7452 char config_file[MAX_BUF_SIZE] = {0};
7453 struct params params;
7454
7455 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7456 //store the paramters, and wait for wifi up to apply
7457 params.name = "wps_state";
7458 params.value = enable ? "2":"0";
7459
7460 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7461 wifi_hostapdWrite(config_file, &params, 1);
7462 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7463 wifi_reloadAp(apIndex);
7464
7465 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7466 return RETURN_OK;
7467}
7468
7469//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
7470INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7471{
7472 if(!output)
7473 return RETURN_ERR;
7474 snprintf(output, 128, "PushButton,PIN");
7475 return RETURN_OK;
7476}
7477
7478//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7479//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.
7480// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7481INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7482{
7483 if(!output)
7484 return RETURN_ERR;
7485 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7486
7487 return RETURN_OK;
7488}
7489
7490//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7491// 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
7492INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7493{
7494 //apply instantly. No setting need to be stored.
7495 char methods[MAX_BUF_SIZE], *token, *next_token;
7496 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7497 struct params params;
7498
7499 if(!methodString)
7500 return RETURN_ERR;
7501 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7502 //store the paramters, and wait for wifi up to apply
7503
7504 snprintf(methods, sizeof(methods), "%s", methodString);
7505 for(token=methods; *token; token=next_token)
7506 {
7507 strtok_r(token, ",", &next_token);
7508 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7509 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7510 else if(*token=='E')
7511 {
7512 if(!strcmp(methods, "Ethernet"))
7513 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7514 else if(!strcmp(methods, "ExternalNFCToken"))
7515 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7516 else
7517 printf("%s: Unknown WpsConfigMethod\n", __func__);
7518 }
7519 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7520 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7521 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7522 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7523 else if(*token=='P' )
7524 {
7525 if(!strcmp(token, "PushButton"))
7526 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
7527 else if(!strcmp(token, "PIN"))
7528 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7529 else
7530 printf("%s: Unknown WpsConfigMethod\n", __func__);
7531 }
7532 else
7533 printf("%s: Unknown WpsConfigMethod\n", __func__);
7534 }
7535 params.name = "config_methods";
7536 params.value = config_methods;
7537 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7538 wifi_hostapdWrite(config_file, &params, 1);
7539 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7540 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7541
7542 return RETURN_OK;
7543}
7544
7545// outputs the pin value, ulong_pin must be allocated by the caller
7546INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7547{
7548 char buf[MAX_BUF_SIZE] = {0};
7549 char cmd[MAX_CMD_SIZE] = {0};
7550
7551 if(!output_ulong)
7552 return RETURN_ERR;
7553 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7554 _syscmd(cmd, buf, sizeof(buf));
7555 if(strlen(buf) > 0)
7556 *output_ulong=strtoul(buf, NULL, 10);
7557
7558 return RETURN_OK;
7559}
7560
7561// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7562INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7563{
7564 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7565 char ap_pin[16] = {0};
7566 char buf[MAX_BUF_SIZE] = {0};
7567 char config_file[MAX_BUF_SIZE] = {0};
7568 ULONG prev_pin = 0;
7569 struct params params;
7570
7571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7572 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7573 params.name = "ap_pin";
7574 params.value = ap_pin;
7575 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7576 wifi_hostapdWrite(config_file, &params, 1);
7577 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7579
7580 return RETURN_OK;
7581}
7582
7583// Output string is either Not configured or Configured, max 32 characters
7584INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7585{
7586 char interface_name[16] = {0};
7587 char cmd[MAX_CMD_SIZE];
7588 char buf[MAX_BUF_SIZE]={0};
7589
7590 if(!output_string)
7591 return RETURN_ERR;
7592 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7593 snprintf(output_string, 32, "Not configured");
7594 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7595 return RETURN_ERR;
7596 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
7597 _syscmd(cmd, buf, sizeof(buf));
7598
7599 if(!strncmp(buf, "configured", 10))
7600 snprintf(output_string, 32, "Configured");
7601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7602
7603 return RETURN_OK;
7604}
7605
7606// sets the WPS pin for this AP
7607INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7608{
7609 char interface_name[16] = {0};
7610 char cmd[MAX_CMD_SIZE];
7611 char buf[MAX_BUF_SIZE]={0};
7612 BOOL enable;
7613
7614 wifi_getApEnable(apIndex, &enable);
7615 if (!enable)
7616 return RETURN_ERR;
7617 wifi_getApWpsEnable(apIndex, &enable);
7618 if (!enable)
7619 return RETURN_ERR;
7620
7621 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7622 return RETURN_ERR;
7623 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
7624 _syscmd(cmd, buf, sizeof(buf));
7625 if((strstr(buf, "OK"))!=NULL)
7626 return RETURN_OK;
7627
7628 return RETURN_ERR;
7629}
7630
7631// This function is called when the WPS push button has been pressed for this AP
7632INT wifi_setApWpsButtonPush(INT apIndex)
7633{
7634 char cmd[MAX_CMD_SIZE];
7635 char buf[MAX_BUF_SIZE]={0};
7636 char interface_name[16] = {0};
7637 BOOL enable=FALSE;
7638
7639 wifi_getApEnable(apIndex, &enable);
7640 if (!enable)
7641 return RETURN_ERR;
7642
7643 wifi_getApWpsEnable(apIndex, &enable);
7644 if (!enable)
7645 return RETURN_ERR;
7646
7647 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7648 return RETURN_ERR;
7649
7650 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
7651 _syscmd(cmd, buf, sizeof(buf));
7652
7653 if((strstr(buf, "OK"))!=NULL)
7654 return RETURN_OK;
7655 return RETURN_ERR;
7656}
7657
7658// cancels WPS mode for this AP
7659INT wifi_cancelApWPS(INT apIndex)
7660{
7661 char interface_name[16] = {0};
7662 char cmd[MAX_CMD_SIZE];
7663 char buf[MAX_BUF_SIZE]={0};
7664
7665 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7666 return RETURN_ERR;
7667 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
7668 _syscmd(cmd,buf, sizeof(buf));
7669
7670 if((strstr(buf, "OK"))!=NULL)
7671 return RETURN_OK;
7672 return RETURN_ERR;
7673}
7674
7675//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7676//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7677INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7678{
7679 char interface_name[16] = {0};
7680 FILE *f = NULL;
7681 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7682 char cmd[256] = {0}, buf[2048] = {0};
7683 char *param = NULL, *value = NULL, *line=NULL;
7684 size_t len = 0;
7685 ssize_t nread = 0;
7686 wifi_associated_dev_t *dev=NULL;
7687
7688 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7689 *associated_dev_array = NULL;
7690 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7691 return RETURN_ERR;
7692 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
7693 _syscmd(cmd,buf,sizeof(buf));
7694 *output_array_size = atoi(buf);
7695
7696 if (*output_array_size <= 0)
7697 return RETURN_OK;
7698
7699 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7700 *associated_dev_array = dev;
7701 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
7702 _syscmd(cmd,buf,sizeof(buf));
7703 f = fopen("/tmp/connected_devices.txt", "r");
7704 if (f==NULL)
7705 {
7706 *output_array_size=0;
7707 return RETURN_ERR;
7708 }
7709 while ((getline(&line, &len, f)) != -1)
7710 {
7711 param = strtok(line,"=");
7712 value = strtok(NULL,"=");
7713
7714 if( strcmp("flags",param) == 0 )
7715 {
7716 value[strlen(value)-1]='\0';
7717 if(strstr (value,"AUTHORIZED") != NULL )
7718 {
7719 dev[auth_temp].cli_AuthenticationState = 1;
7720 dev[auth_temp].cli_Active = 1;
7721 auth_temp++;
7722 read_flag=1;
7723 }
7724 }
7725 if(read_flag==1)
7726 {
7727 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7728 {
7729 value[strlen(value)-1]='\0';
7730 sscanf(value, "%x:%x:%x:%x:%x:%x",
7731 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7732 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7733 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7734 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7735 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7736 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7737 mac_temp++;
7738 read_flag=0;
7739 }
7740 }
7741 }
7742 *output_array_size = auth_temp;
7743 auth_temp=0;
7744 mac_temp=0;
7745 free(line);
7746 fclose(f);
7747 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7748 return RETURN_OK;
7749}
7750
7751#define MACADDRESS_SIZE 6
7752
7753INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7754{
7755 FILE *fp = NULL;
7756 char str[MAX_BUF_SIZE] = {0};
7757 int wificlientindex = 0 ;
7758 int count = 0;
7759 int signalstrength = 0;
7760 int arr[MACADDRESS_SIZE] = {0};
7761 unsigned char mac[MACADDRESS_SIZE] = {0};
7762 UINT wifi_count = 0;
7763 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7764 char pipeCmd[MAX_CMD_SIZE] = {0};
7765
7766 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7767 *output_array_size = 0;
7768 *associated_dev_array = NULL;
7769
7770 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7771 fp = popen(pipeCmd, "r");
developer69b61b02023-03-07 17:17:44 +08007772 if (fp == NULL)
developer72fb0bb2023-01-11 09:46:29 +08007773 {
7774 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7775 return RETURN_ERR;
7776 }
7777
7778 /* Read the output a line at a time - output it. */
7779 fgets(str, sizeof(str)-1, fp);
7780 wifi_count = (unsigned int) atoi ( str );
7781 *output_array_size = wifi_count;
7782 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7783 pclose(fp);
7784
7785 if(wifi_count == 0)
7786 {
7787 return RETURN_OK;
7788 }
7789 else
7790 {
7791 wifi_associated_dev3_t* temp = NULL;
7792 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7793 if(temp == NULL)
7794 {
7795 printf("Error Statement. Insufficient memory \n");
7796 return RETURN_ERR;
7797 }
7798
7799 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7800 system(pipeCmd);
7801 memset(pipeCmd,0,sizeof(pipeCmd));
7802 if(apIndex == 0)
7803 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7804 else if(apIndex == 1)
7805 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7806 system(pipeCmd);
7807
7808 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7809 if(fp == NULL)
7810 {
7811 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7812 free(temp);
7813 return RETURN_ERR;
7814 }
7815 fclose(fp);
7816
7817 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
7818 fp = popen(pipeCmd, "r");
7819 if(fp)
7820 {
7821 for(count =0 ; count < wifi_count; count++)
7822 {
7823 fgets(str, MAX_BUF_SIZE, fp);
7824 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7825 {
7826 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7827 {
7828 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7829
7830 }
7831 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7832 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]);
7833 }
7834 temp[count].cli_AuthenticationState = 1; //TODO
7835 temp[count].cli_Active = 1; //TODO
7836 }
7837 pclose(fp);
7838 }
7839
7840 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
7841 fp = popen(pipeCmd, "r");
7842 if(fp)
developer69b61b02023-03-07 17:17:44 +08007843 {
developer72fb0bb2023-01-11 09:46:29 +08007844 pclose(fp);
7845 }
7846 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7847 if(fp)
7848 {
7849 for(count =0 ; count < wifi_count ;count++)
7850 {
7851 fgets(str, MAX_BUF_SIZE, fp);
7852 signalstrength = atoi(str);
7853 temp[count].cli_SignalStrength = signalstrength;
7854 temp[count].cli_RSSI = signalstrength;
7855 temp[count].cli_SNR = signalstrength + 95;
7856 }
7857 pclose(fp);
7858 }
7859
7860
7861 if((apIndex == 0) || (apIndex == 4))
7862 {
7863 for(count =0 ; count < wifi_count ;count++)
developer69b61b02023-03-07 17:17:44 +08007864 {
developer72fb0bb2023-01-11 09:46:29 +08007865 strcpy(temp[count].cli_OperatingStandard,"g");
7866 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7867 }
7868
7869 //BytesSent
7870 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
7871 fp = popen(pipeCmd, "r");
7872 if(fp)
developer69b61b02023-03-07 17:17:44 +08007873 {
developer72fb0bb2023-01-11 09:46:29 +08007874 pclose(fp);
7875 }
7876 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7877 if(fp)
7878 {
7879 for (count = 0; count < wifi_count; count++)
7880 {
7881 fgets(str, MAX_BUF_SIZE, fp);
7882 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7883 }
7884 pclose(fp);
7885 }
7886
7887 //BytesReceived
7888 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
7889 fp = popen(pipeCmd, "r");
7890 if (fp)
7891 {
7892 pclose(fp);
7893 }
7894 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7895 if (fp)
7896 {
7897 for (count = 0; count < wifi_count; count++)
7898 {
7899 fgets(str, MAX_BUF_SIZE, fp);
7900 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7901 }
7902 pclose(fp);
7903 }
7904
7905 //PacketsSent
7906 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
7907 fp = popen(pipeCmd, "r");
7908 if (fp)
7909 {
7910 pclose(fp);
7911 }
7912
7913 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7914 if (fp)
7915 {
7916 for (count = 0; count < wifi_count; count++)
7917 {
7918 fgets(str, MAX_BUF_SIZE, fp);
7919 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7920 }
7921 pclose(fp);
7922 }
7923
7924 //PacketsReceived
7925 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
7926 fp = popen(pipeCmd, "r");
7927 if (fp)
7928 {
7929 pclose(fp);
7930 }
7931 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7932 if (fp)
7933 {
7934 for (count = 0; count < wifi_count; count++)
7935 {
7936 fgets(str, MAX_BUF_SIZE, fp);
7937 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7938 }
7939 pclose(fp);
7940 }
7941
7942 //ErrorsSent
7943 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7944 fp = popen(pipeCmd, "r");
7945 if (fp)
7946 {
7947 pclose(fp);
7948 }
7949 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7950 if (fp)
7951 {
7952 for (count = 0; count < wifi_count; count++)
7953 {
7954 fgets(str, MAX_BUF_SIZE, fp);
7955 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7956 }
7957 pclose(fp);
7958 }
7959
7960 //ErrorsSent
7961 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7962 fp = popen(pipeCmd, "r");
7963 if (fp)
7964 {
7965 pclose(fp);
7966 }
7967 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7968 if (fp)
7969 {
7970 for (count = 0; count < wifi_count; count++)
7971 {
7972 fgets(str, MAX_BUF_SIZE, fp);
7973 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7974 }
7975 pclose(fp);
7976 }
7977
7978 //LastDataDownlinkRate
7979 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
7980 fp = popen(pipeCmd, "r");
7981 if (fp)
7982 {
7983 pclose(fp);
7984 }
7985 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7986 if (fp)
7987 {
7988 for (count = 0; count < wifi_count; count++)
7989 {
7990 fgets(str, MAX_BUF_SIZE, fp);
7991 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7992 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7993 }
7994 pclose(fp);
7995 }
7996
7997 //LastDataUplinkRate
7998 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
7999 fp = popen(pipeCmd, "r");
8000 if (fp)
8001 {
8002 pclose(fp);
8003 }
8004 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8005 if (fp)
8006 {
8007 for (count = 0; count < wifi_count; count++)
8008 {
8009 fgets(str, MAX_BUF_SIZE, fp);
8010 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8011 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8012 }
8013 pclose(fp);
8014 }
8015
8016 }
8017 else if ((apIndex == 1) || (apIndex == 5))
8018 {
8019 for (count = 0; count < wifi_count; count++)
8020 {
8021 strcpy(temp[count].cli_OperatingStandard, "a");
8022 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
8023 temp[count].cli_BytesSent = 0;
8024 temp[count].cli_BytesReceived = 0;
8025 temp[count].cli_LastDataUplinkRate = 0;
8026 temp[count].cli_LastDataDownlinkRate = 0;
8027 temp[count].cli_PacketsSent = 0;
8028 temp[count].cli_PacketsReceived = 0;
8029 temp[count].cli_ErrorsSent = 0;
8030 }
8031 }
8032
8033 for (count = 0; count < wifi_count; count++)
8034 {
8035 temp[count].cli_Retransmissions = 0;
8036 temp[count].cli_DataFramesSentAck = 0;
8037 temp[count].cli_DataFramesSentNoAck = 0;
8038 temp[count].cli_MinRSSI = 0;
8039 temp[count].cli_MaxRSSI = 0;
8040 strncpy(temp[count].cli_InterferenceSources, "", 64);
8041 memset(temp[count].cli_IPAddress, 0, 64);
8042 temp[count].cli_RetransCount = 0;
8043 temp[count].cli_FailedRetransCount = 0;
8044 temp[count].cli_RetryCount = 0;
8045 temp[count].cli_MultipleRetryCount = 0;
8046 }
8047 *associated_dev_array = temp;
8048 }
8049 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8050 return RETURN_OK;
8051}
8052
developer7e4a2a62023-04-06 19:56:03 +08008053int wifihal_interfacestatus(CHAR *wifi_status, CHAR *interface_name)
developer72fb0bb2023-01-11 09:46:29 +08008054{
developer7e4a2a62023-04-06 19:56:03 +08008055 char cmd[MAX_CMD_SIZE] = {0};
8056 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08008057
developer7e4a2a62023-04-06 19:56:03 +08008058 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
8059
8060 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4 | tr -d '\\n'",
8061 interface_name);
8062 _syscmd(cmd, buf, MAX_BUF_SIZE);
8063
8064 strcpy(wifi_status, buf); /* TBD: check wifi_status mem lenth and replace with strcpy later */
8065
8066 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008067 return RETURN_OK;
8068}
8069
8070/* #define HOSTAPD_STA_PARAM_ENTRIES 29
8071struct hostapd_sta_param {
8072 char key[50];
8073 char value[100];
8074}
8075
8076static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
8077 int i = 0;
8078
8079 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
8080 if (strncmp(params[i].key,key,50) == 0){
8081 return &params[i].value;
8082 }
8083 i++;
8084 }
8085 return NULL;
8086
8087} */
8088
8089static unsigned int count_occurences(const char *buf, const char *word)
8090{
8091 unsigned int n = 0;
8092 char *ptr = strstr(buf, word);
8093
8094 while (ptr++) {
8095 n++;
8096 ptr = strstr(ptr, word);
8097 }
8098
8099 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
8100 return n;
8101}
8102
8103static const char *get_line_from_str_buf(const char *buf, char *line)
8104{
8105 int i;
8106 int n = strlen(buf);
8107
8108 for (i = 0; i < n; i++) {
8109 line[i] = buf[i];
8110 if (buf[i] == '\n') {
8111 line[i] = '\0';
8112 return &buf[i + 1];
8113 }
8114 }
8115
8116 return NULL;
8117}
8118
8119INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8120{
8121 unsigned int assoc_cnt = 0;
8122 char interface_name[50] = {0};
8123 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
8124 char cmd[MAX_CMD_SIZE] = {'\0'};
8125 char line[256] = {'\0'};
8126 int i = 0;
8127 int ret = 0;
8128 const char *ptr = NULL;
8129 char *key = NULL;
8130 char *val = NULL;
8131 wifi_associated_dev3_t *temp = NULL;
8132 int rssi;
8133
8134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8135
8136 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8137 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8138 return RETURN_ERR;
8139 }
8140
8141 // Example filtered output of 'iw dev' command:
8142 // Station 0a:69:72:10:d2:fa (on wifi0)
8143 // signal avg:-67 [-71, -71] dBm
8144 // Station 28:c2:1f:25:5f:99 (on wifi0)
8145 // signal avg:-67 [-71, -70] dBm
8146 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
8147 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
8148 return RETURN_ERR;
8149 }
8150
8151 ret = _syscmd(cmd, buf, sizeof(buf));
8152 if (ret == RETURN_ERR) {
8153 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
8154 return RETURN_ERR;
8155 }
8156
8157 *output_array_size = count_occurences(buf, "Station");
8158 if (*output_array_size == 0) return RETURN_OK;
8159
8160 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
8161 if (temp == NULL) {
8162 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
8163 return RETURN_ERR;
8164 }
8165 *associated_dev_array = temp;
8166
8167 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
8168 ptr = get_line_from_str_buf(buf, line);
8169 i = -1;
8170 while (ptr) {
8171 if (strstr(line, "Station")) {
8172 i++;
8173 key = strtok(line, " ");
8174 val = strtok(NULL, " ");
8175 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
8176 &temp[i].cli_MACAddress[0],
8177 &temp[i].cli_MACAddress[1],
8178 &temp[i].cli_MACAddress[2],
8179 &temp[i].cli_MACAddress[3],
8180 &temp[i].cli_MACAddress[4],
8181 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
8182 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
8183 free(*associated_dev_array);
8184 return RETURN_ERR;
8185 }
8186 }
8187 else if (i < 0) {
8188 ptr = get_line_from_str_buf(ptr, line);
8189 continue; // We didn't detect 'station' entry yet
8190 }
8191 else if (strstr(line, "signal avg")) {
8192 key = strtok(line, ":");
8193 val = strtok(NULL, " ");
8194 if (sscanf(val, "%d", &rssi) <= 0 ) {
8195 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
8196 free(*associated_dev_array);
8197 return RETURN_ERR;
8198 }
8199 temp[i].cli_RSSI = rssi;
8200 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
8201 }
8202 // Here other fields can be parsed if added to filter of 'iw dev' command
8203
8204 ptr = get_line_from_str_buf(ptr, line);
8205 };
8206
8207 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8208
8209 return RETURN_OK;
8210}
8211
8212#if 0
8213//To-do
8214INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8215{
8216 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8217
8218 //Using different approach to get required WiFi Parameters from system available commands
developer69b61b02023-03-07 17:17:44 +08008219#if 0
developer72fb0bb2023-01-11 09:46:29 +08008220 FILE *f;
8221 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8222 char cmd[256], buf[2048];
8223 char *param , *value, *line=NULL;
8224 size_t len = 0;
8225 ssize_t nread;
8226 wifi_associated_dev3_t *dev=NULL;
8227 *associated_dev_array = NULL;
8228 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
8229 _syscmd(cmd,buf,sizeof(buf));
8230 *output_array_size = atoi(buf);
8231
8232 if (*output_array_size <= 0)
8233 return RETURN_OK;
8234
8235 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8236 *associated_dev_array = dev;
8237 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
8238 _syscmd(cmd,buf,sizeof(buf));
8239 f = fopen("/tmp/connected_devices.txt", "r");
8240 if (f==NULL)
8241 {
8242 *output_array_size=0;
8243 return RETURN_ERR;
8244 }
8245 while ((nread = getline(&line, &len, f)) != -1)
8246 {
8247 param = strtok(line,"=");
8248 value = strtok(NULL,"=");
8249
8250 if( strcmp("flags",param) == 0 )
8251 {
8252 value[strlen(value)-1]='\0';
8253 if(strstr (value,"AUTHORIZED") != NULL )
8254 {
8255 dev[auth_temp].cli_AuthenticationState = 1;
8256 dev[auth_temp].cli_Active = 1;
8257 auth_temp++;
8258 read_flag=1;
8259 }
8260 }
8261 if(read_flag==1)
8262 {
8263 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8264 {
8265 value[strlen(value)-1]='\0';
8266 sscanf(value, "%x:%x:%x:%x:%x:%x",
8267 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8268 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8269 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8270 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8271 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8272 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8273
8274 }
8275 else if( strcmp("rx_packets",param) == 0 )
8276 {
8277 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8278 }
8279
8280 else if( strcmp("tx_packets",param) == 0 )
8281 {
developer69b61b02023-03-07 17:17:44 +08008282 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
developer72fb0bb2023-01-11 09:46:29 +08008283 }
8284
8285 else if( strcmp("rx_bytes",param) == 0 )
8286 {
8287 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8288 }
8289
8290 else if( strcmp("tx_bytes",param) == 0 )
8291 {
developer69b61b02023-03-07 17:17:44 +08008292 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
developer72fb0bb2023-01-11 09:46:29 +08008293 mac_temp++;
8294 read_flag=0;
developer69b61b02023-03-07 17:17:44 +08008295 }
developer72fb0bb2023-01-11 09:46:29 +08008296 }
8297 }
8298
8299 *output_array_size = auth_temp;
8300 auth_temp=0;
8301 mac_temp=0;
8302 free(line);
8303 fclose(f);
8304#endif
8305 char interface_name[MAX_BUF_SIZE] = {0};
8306 char wifi_status[MAX_BUF_SIZE] = {0};
8307 char hostapdconf[MAX_BUF_SIZE] = {0};
8308
8309 wifi_associated_dev3_t *dev_array = NULL;
8310 ULONG wifi_count = 0;
8311
8312 *associated_dev_array = NULL;
8313 *output_array_size = 0;
8314
8315 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8316 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8317 {
8318 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8319
8320 wifi_GetInterfaceName(interface_name, hostapdconf);
8321
8322 if(strlen(interface_name) > 1)
8323 {
8324 wifihal_interfacestatus(wifi_status,interface_name);
8325 if(strcmp(wifi_status,"RUNNING") == 0)
8326 {
8327 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8328
8329 *associated_dev_array = dev_array;
developer69b61b02023-03-07 17:17:44 +08008330 *output_array_size = wifi_count;
developer72fb0bb2023-01-11 09:46:29 +08008331 }
8332 else
8333 {
8334 *associated_dev_array = NULL;
8335 }
8336 }
8337 }
8338
8339 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8340 return RETURN_OK;
8341}
8342#endif
8343
8344/* getIPAddress function */
8345/**
8346* @description Returning IpAddress of the Matched String
8347*
developer69b61b02023-03-07 17:17:44 +08008348* @param
developer72fb0bb2023-01-11 09:46:29 +08008349* @str Having MacAddress
developer69b61b02023-03-07 17:17:44 +08008350* @ipaddr Having ipaddr
developer72fb0bb2023-01-11 09:46:29 +08008351* @return The status of the operation
8352* @retval RETURN_OK if successful
8353* @retval RETURN_ERR if any error is detected
8354*
8355*/
8356
8357INT getIPAddress(char *str,char *ipaddr)
8358{
8359 FILE *fp = NULL;
8360 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8361 int LeaseTime = 0,ret = 0;
8362 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8363 {
8364 return RETURN_ERR;
8365 }
8366
8367 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8368 {
8369 /*
8370 Sample:sss
8371 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8372 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8373 */
8374 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
8375 &(LeaseTime),
8376 phyAddr,
8377 ipAddr,
8378 hostName
8379 );
8380 if(ret != 4)
8381 continue;
8382 if(strcmp(str,phyAddr) == 0)
8383 strcpy(ipaddr,ipAddr);
8384 }
8385 fclose(fp);
8386 return RETURN_OK;
8387}
8388
8389/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8390/**
8391* @description Returning Inactive wireless connected clients informations
8392*
developer69b61b02023-03-07 17:17:44 +08008393* @param
developer72fb0bb2023-01-11 09:46:29 +08008394* @filename Holding private_wifi 2g/5g content files
8395* @associated_dev_array Having inactiv wireless clients informations
8396* @output_array_size Returning Inactive wireless counts
8397* @return The status of the operation
8398* @retval RETURN_OK if successful
8399* @retval RETURN_ERR if any error is detected
8400*
8401*/
8402
8403INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8404{
8405 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8406 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8407 FILE *fp = NULL;
8408 int arr[MACADDRESS_SIZE] = {0};
8409 unsigned char mac[MACADDRESS_SIZE] = {0};
8410 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8411 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8412 fp = popen(buf,"r");
8413 if(fp == NULL)
8414 return RETURN_ERR;
8415 else
8416 {
8417 fgets(path,sizeof(path),fp);
8418 maccount = atoi(path);
8419 }
8420 pclose(fp);
8421 *output_array_size = maccount;
8422 wifi_associated_dev3_t* temp = NULL;
8423 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8424 *associated_dev_array = temp;
8425 if(temp == NULL)
8426 {
8427 printf("Error Statement. Insufficient memory \n");
8428 return RETURN_ERR;
8429 }
8430 memset(buf,0,sizeof(buf));
8431 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8432 fp = popen(buf,"r");
8433 if (fp == NULL) {
8434 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8435 return RETURN_ERR;
8436 }
8437 for(count = 0; count < maccount ; count++)
8438 {
8439 fgets(path,sizeof(path),fp);
8440 for(i = 0; path[i]!='\n';i++)
8441 str[i]=path[i];
8442 str[i]='\0';
8443 getIPAddress(str,ipaddr);
8444 memset(buf,0,sizeof(buf));
8445 if(strlen(ipaddr) > 0)
8446 {
8447 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8448 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8449 {
8450 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8451 {
8452 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8453 {
8454 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8455
8456 }
8457 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8458 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]);
8459 }
8460 temp[count].cli_AuthenticationState = 0; //TODO
developer69b61b02023-03-07 17:17:44 +08008461 temp[count].cli_Active = 0; //TODO
developer72fb0bb2023-01-11 09:46:29 +08008462 temp[count].cli_SignalStrength = 0;
8463 }
8464 else //Active wireless clients info
8465 {
8466 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8467 {
8468 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8469 {
8470 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8471
8472 }
8473 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8474 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]);
8475 }
8476 temp[count].cli_Active = 1;
8477 }
8478 }
8479 memset(ipaddr,0,sizeof(ipaddr));
8480 }
8481 pclose(fp);
8482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8483 return RETURN_OK;
8484}
8485//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8486//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8487//To get Band Steering Capability
8488INT wifi_getBandSteeringCapability(BOOL *support)
8489{
8490 *support = FALSE;
8491 return RETURN_OK;
8492}
8493
8494
8495//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8496//To get Band Steering enable status
8497INT wifi_getBandSteeringEnable(BOOL *enable)
8498{
8499 *enable = FALSE;
8500 return RETURN_OK;
8501}
8502
8503//To turn on/off Band steering
8504INT wifi_setBandSteeringEnable(BOOL enable)
8505{
8506 return RETURN_OK;
8507}
8508
8509//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8510//To get Band Steering AP group
8511INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8512{
8513 if (NULL == output_ApGroup)
8514 return RETURN_ERR;
8515
8516 strcpy(output_ApGroup, "1,2");
8517 return RETURN_OK;
8518}
8519
8520//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8521//to set and read the band steering BandUtilizationThreshold parameters
8522INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8523{
8524 return RETURN_ERR;
8525}
8526
8527INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8528{
8529 return RETURN_ERR;
8530}
8531
8532//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8533//to set and read the band steering RSSIThreshold parameters
8534INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8535{
8536 return RETURN_ERR;
8537}
8538
8539INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8540{
8541 return RETURN_ERR;
8542}
8543
8544
8545//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8546//to set and read the band steering physical modulation rate threshold parameters
8547INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8548{
8549 //If chip is not support, return -1
8550 return RETURN_ERR;
8551}
8552
8553INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8554{
8555 //If chip is not support, return -1
8556 return RETURN_ERR;
8557}
8558
8559//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8560//to set and read the inactivity time (in seconds) for steering under overload condition
8561INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8562{
8563 return RETURN_ERR;
8564}
8565
8566INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8567{
8568 return RETURN_ERR;
8569}
8570
8571//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8572//to set and read the inactivity time (in seconds) for steering under Idle condition
8573INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8574{
8575 return RETURN_ERR;
8576}
8577
8578INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8579{
8580 return RETURN_ERR;
8581}
8582
8583//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8584//pClientMAC[64]
8585//pSourceSSIDIndex[64]
8586//pDestSSIDIndex[64]
8587//pSteeringReason[256]
8588INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8589{
8590 //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
8591 *pSteeringTime=time(NULL);
8592 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8593 return RETURN_OK;
8594}
8595
8596INT wifi_ifConfigDown(INT apIndex)
8597{
8598 INT status = RETURN_OK;
8599 char cmd[64];
8600
8601 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8602 printf("%s: %s\n", __func__, cmd);
8603 system(cmd);
8604
8605 return status;
8606}
8607
8608INT wifi_ifConfigUp(INT apIndex)
8609{
8610 char interface_name[16] = {0};
8611 char cmd[128];
8612 char buf[1024];
8613
8614 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8615 return RETURN_ERR;
8616 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
8617 _syscmd(cmd, buf, sizeof(buf));
8618 return 0;
8619}
8620
8621//>> Deprecated. Replace with wifi_applyRadioSettings
8622INT wifi_pushBridgeInfo(INT apIndex)
8623{
8624 char interface_name[16] = {0};
8625 char ip[32] = {0};
8626 char subnet[32] = {0};
8627 char bridge[32] = {0};
8628 int vlanId = 0;
8629 char cmd[128] = {0};
8630 char buf[1024] = {0};
8631
8632 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8633 wifi_getApVlanID(apIndex,&vlanId);
8634
8635 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8636 return RETURN_ERR;
8637 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
8638 _syscmd(cmd,buf, sizeof(buf));
8639
8640 return 0;
8641}
8642
8643INT wifi_pushChannel(INT radioIndex, UINT channel)
8644{
8645 char interface_name[16] = {0};
8646 char cmd[128];
8647 char buf[1024];
8648 int apIndex;
8649
developer69b61b02023-03-07 17:17:44 +08008650 apIndex=(radioIndex==0)?0:1;
developer72fb0bb2023-01-11 09:46:29 +08008651 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8652 return RETURN_ERR;
8653 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
8654 _syscmd(cmd,buf, sizeof(buf));
8655
8656 return 0;
8657}
8658
8659INT wifi_pushChannelMode(INT radioIndex)
8660{
8661 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8662 return RETURN_ERR;
8663}
8664
8665INT wifi_pushDefaultValues(INT radioIndex)
8666{
8667 //Apply Comcast specified default radio settings instantly
8668 //AMPDU=1
8669 //AMPDUFrames=32
8670 //AMPDULim=50000
8671 //txqueuelen=1000
8672
8673 return RETURN_ERR;
8674}
8675
8676INT wifi_pushTxChainMask(INT radioIndex)
8677{
8678 //Apply default TxChainMask instantly
8679 return RETURN_ERR;
8680}
8681
8682INT wifi_pushRxChainMask(INT radioIndex)
8683{
8684 //Apply default RxChainMask instantly
8685 return RETURN_ERR;
8686}
8687
8688INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8689{
developer7e4a2a62023-04-06 19:56:03 +08008690 INT status;
developer72fb0bb2023-01-11 09:46:29 +08008691
developer7e4a2a62023-04-06 19:56:03 +08008692 status = wifi_setSSIDName(apIndex, ssid);
8693 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08008694
developer7e4a2a62023-04-06 19:56:03 +08008695 return status;
developer72fb0bb2023-01-11 09:46:29 +08008696}
8697
8698INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8699{
8700 //Apply default Ssid Advertisement instantly
8701 return RETURN_ERR;
8702}
8703
8704INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8705{
developere82c0ca2023-05-10 16:25:35 +08008706 time_t now;
8707
8708 time(&now);
8709 if (now > radio_up_time[radioIndex])
8710 *output = now - radio_up_time[radioIndex];
8711 else {
8712 *output = 0;
8713 return RETURN_ERR;
8714 }
8715
8716 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08008717}
8718
8719INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8720{
8721 return RETURN_OK;
8722}
8723
8724INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8725{
8726 return RETURN_OK;
8727}
8728
8729//To-do
8730INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8731{
8732 char output[16]={'\0'};
8733 char config_file[MAX_BUF_SIZE] = {0};
8734
8735 if (!output_string)
8736 return RETURN_ERR;
8737
8738 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8739 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8740
8741 if (strlen(output) == 0)
8742 snprintf(output_string, 64, "Disabled");
8743 else if (strncmp(output, "0", 1) == 0)
8744 snprintf(output_string, 64, "Disabled");
8745 else if (strncmp(output, "1", 1) == 0)
8746 snprintf(output_string, 64, "Optional");
8747 else if (strncmp(output, "2", 1) == 0)
8748 snprintf(output_string, 64, "Required");
8749 else {
8750 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8751 return RETURN_ERR;
8752 }
8753
8754 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
8755 return RETURN_OK;
8756}
8757INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8758{
8759 char str[MAX_BUF_SIZE]={'\0'};
8760 char cmd[MAX_CMD_SIZE]={'\0'};
8761 struct params params;
8762 char config_file[MAX_BUF_SIZE] = {0};
8763
8764 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8765 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8766 return RETURN_ERR;
8767
8768 params.name = "ieee80211w";
8769 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8770 params.value = "0";
8771 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8772 params.value = "1";
8773 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8774 params.value = "2";
8775 else{
8776 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8777 return RETURN_ERR;
8778 }
8779 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8780 wifi_hostapdWrite(config_file, &params, 1);
8781 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
8782 return RETURN_OK;
8783}
8784INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8785{
8786 char output[16]={'\0'};
8787 char config_file[MAX_BUF_SIZE] = {0};
8788
8789 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8790 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8791 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8792
8793 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8794 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8795
8796 return RETURN_OK;
8797}
8798
8799INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8800{
8801 return RETURN_OK;
8802}
8803
8804INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8805{
8806 return RETURN_OK;
8807}
8808
8809INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8810{
8811 return RETURN_OK;
8812}
8813
8814INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8815{
8816 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8817 char config_file[MAX_BUF_SIZE] = {0};
8818
8819 if (NULL == output)
8820 return RETURN_ERR;
8821 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8822 wifi_hostapdRead(config_file,"hw_mode",output,64);
8823
8824 if(strcmp(output,"b")==0)
8825 sprintf(output, "%s", "1,2,5.5,11");
8826 else if (strcmp(output,"a")==0)
8827 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8828 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8829 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8830
8831 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8832 return RETURN_OK;
8833}
8834
8835INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8836{
8837 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8838 char *temp;
8839 char temp_output[128];
8840 char temp_TransmitRates[128];
8841 char config_file[MAX_BUF_SIZE] = {0};
8842
8843 if (NULL == output)
8844 return RETURN_ERR;
8845
8846 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8847 wifi_hostapdRead(config_file,"supported_rates",output,64);
8848
8849 if (strlen(output) == 0) {
8850 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8851 return RETURN_OK;
8852 }
8853 strcpy(temp_TransmitRates,output);
8854 strcpy(temp_output,"");
8855 temp = strtok(temp_TransmitRates," ");
8856 while(temp!=NULL)
8857 {
8858 temp[strlen(temp)-1]=0;
8859 if((temp[0]=='5') && (temp[1]=='\0'))
8860 {
8861 temp="5.5";
8862 }
8863 strcat(temp_output,temp);
8864 temp = strtok(NULL," ");
8865 if(temp!=NULL)
8866 {
8867 strcat(temp_output,",");
8868 }
8869 }
8870 strcpy(output,temp_output);
8871 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8872
8873 return RETURN_OK;
8874}
8875
8876INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8877{
8878 return RETURN_OK;
8879}
8880
8881
8882INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8883{
8884 int i=0;
8885 char *temp;
8886 char temp1[128] = {0};
8887 char temp_output[128] = {0};
8888 char temp_TransmitRates[128] = {0};
8889 struct params params={'\0'};
8890 char config_file[MAX_BUF_SIZE] = {0};
8891 wifi_band band = wifi_index_to_band(wlanIndex);
8892
8893 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8894 if(NULL == output)
8895 return RETURN_ERR;
8896 strcpy(temp_TransmitRates,output);
8897
8898 for(i=0;i<strlen(temp_TransmitRates);i++)
8899 {
8900 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
8901 {
8902 continue;
8903 }
8904 else
8905 {
8906 return RETURN_ERR;
8907 }
8908 }
8909 strcpy(temp_output,"");
8910 temp = strtok(temp_TransmitRates,",");
8911 while(temp!=NULL)
8912 {
8913 strcpy(temp1,temp);
8914 if(band == band_5)
8915 {
8916 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
8917 {
8918 return RETURN_ERR;
8919 }
8920 }
8921
8922 if(strcmp(temp,"5.5")==0)
8923 {
8924 strcpy(temp1,"55");
8925 }
8926 else
8927 {
8928 strcat(temp1,"0");
8929 }
8930 strcat(temp_output,temp1);
8931 temp = strtok(NULL,",");
8932 if(temp!=NULL)
8933 {
8934 strcat(temp_output," ");
8935 }
8936 }
8937 strcpy(output,temp_output);
8938
8939 params.name = "supported_rates";
8940 params.value = output;
8941
8942 wifi_dbg_printf("\n%s:",__func__);
8943 wifi_dbg_printf("params.value=%s\n",params.value);
8944 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8945 wifi_hostapdWrite(config_file,&params,1);
8946 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8947
8948 return RETURN_OK;
8949}
8950
8951
8952static char *sncopy(char *dst, int dst_sz, const char *src)
8953{
8954 if (src && dst && dst_sz > 0) {
8955 strncpy(dst, src, dst_sz);
8956 dst[dst_sz - 1] = '\0';
8957 }
8958 return dst;
8959}
8960
8961static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8962{
8963 if (0 == strcmp(ht_mode, "HT40") ||
8964 0 == strcmp(ht_mode, "HT80") ||
8965 0 == strcmp(ht_mode, "HT160")) {
8966 switch (channel) {
8967 case 1 ... 7:
8968 case 36:
8969 case 44:
8970 case 52:
8971 case 60:
8972 case 100:
8973 case 108:
8974 case 116:
8975 case 124:
8976 case 132:
8977 case 140:
8978 case 149:
8979 case 157:
8980 return 1;
8981 case 8 ... 13:
8982 case 40:
8983 case 48:
8984 case 56:
8985 case 64:
8986 case 104:
8987 case 112:
8988 case 120:
8989 case 128:
8990 case 136:
8991 case 144:
8992 case 153:
8993 case 161:
8994 return -1;
8995 default:
8996 return -EINVAL;
8997 }
8998 }
8999
9000 return -EINVAL;
9001}
9002
9003static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
9004{
9005 int idx = channel%8;
9006 if (0 == strcmp(ht_mode, "HT40") ||
9007 0 == strcmp(ht_mode, "HT80") ||
9008 0 == strcmp(ht_mode, "HT160")) {
9009 switch (idx) {
9010 case 1:
9011 return 1;
9012 case 5:
9013 return -1;
9014 default:
9015 return -EINVAL;
9016 }
9017 }
9018
9019 return -EINVAL;
9020}
9021static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
9022{
9023 if (NULL == hw_mode) return;
9024
9025 if (0 == strcmp(hw_mode, "ac"))
9026 sncopy(bw_mode, bw_mode_len, "ht vht");
9027
9028 if (0 == strcmp(hw_mode, "n"))
9029 sncopy(bw_mode, bw_mode_len, "ht");
9030
9031 return;
9032}
9033
9034static int util_chan_to_freq(int chan)
9035{
9036 if (chan == 14)
9037 return 2484;
9038 else if (chan < 14)
9039 return 2407 + chan * 5;
9040 else if (chan >= 182 && chan <= 196)
9041 return 4000 + chan * 5;
9042 else
9043 return 5000 + chan * 5;
9044 return 0;
9045}
9046
9047static int util_6G_chan_to_freq(int chan)
9048{
9049 if (chan)
9050 return 5950 + chan * 5;
9051 else
9052 return 0;
developer69b61b02023-03-07 17:17:44 +08009053
developer72fb0bb2023-01-11 09:46:29 +08009054}
9055const int *util_unii_5g_chan2list(int chan, int width)
9056{
9057 static const int lists[] = {
9058 // <width>, <chan1>, <chan2>..., 0,
9059 20, 36, 0,
9060 20, 40, 0,
9061 20, 44, 0,
9062 20, 48, 0,
9063 20, 52, 0,
9064 20, 56, 0,
9065 20, 60, 0,
9066 20, 64, 0,
9067 20, 100, 0,
9068 20, 104, 0,
9069 20, 108, 0,
9070 20, 112, 0,
9071 20, 116, 0,
9072 20, 120, 0,
9073 20, 124, 0,
9074 20, 128, 0,
9075 20, 132, 0,
9076 20, 136, 0,
9077 20, 140, 0,
9078 20, 144, 0,
9079 20, 149, 0,
9080 20, 153, 0,
9081 20, 157, 0,
9082 20, 161, 0,
9083 20, 165, 0,
9084 40, 36, 40, 0,
9085 40, 44, 48, 0,
9086 40, 52, 56, 0,
9087 40, 60, 64, 0,
9088 40, 100, 104, 0,
9089 40, 108, 112, 0,
9090 40, 116, 120, 0,
9091 40, 124, 128, 0,
9092 40, 132, 136, 0,
9093 40, 140, 144, 0,
9094 40, 149, 153, 0,
9095 40, 157, 161, 0,
9096 80, 36, 40, 44, 48, 0,
9097 80, 52, 56, 60, 64, 0,
9098 80, 100, 104, 108, 112, 0,
9099 80, 116, 120, 124, 128, 0,
9100 80, 132, 136, 140, 144, 0,
9101 80, 149, 153, 157, 161, 0,
9102 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
9103 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
9104 -1 // final delimiter
9105 };
9106 const int *start;
9107 const int *p;
9108
9109 for (p = lists; *p != -1; p++) {
9110 if (*p == width) {
9111 for (start = ++p; *p != 0; p++) {
9112 if (*p == chan)
9113 return start;
9114 }
9115 }
9116 // move to the end of channel list of given width
9117 while (*p != 0) {
9118 p++;
9119 }
9120 }
9121
9122 return NULL;
9123}
9124
9125static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
9126{
9127 if (NULL == ht_mode)
9128 return 0;
9129
9130 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
9131 const int *chans = util_unii_5g_chan2list(channel, width);
9132 int sum = 0;
9133 int cnt = 0;
9134
9135 if (NULL == chans)
9136 return 0;
9137
9138 while (*chans) {
9139 sum += *chans;
9140 cnt++;
9141 chans++;
9142 }
9143 if (cnt == 0)
9144 return 0;
9145 return sum / cnt;
9146}
9147
9148static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
9149{
9150 if (NULL == ht_mode)
9151 return 0;
9152
9153 int width = strtol((ht_mode + 2), NULL, 10);
9154
9155 int idx = 0 ;
9156 int centerchan = 0;
9157 int chan_ofs = 1;
9158
9159 if (width == 40){
9160 idx = ((channel/4) + chan_ofs)%2;
9161 switch (idx) {
9162 case 0:
9163 centerchan = (channel - 2);
9164 break;
9165 case 1:
9166 centerchan = (channel + 2);
developer69b61b02023-03-07 17:17:44 +08009167 break;
developer72fb0bb2023-01-11 09:46:29 +08009168 default:
9169 return -EINVAL;
9170 }
9171 }else if (width == 80){
developer69b61b02023-03-07 17:17:44 +08009172 idx = ((channel/4) + chan_ofs)%4;
developer72fb0bb2023-01-11 09:46:29 +08009173 switch (idx) {
9174 case 0:
9175 centerchan = (channel - 6);
9176 break;
9177 case 1:
9178 centerchan = (channel + 6);
9179 break;
9180 case 2:
9181 centerchan = (channel + 2);
9182 break;
9183 case 3:
9184 centerchan = (channel - 2);
9185 break;
9186 default:
9187 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08009188 }
developer72fb0bb2023-01-11 09:46:29 +08009189 }else if (width == 160){
9190 switch (channel) {
9191 case 1 ... 29:
9192 centerchan = 15;
9193 break;
9194 case 33 ... 61:
9195 centerchan = 47;
9196 break;
9197 case 65 ... 93:
9198 centerchan = 79;
9199 break;
9200 case 97 ... 125:
9201 centerchan = 111;
9202 break;
9203 case 129 ... 157:
9204 centerchan = 143;
9205 break;
9206 case 161 ... 189:
9207 centerchan = 175;
9208 break;
9209 case 193 ... 221:
9210 centerchan = 207;
9211 break;
9212 default:
9213 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08009214 }
developer72fb0bb2023-01-11 09:46:29 +08009215 }
9216 return centerchan;
9217}
9218static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9219{
9220 BOOL onlyG, onlyN, onlyA;
9221 CHAR tmp[64];
9222 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9223 if (ret == RETURN_OK) {
9224 sncopy(hw_mode, hw_mode_size, tmp);
9225 }
9226 return ret;
9227}
9228
9229INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9230{
9231 // Sample commands:
9232 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9233 // hostapd_cli -i wifi0 chan_switch 30 2437
9234 char cmd[MAX_CMD_SIZE] = {0};
9235 char buf[MAX_BUF_SIZE] = {0};
9236 int freq = 0, ret = 0;
9237 char center_freq1_str[32] = ""; // center_freq1=%d
9238 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9239 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9240 char hw_mode[16] = ""; // n|ac
9241 char bw_mode[16] = ""; // ht|ht vht
9242 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
9243 char interface_name[16] = {0};
9244 int sec_chan_offset;
9245 int width;
9246 char config_file[64] = {0};
9247 BOOL stbcEnable = FALSE;
9248 char *ext_str = "None";
9249 wifi_band band = band_invalid;
9250 int center_chan = 0;
9251 int center_freq1 = 0;
developer4903e3f2023-05-15 10:04:40 +08009252 struct params mwctl = {0};
9253 char str_channel[8]={0};
developer72fb0bb2023-01-11 09:46:29 +08009254
9255 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
9256
9257 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9258 return RETURN_ERR;
9259
9260 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9261
9262 band = wifi_index_to_band(radioIndex);
9263
9264 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
9265
9266 // Get radio mode HT20|HT40|HT80 etc.
9267 if (channel){
9268 if (band == band_6){
9269 freq = util_6G_chan_to_freq(channel);
9270 }else{
9271 freq = util_chan_to_freq(channel);
9272 }
9273 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
9274
9275 // Provide bandwith if specified
9276 if (channel_width_MHz > 20) {
9277 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9278 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9279 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
9280
9281 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9282 }else if (channel_width_MHz == 20){
9283 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9284 }
9285
9286
9287 if (channel_width_MHz > 20) {
9288 if (band == band_6){
9289 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9290 if(center_chan){
9291 center_freq1 = util_6G_chan_to_freq(center_chan);
9292 }
9293 }else{
9294 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9295 if(center_chan){
9296 center_freq1 = util_chan_to_freq(center_chan);
9297 }
9298 }
developer69b61b02023-03-07 17:17:44 +08009299
developer72fb0bb2023-01-11 09:46:29 +08009300 if (center_freq1)
9301 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
developer69b61b02023-03-07 17:17:44 +08009302
developer72fb0bb2023-01-11 09:46:29 +08009303 }
9304
9305 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9306 if (band == band_6){
9307 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9308 }else{
9309 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
9310 }
9311 if (sec_chan_offset != -EINVAL)
9312 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
9313
9314 // Only the first AP, other are hanging on the same radio
9315 int apIndex = radioIndex;
developer4903e3f2023-05-15 10:04:40 +08009316 /* snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
developer72fb0bb2023-01-11 09:46:29 +08009317 interface_name, csa_beacon_count, freq,
developer4903e3f2023-05-15 10:04:40 +08009318 sec_chan_offset_str, center_freq1_str, opt_chan_info_str); */
9319 snprintf(str_channel, sizeof(str_channel), "%d", channel);
9320 mwctl.name = "channel num=";
9321 mwctl.value = str_channel;
9322 ret = wifi_mwctlSet(radioIndex, &mwctl, BASE_PHY_INDEX);
9323 if (ret != RETURN_OK) {
9324 fprintf(stderr, "%s: wifi_mwctlSet return error.\n", __func__);
9325 return RETURN_ERR;
9326 }
9327 /* wifi_dbg_printf("execute: '%s'\n", cmd);
9328 ret = _syscmd(cmd, buf, sizeof(buf));*/
developer72fb0bb2023-01-11 09:46:29 +08009329 wifi_reloadAp(radioIndex);
9330
9331 ret = wifi_setRadioChannel(radioIndex, channel);
9332 if (ret != RETURN_OK) {
9333 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9334 return RETURN_ERR;
9335 }
9336
9337 if (sec_chan_offset == 1) ext_str = "Above";
9338 else if (sec_chan_offset == -1) ext_str = "Below";
9339
9340 wifi_setRadioCenterChannel(radioIndex, center_chan);
9341
9342 } else {
9343 if (channel_width_MHz > 20)
9344 ext_str = "Above";
9345 }
9346
9347 wifi_setRadioExtChannel(radioIndex, ext_str);
9348
9349 char mhz_str[16];
9350 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
9351 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
9352
9353 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9354
9355 return RETURN_OK;
9356}
9357
9358INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9359{
9360 int index = -1;
9361 wifi_neighbor_ap2_t *scan_array = NULL;
9362 char cmd[256]={0};
9363 char buf[128]={0};
9364 char file_name[32] = {0};
9365 char filter_SSID[32] = {0};
9366 char line[256] = {0};
9367 char interface_name[16] = {0};
9368 char *ret = NULL;
9369 int freq=0;
9370 FILE *f = NULL;
9371 size_t len=0;
9372 int channels_num = 0;
9373 int vht_channel_width = 0;
9374 int get_noise_ret = RETURN_ERR;
9375 bool filter_enable = false;
9376 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
9377 int phyId = 0;
9378
9379 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
9380
9381 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9382 f = fopen(file_name, "r");
9383 if (f != NULL) {
9384 fgets(filter_SSID, sizeof(file_name), f);
9385 if (strlen(filter_SSID) != 0)
9386 filter_enable = true;
9387 fclose(f);
9388 }
9389
9390 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
9391 return RETURN_ERR;
9392
9393 phyId = radio_index_to_phy(radio_index);
9394
9395 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
9396 _syscmd(cmd, buf, sizeof(buf));
9397 channels_num = strtol(buf, NULL, 10);
9398
9399 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9400 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
9401 fprintf(stderr, "cmd: %s\n", cmd);
9402 if ((f = popen(cmd, "r")) == NULL) {
9403 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9404 return RETURN_ERR;
9405 }
developer69b61b02023-03-07 17:17:44 +08009406
developer72fb0bb2023-01-11 09:46:29 +08009407 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9408 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08009409
developer72fb0bb2023-01-11 09:46:29 +08009410 ret = fgets(line, sizeof(line), f);
9411 while (ret != NULL) {
9412 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08009413 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
developer72fb0bb2023-01-11 09:46:29 +08009414 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9415 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9416
9417 if (!filter_BSS) {
9418 index++;
9419 wifi_neighbor_ap2_t *tmp;
9420 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9421 if (tmp == NULL) { // no more memory to use
9422 index--;
9423 wifi_dbg_printf("%s: realloc failed\n", __func__);
9424 break;
9425 }
9426 scan_array = tmp;
9427 }
9428 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9429
9430 filter_BSS = false;
9431 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9432 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9433 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9434 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9435 } else if (strstr(line, "freq") != NULL) {
9436 sscanf(line," freq: %d", &freq);
9437 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
9438
9439 if (freq >= 2412 && freq <= 2484) {
9440 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9441 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9442 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9443 }
9444 else if (freq >= 5160 && freq <= 5805) {
9445 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9446 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9447 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9448 }
9449
9450 scan_array[index].ap_Noise = 0;
9451 if (get_noise_ret == RETURN_OK) {
9452 for (int i = 0; i < channels_num; i++) {
9453 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9454 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9455 break;
9456 }
9457 }
9458 }
9459 } else if (strstr(line, "beacon interval") != NULL) {
9460 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9461 } else if (strstr(line, "signal") != NULL) {
9462 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9463 } else if (strstr(line,"SSID") != NULL) {
9464 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9465 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9466 filter_BSS = true;
9467 }
9468 } else if (strstr(line, "Supported rates") != NULL) {
9469 char SRate[80] = {0}, *tmp = NULL;
9470 memset(buf, 0, sizeof(buf));
9471 strcpy(SRate, line);
9472 tmp = strtok(SRate, ":");
9473 tmp = strtok(NULL, ":");
9474 strcpy(buf, tmp);
9475 memset(SRate, 0, sizeof(SRate));
9476
9477 tmp = strtok(buf, " \n");
9478 while (tmp != NULL) {
9479 strcat(SRate, tmp);
9480 if (SRate[strlen(SRate) - 1] == '*') {
9481 SRate[strlen(SRate) - 1] = '\0';
9482 }
9483 strcat(SRate, ",");
9484
9485 tmp = strtok(NULL, " \n");
9486 }
9487 SRate[strlen(SRate) - 1] = '\0';
9488 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9489 } else if (strstr(line, "DTIM") != NULL) {
9490 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9491 } else if (strstr(line, "VHT capabilities") != NULL) {
9492 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9493 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9494 } else if (strstr(line, "HT capabilities") != NULL) {
9495 strcat(scan_array[index].ap_SupportedStandards, ",n");
9496 strcpy(scan_array[index].ap_OperatingStandards, "n");
9497 } else if (strstr(line, "VHT operation") != NULL) {
9498 ret = fgets(line, sizeof(line), f);
9499 sscanf(line," * channel width: %d", &vht_channel_width);
9500 if(vht_channel_width == 1) {
9501 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9502 } else {
9503 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9504 }
9505 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9506 continue;
9507 } else if (strstr(line, "HT operation") != NULL) {
9508 ret = fgets(line, sizeof(line), f);
9509 sscanf(line," * secondary channel offset: %s", &buf);
9510 if (!strcmp(buf, "above")) {
9511 //40Mhz +
9512 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
9513 }
9514 else if (!strcmp(buf, "below")) {
9515 //40Mhz -
9516 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9517 } else {
9518 //20Mhz
9519 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
9520 }
9521 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9522 continue;
9523 } else if (strstr(line, "HE capabilities") != NULL) {
9524 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9525 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9526 ret = fgets(line, sizeof(line), f);
9527 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9528 if (strstr(line, "HE40/2.4GHz") != NULL)
9529 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9530 else
9531 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9532 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9533 if (strstr(line, "HE80/5GHz") != NULL) {
9534 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9535 ret = fgets(line, sizeof(line), f);
9536 } else
9537 continue;
9538 if (strstr(line, "HE160/5GHz") != NULL)
9539 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
9540 }
9541 continue;
9542 } else if (strstr(line, "WPA") != NULL) {
9543 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9544 } else if (strstr(line, "RSN") != NULL) {
9545 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9546 } else if (strstr(line, "Group cipher") != NULL) {
9547 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9548 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9549 strcpy(scan_array[index].ap_EncryptionMode, "AES");
9550 }
9551 }
9552 ret = fgets(line, sizeof(line), f);
9553 }
9554
9555 if (!filter_BSS) {
9556 *output_array_size = index + 1;
9557 } else {
9558 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9559 *output_array_size = index;
9560 }
9561 *neighbor_ap_array = scan_array;
9562 pclose(f);
9563 free(channels_noise_arr);
9564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9565 return RETURN_OK;
9566}
9567
9568INT wifi_getApAssociatedDeviceStats(
9569 INT apIndex,
9570 mac_address_t *clientMacAddress,
9571 wifi_associated_dev_stats_t *associated_dev_stats,
9572 u64 *handle)
9573{
9574 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9575 char interface_name[50] = {0};
9576 char cmd[1024] = {0};
9577 char mac_str[18] = {0};
9578 char *key = NULL;
9579 char *val = NULL;
9580 FILE *f = NULL;
9581 char *line = NULL;
9582 size_t len = 0;
9583
9584 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9585 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9586 return RETURN_ERR;
9587 }
9588
9589 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9590 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9591 if((f = popen(cmd, "r")) == NULL) {
9592 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9593 return RETURN_ERR;
9594 }
9595
9596 while ((getline(&line, &len, f)) != -1) {
9597 key = strtok(line,":");
9598 val = strtok(NULL,":");
9599
9600 if(!strncmp(key,"rx bytes",8))
9601 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9602 if(!strncmp(key,"tx bytes",8))
9603 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9604 if(!strncmp(key,"rx packets",10))
9605 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9606 if(!strncmp(key,"tx packets",10))
9607 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9608 if(!strncmp(key,"tx retries",10))
9609 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9610 if(!strncmp(key,"tx failed",9))
9611 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9612 if(!strncmp(key,"rx drop misc",13))
9613 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9614 if(!strncmp(key,"rx bitrate",10)) {
9615 val = strtok(val, " ");
9616 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9617 }
9618 if(!strncmp(key,"tx bitrate",10)) {
9619 val = strtok(val, " ");
9620 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9621 }
9622 }
9623 free(line);
9624 pclose(f);
9625 return RETURN_OK;
9626}
9627
9628INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9629{
developer7e4a2a62023-04-06 19:56:03 +08009630 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009631 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9632
developer7e4a2a62023-04-06 19:56:03 +08009633 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9634
developer72fb0bb2023-01-11 09:46:29 +08009635 if (NULL == output_string)
9636 return RETURN_ERR;
9637
9638 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9639 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08009640
9641 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\\n'", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08009642 _syscmd(cmd, buf, sizeof(buf));
9643
9644 //size of SSID name restricted to value less than 32 bytes
9645 snprintf(output_string, 32, "%s", buf);
developer7e4a2a62023-04-06 19:56:03 +08009646 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08009647
9648 return RETURN_OK;
9649}
9650
9651INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9652{
developer7e4a2a62023-04-06 19:56:03 +08009653 char cmd[MAX_CMD_SIZE] = {0};
9654 char buf[MAX_BUF_SIZE] = {0};
9655 char inf_name[IF_NAME_SIZE] = {0};
9656 char policy = 0;
developer72fb0bb2023-01-11 09:46:29 +08009657
9658 if (!output_filterMode)
9659 return RETURN_ERR;
9660
developer7e4a2a62023-04-06 19:56:03 +08009661 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
9662 return RETURN_ERR;
9663
9664 /* mwctl get acl policy */
9665 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | grep policy | cut -d '=' -f2 | tr -d '\\n'", inf_name);
9666 _syscmd(cmd, buf, sizeof(buf));
9667
9668
9669 policy = atoi(buf);
9670
9671 if (policy < 0 || policy > 2) {
9672 printf("%s:get wrong acl policy!!!\n", __func__);
9673 *output_filterMode = 0;
9674 return RETURN_ERR;
9675 } else
9676 *output_filterMode = policy;
9677
developer72fb0bb2023-01-11 09:46:29 +08009678
9679 return RETURN_OK;
9680}
9681
9682INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9683{
9684 FILE *fp = NULL;
9685 char str[MAX_BUF_SIZE] = {0};
9686 int wificlientindex = 0 ;
9687 int count = 0;
9688 int signalstrength = 0;
9689 int arr[MACADDRESS_SIZE] = {0};
9690 unsigned char mac[MACADDRESS_SIZE] = {0};
9691 UINT wifi_count = 0;
9692 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9693 char pipeCmd[MAX_CMD_SIZE] = {0};
9694
9695 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9696 *output_array_size = 0;
9697 *associated_dev_array = NULL;
9698 char interface_name[50] = {0};
9699
9700 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9701 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9702 return RETURN_ERR;
9703 }
9704
9705 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9706 fp = popen(pipeCmd, "r");
9707 if (fp == NULL)
9708 {
9709 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9710 return RETURN_ERR;
9711 }
9712
9713 /* Read the output a line at a time - output it. */
9714 fgets(str, sizeof(str)-1, fp);
9715 wifi_count = (unsigned int) atoi ( str );
9716 *output_array_size = wifi_count;
9717 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9718 pclose(fp);
9719
9720 if(wifi_count == 0)
9721 {
9722 return RETURN_OK;
9723 }
9724 else
9725 {
9726 wifi_associated_dev2_t* temp = NULL;
9727 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9728 *associated_dev_array = temp;
9729 if(temp == NULL)
9730 {
9731 printf("Error Statement. Insufficient memory \n");
9732 return RETURN_ERR;
9733 }
9734
9735 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9736 system(pipeCmd);
9737
9738 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9739 if(fp == NULL)
9740 {
9741 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9742 return RETURN_ERR;
9743 }
9744 fclose(fp);
9745
9746 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
9747 fp = popen(pipeCmd, "r");
9748 if(fp)
9749 {
9750 for(count =0 ; count < wifi_count; count++)
9751 {
9752 fgets(str, MAX_BUF_SIZE, fp);
9753 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9754 {
9755 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9756 {
9757 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9758
9759 }
9760 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9761 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]);
9762 }
9763 temp[count].cli_AuthenticationState = 1; //TODO
9764 temp[count].cli_Active = 1; //TODO
9765 }
9766 pclose(fp);
9767 }
9768
9769 //Updating RSSI per client
9770 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
9771 fp = popen(pipeCmd, "r");
9772 if(fp)
9773 {
9774 pclose(fp);
9775 }
9776 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9777 if(fp)
9778 {
9779 for(count =0 ; count < wifi_count ;count++)
9780 {
9781 fgets(str, MAX_BUF_SIZE, fp);
9782 signalstrength = atoi(str);
9783 temp[count].cli_RSSI = signalstrength;
9784 }
9785 pclose(fp);
9786 }
9787
9788
9789 //LastDataDownlinkRate
9790 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
9791 fp = popen(pipeCmd, "r");
9792 if (fp)
9793 {
9794 pclose(fp);
9795 }
9796 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9797 if (fp)
9798 {
9799 for (count = 0; count < wifi_count; count++)
9800 {
9801 fgets(str, MAX_BUF_SIZE, fp);
9802 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9803 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9804 }
9805 pclose(fp);
9806 }
9807
9808 //LastDataUplinkRate
9809 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
9810 fp = popen(pipeCmd, "r");
9811 if (fp)
9812 {
9813 pclose(fp);
9814 }
9815 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9816 if (fp)
9817 {
9818 for (count = 0; count < wifi_count; count++)
9819 {
9820 fgets(str, MAX_BUF_SIZE, fp);
9821 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9822 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9823 }
9824 pclose(fp);
9825 }
9826 }
9827 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9828 return RETURN_OK;
9829
9830}
9831
9832INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9833{
9834#if 0
9835 /*char buf[1024] = {0};
9836 sprintf(cmd, "ifconfig %s ", interface_name);
9837 _syscmd(cmd, buf, sizeof(buf));*/
9838
9839 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9840 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9841 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9842 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9843
9844 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.
9845 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].
9846 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].
9847 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].
9848 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9849 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9850
9851 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9852 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9853 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9854 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.
9855 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.
9856 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.
9857 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.
9858 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.
9859 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.
9860 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.
9861 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9862#endif
9863
9864 FILE *fp = NULL;
9865 char interface_name[50] = {0};
9866 char pipeCmd[128] = {0};
9867 char str[256] = {0};
9868 wifi_ssidTrafficStats2_t *out = output_struct;
9869
9870 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9871 if (!output_struct)
9872 return RETURN_ERR;
9873
9874 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9875 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
9876 return RETURN_ERR;
9877 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
9878
9879 fp = popen(pipeCmd, "r");
9880 if (fp == NULL) {
9881 fprintf(stderr, "%s: popen failed\n", __func__);
9882 return RETURN_ERR;
9883 }
9884 fgets(str, sizeof(str), fp);
9885 pclose(fp);
9886
9887 if (strlen(str) == 0) // interface not exist
9888 return RETURN_OK;
9889
9890 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9891 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
9892
9893 memset(str, 0, sizeof(str));
9894 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
9895 fp = popen(pipeCmd, "r");
9896 if (fp == NULL) {
9897 fprintf(stderr, "%s: popen failed\n", __func__);
9898 return RETURN_ERR;
9899 }
9900 fgets(str, sizeof(str), fp);
9901
9902 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9903 &out->ssid_BroadcastPacketsSent);
9904 pclose(fp);
9905
9906 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9907 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9908
9909 // Not supported
9910 output_struct->ssid_RetransCount = 0;
9911 output_struct->ssid_FailedRetransCount = 0;
9912 output_struct->ssid_RetryCount = 0;
9913 output_struct->ssid_MultipleRetryCount = 0;
9914 output_struct->ssid_ACKFailureCount = 0;
9915 output_struct->ssid_AggregatedPacketCount = 0;
9916
9917 return RETURN_OK;
9918}
9919
9920//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).
9921INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9922{
9923 char output_val[16]={'\0'};
9924 char config_file[MAX_BUF_SIZE] = {0};
9925
9926 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9927 if (!output)
9928 return RETURN_ERR;
9929 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9930 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9931
9932 if( strcmp(output_val,"1") == 0 )
9933 *output = TRUE;
9934 else
9935 *output = FALSE;
9936 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9937
9938 return RETURN_OK;
9939}
9940
9941INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9942{
9943 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9944 char str[MAX_BUF_SIZE]={'\0'};
9945 char string[MAX_BUF_SIZE]={'\0'};
9946 char cmd[MAX_CMD_SIZE]={'\0'};
9947 char *ch;
9948 char config_file[MAX_BUF_SIZE] = {0};
9949 struct params params;
9950
9951 if(enable == TRUE)
9952 strcpy(string,"1");
9953 else
9954 strcpy(string,"0");
9955
9956 params.name = "ap_isolate";
9957 params.value = string;
9958
9959 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9960 wifi_hostapdWrite(config_file,&params,1);
9961 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9962
9963 return RETURN_OK;
9964}
9965
9966INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9967{
developera1255e42023-05-13 17:45:02 +08009968 char mgmtpwr_file[32] = {0};
9969 char cmd[64] = {0};
9970 char buf[32]={0};
9971
developer72fb0bb2023-01-11 09:46:29 +08009972 if (NULL == output_dBm)
9973 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08009974 snprintf(mgmtpwr_file, sizeof(mgmtpwr_file), "%s%d.txt", MGMT_POWER_CTRL, apIndex);
9975 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mgmtpwr_file);
9976 _syscmd(cmd, buf, sizeof(buf));
9977 if (strlen(buf) > 0)
9978 *output_dBm = strtol(buf, NULL, 10);
9979 else
9980 *output_dBm = 23;
developer72fb0bb2023-01-11 09:46:29 +08009981 return RETURN_OK;
9982}
9983
9984INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9985{
developera1255e42023-05-13 17:45:02 +08009986 char interface_name[16] = {0};
9987 char cmd[128]={0};
9988 char buf[128]={0};
9989 char mgmt_pwr_file[128]={0};
9990 FILE *f = NULL;
9991
9992 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9993
9994 if (wifi_GetInterfaceName(wlanIndex, interface_name) != RETURN_OK)
9995 return RETURN_ERR;
9996 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr mgmt_frame_pwr=%d", interface_name, dBm);
9997 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR) {
9998 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
9999 return RETURN_ERR;
10000 }
10001 snprintf(mgmt_pwr_file, sizeof(mgmt_pwr_file), "%s%d.txt", MGMT_POWER_CTRL, wlanIndex);
10002 f = fopen(mgmt_pwr_file, "w");
10003 if (f == NULL) {
10004 fprintf(stderr, "%s: fopen failed\n", __func__);
10005 return RETURN_ERR;
10006 }
10007 fprintf(f, "%d", dBm);
10008 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +080010009 return RETURN_OK;
10010}
10011INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
10012{
10013 return RETURN_OK;
10014}
10015INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
10016{
10017 return RETURN_OK;
10018}
10019INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
10020{
10021 return RETURN_OK;
10022}
10023INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
10024{
10025 return RETURN_OK;
10026}
10027INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
10028{
10029 char config_file[MAX_BUF_SIZE] = {0};
10030 struct params list;
10031
10032 list.name = "bss_transition";
10033 list.value = activate?"1":"0";
10034 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
10035 wifi_hostapdWrite(config_file, &list, 1);
10036
10037 return RETURN_OK;
10038}
10039wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
10040
10041void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
10042{
10043 return;
10044}
10045
10046INT wifi_setApCsaDeauth(INT apIndex, INT mode)
10047{
10048 // TODO Implement me!
10049 return RETURN_OK;
10050}
10051
10052INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
10053{
10054 char file_name[128] = {0};
10055 char buf[128] = {0};
10056 FILE *f = NULL;
10057 int max_num_radios = 0;
10058
10059 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10060
10061 wifi_getMaxRadioNumber(&max_num_radios);
10062 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
10063 for (int index = 0; index < max_num_radios; index++) {
10064 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
10065 f = fopen(file_name, "w");
10066 if (f == NULL)
10067 return RETURN_ERR;
10068 // For mode == 0 is to disable filter, just don't write to the file.
10069 if (mode)
10070 fprintf(f, "%s", essid);
10071
10072 fclose(f);
10073 }
10074 } else { // special case, need to set AP's SSID as filter for each radio.
10075 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
10076 f = fopen(file_name, "w");
10077 if (f == NULL)
10078 return RETURN_ERR;
10079
10080 // For mode == 0 is to disable filter, just don't write to the file.
10081 if (mode)
10082 fprintf(f, "%s", essid);
10083
10084 fclose(f);
10085 }
10086
10087 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10088 return RETURN_OK;
10089}
10090
10091INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
10092{
10093 // TODO Implement me!
10094 //Apply wifi_pushRadioChannel() instantly
10095 return RETURN_ERR;
10096}
10097
10098INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
10099{
10100 // TODO Implement me!
10101 return RETURN_OK;
10102}
10103
10104#ifdef HAL_NETLINK_IMPL
10105static int tidStats_callback(struct nl_msg *msg, void *arg) {
10106 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10107 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10108 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10109 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
10110 int rem , tid_index = 0;
10111
10112 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
10113 wifi_associated_dev_tid_entry_t *stats_entry;
10114
10115 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
10116 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
10117 };
10118 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
10119 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
10120 };
10121
10122 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10123 genlmsg_attrlen(gnlh, 0), NULL);
10124
10125
10126 if (!tb[NL80211_ATTR_STA_INFO]) {
10127 fprintf(stderr, "station stats missing!\n");
10128 return NL_SKIP;
10129 }
10130
10131 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
10132 tb[NL80211_ATTR_STA_INFO],
10133 stats_policy)) {
10134 fprintf(stderr, "failed to parse nested attributes!\n");
10135 return NL_SKIP;
10136 }
10137
10138 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
10139 {
10140 stats_entry = &out->tid_array[tid_index];
10141
10142 stats_entry->tid = tid_index;
10143 stats_entry->ac = _tid_ac_index_get[tid_index];
10144
10145 if(sinfo[NL80211_STA_INFO_TID_STATS])
10146 {
10147 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
10148 printf("failed to parse nested stats attributes!");
10149 return NL_SKIP;
10150 }
10151 }
10152 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10153 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10154
10155 if(tid_index < (PS_MAX_TID - 1))
10156 tid_index++;
10157 }
10158 //ToDo: sum_time_ms, ewma_time_ms
10159 return NL_SKIP;
10160}
10161#endif
10162
10163INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
10164{
10165#ifdef HAL_NETLINK_IMPL
10166 Netlink nl;
10167 char if_name[10];
10168 char interface_name[16] = {0};
10169
10170 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10171 return RETURN_ERR;
10172
10173 snprintf(if_name, sizeof(if_name), "%s", interface_name);
10174
10175 nl.id = initSock80211(&nl);
10176
10177 if (nl.id < 0) {
10178 fprintf(stderr, "Error initializing netlink \n");
10179 return -1;
10180 }
10181
10182 struct nl_msg* msg = nlmsg_alloc();
10183
10184 if (!msg) {
10185 fprintf(stderr, "Failed to allocate netlink message.\n");
10186 nlfree(&nl);
10187 return -2;
10188 }
10189
10190 genlmsg_put(msg,
10191 NL_AUTO_PORT,
10192 NL_AUTO_SEQ,
10193 nl.id,
10194 0,
10195 0,
10196 NL80211_CMD_GET_STATION,
10197 0);
10198
10199 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10200 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10201 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
10202 nl_send_auto(nl.socket, msg);
10203 nl_recvmsgs(nl.socket, nl.cb);
10204 nlmsg_free(msg);
10205 nlfree(&nl);
10206 return RETURN_OK;
10207#else
10208//iw implementation
10209#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
10210#define TOTAL_MAX_LINES 50
10211
10212 char buf[256] = {'\0'}; /* or other suitable maximum line size */
10213 char if_name[32] = {0};
10214 FILE *fp=NULL;
10215 char pipeCmd[1024]= {'\0'};
10216 int lines,tid_index=0;
10217 char mac_addr[20] = {'\0'};
10218
10219 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10220 return RETURN_ERR;
10221
10222 wifi_associated_dev_tid_entry_t *stats_entry;
10223
10224 strcpy(mac_addr,clientMacAddress);
10225
10226 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
10227 fp= popen(pipeCmd,"r");
10228 if(fp == NULL)
10229 {
10230 perror("popen for station dump failed\n");
10231 return RETURN_ERR;
10232 }
10233 pclose(fp);
10234
10235 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
10236 fp=popen(pipeCmd,"r");
10237 if(fp == NULL)
10238 {
10239 perror("popen for grep station failed\n");
10240 return RETURN_ERR;
10241 }
10242 else if(fgets(buf,sizeof(buf),fp) != NULL)
10243 lines=atoi(buf);
10244 else
10245 {
10246 pclose(fp);
10247 fprintf(stderr,"No devices are connected \n");
10248 return RETURN_ERR;
10249 }
10250 pclose(fp);
10251
10252 if(lines == 1)
10253 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
10254
10255 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
10256 {
10257 stats_entry = &tid_stats->tid_array[tid_index];
10258 stats_entry->tid = tid_index;
10259
10260 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);
10261
10262 fp=popen(pipeCmd,"r");
10263 if(fp ==NULL)
10264 {
10265 perror("Failed to read from tid file \n");
10266 return RETURN_ERR;
10267 }
10268 else if(fgets(buf,sizeof(buf),fp) != NULL)
10269 stats_entry->num_msdus = atol(buf);
10270
10271 pclose(fp);
10272 stats_entry->ac = _tid_ac_index_get[tid_index];
10273// TODO:
10274// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
10275// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
10276 }
10277 return RETURN_OK;
10278#endif
10279}
10280
10281
10282INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
10283{
10284 char interface_name[16] = {0};
10285 char cmd[128]={0};
10286 char buf[128]={0};
10287 int freq = 0;
10288
10289 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10290
10291 // full mode is used to scan all channels.
10292 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10293 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
10294 ieee80211_channel_to_frequency(chan_list[0], &freq);
10295
10296 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10297 return RETURN_ERR;
10298
10299 if (freq)
10300 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
10301 else
10302 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
10303
10304 _syscmd(cmd, buf, sizeof(buf));
10305 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10306
10307 return RETURN_OK;
10308}
10309
10310
10311INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10312{
10313 // TODO Implement me!
10314 return RETURN_ERR;
10315}
10316
10317INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10318{
10319 // TODO Implement me!
10320 return RETURN_ERR;
10321}
10322
10323INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10324{
10325 // TODO Implement me!
10326 return RETURN_ERR;
10327}
10328
10329INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10330{
10331 // TODO Implement me!
10332 return RETURN_ERR;
10333}
10334
10335INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10336{
10337 // TODO Implement me!
10338 return RETURN_ERR;
10339}
10340
10341INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10342{
10343 // TODO Implement me!
10344 return RETURN_ERR;
10345}
10346
10347INT wifi_steering_eventUnregister(void)
10348{
10349 // TODO Implement me!
10350 return RETURN_ERR;
10351}
10352
10353INT wifi_delApAclDevices(INT apIndex)
10354{
developer7e4a2a62023-04-06 19:56:03 +080010355 char cmd[MAX_CMD_SIZE] = {0};
10356 char buf[MAX_BUF_SIZE] = {0};
10357 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080010358
developer7e4a2a62023-04-06 19:56:03 +080010359 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
10360 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080010361
developer7e4a2a62023-04-06 19:56:03 +080010362 /* mwctl acl clear all stas */
10363 snprintf(cmd, sizeof(cmd), "mwctl %s acl clear_all", inf_name);
10364 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080010365
10366 return RETURN_OK;
10367}
10368
10369#ifdef HAL_NETLINK_IMPL
10370static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10371 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10372 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10373 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10374 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10375 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10376 char mac_addr[20],dev[20];
10377
10378 nla_parse(tb,
10379 NL80211_ATTR_MAX,
10380 genlmsg_attrdata(gnlh, 0),
10381 genlmsg_attrlen(gnlh, 0),
10382 NULL);
10383
10384 if(!tb[NL80211_ATTR_STA_INFO]) {
10385 fprintf(stderr, "sta stats missing!\n");
10386 return NL_SKIP;
10387 }
10388
10389 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10390 fprintf(stderr, "failed to parse nested attributes!\n");
10391 return NL_SKIP;
10392 }
10393 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10394
10395 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10396
10397 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10398 fprintf(stderr, "failed to parse nested rate attributes!");
10399 return NL_SKIP;
10400 }
10401
10402 if(sinfo[NL80211_STA_INFO_TID_STATS])
10403 {
10404 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10405 printf("failed to parse nested stats attributes!");
10406 return NL_SKIP;
10407 }
10408 }
10409
10410 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10411 {
10412 printf("Type is VHT\n");
10413 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10414 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10415
10416 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10417 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10418 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10419 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10420 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10421 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10422 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10423 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10424 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10425 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10426 }
10427 else
10428 {
10429 printf(" OFDM or CCK \n");
10430 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10431 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10432 }
10433
10434 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10435 if(rinfo[NL80211_RATE_INFO_MCS])
10436 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10437 }
10438 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10439 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10440 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10441 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10442
10443 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10444 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10445
10446 if (sinfo[NL80211_STA_INFO_SIGNAL])
10447 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10448 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10449 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10450 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10451 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10452 //rssi_array need to be filled
10453 return NL_SKIP;
10454}
10455#endif
10456
10457INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10458{
10459#ifdef HAL_NETLINK_IMPL
10460 Netlink nl;
10461 char if_name[32];
10462 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10463 return RETURN_ERR;
10464
10465 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10466
10467 if (*output_array_size <= 0)
10468 return RETURN_OK;
10469
10470 nl.id = initSock80211(&nl);
10471
10472 if (nl.id < 0) {
10473 fprintf(stderr, "Error initializing netlink \n");
10474 return 0;
10475 }
10476
10477 struct nl_msg* msg = nlmsg_alloc();
10478
10479 if (!msg) {
10480 fprintf(stderr, "Failed to allocate netlink message.\n");
10481 nlfree(&nl);
10482 return 0;
10483 }
10484
10485 genlmsg_put(msg,
10486 NL_AUTO_PORT,
10487 NL_AUTO_SEQ,
10488 nl.id,
10489 0,
10490 0,
10491 NL80211_CMD_GET_STATION,
10492 0);
10493
10494 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10495 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10496 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10497 nl_send_auto(nl.socket, msg);
10498 nl_recvmsgs(nl.socket, nl.cb);
10499 nlmsg_free(msg);
10500 nlfree(&nl);
10501 return RETURN_OK;
10502#else
10503 //TODO Implement me
10504 return RETURN_OK;
10505#endif
10506}
10507
10508#ifdef HAL_NETLINK_IMPL
10509static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10510 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10511 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10512 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10513 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10514 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10515 char mac_addr[20],dev[20];
10516
10517 nla_parse(tb,
10518 NL80211_ATTR_MAX,
10519 genlmsg_attrdata(gnlh, 0),
10520 genlmsg_attrlen(gnlh, 0),
10521 NULL);
10522
10523 if(!tb[NL80211_ATTR_STA_INFO]) {
10524 fprintf(stderr, "sta stats missing!\n");
10525 return NL_SKIP;
10526 }
10527
10528 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10529 fprintf(stderr, "failed to parse nested attributes!\n");
10530 return NL_SKIP;
10531 }
10532
10533 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10534
10535 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10536
10537 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10538 fprintf(stderr, "failed to parse nested rate attributes!");
10539 return NL_SKIP;
10540 }
10541
10542 if(sinfo[NL80211_STA_INFO_TID_STATS])
10543 {
10544 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10545 printf("failed to parse nested stats attributes!");
10546 return NL_SKIP;
10547 }
10548 }
10549 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10550 {
10551 printf("Type is VHT\n");
10552 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10553 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10554
10555 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10556 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10557 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10558 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10559 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10560 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10561 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10562 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10563 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10564 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10565 }
10566 else
10567 {
10568 printf(" OFDM or CCK \n");
10569 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10570 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10571 }
10572
10573 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10574 if(rinfo[NL80211_RATE_INFO_MCS])
10575 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10576 }
10577
10578 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10579 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10580 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10581 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10582
10583 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10584 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10585 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10586
10587 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10588 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10589
10590 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10591 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10592
10593 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10594 ((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]);
10595
10596 return NL_SKIP;
10597}
10598#endif
10599
10600INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10601{
10602#ifdef HAL_NETLINK_IMPL
10603 Netlink nl;
10604 char if_name[10];
10605 char interface_name[16] = {0};
10606 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10607 return RETURN_ERR;
10608
10609 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10610
10611 if (*output_array_size <= 0)
10612 return RETURN_OK;
10613
10614 snprintf(if_name, sizeof(if_name), "%s", interface_name);
10615
10616 nl.id = initSock80211(&nl);
10617
10618 if(nl.id < 0) {
10619 fprintf(stderr, "Error initializing netlink \n");
10620 return 0;
10621 }
10622
10623 struct nl_msg* msg = nlmsg_alloc();
10624
10625 if(!msg) {
10626 fprintf(stderr, "Failed to allocate netlink message.\n");
10627 nlfree(&nl);
10628 return 0;
10629 }
10630
10631 genlmsg_put(msg,
10632 NL_AUTO_PORT,
10633 NL_AUTO_SEQ,
10634 nl.id,
10635 0,
10636 0,
10637 NL80211_CMD_GET_STATION,
10638 0);
10639
10640 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10641 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10642 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10643 nl_send_auto(nl.socket, msg);
10644 nl_recvmsgs(nl.socket, nl.cb);
10645 nlmsg_free(msg);
10646 nlfree(&nl);
10647 return RETURN_OK;
10648#else
10649 //TODO Implement me
10650 return RETURN_OK;
10651#endif
10652}
10653
10654INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10655{
10656 // TODO Implement me!
10657 char buf[MAX_BUF_SIZE] = {0};
10658 char config_file[MAX_BUF_SIZE] = {0};
10659
10660 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10661 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10662 *activate = (strncmp("1",buf,1) == 0);
10663
10664 return RETURN_OK;
10665}
10666
10667INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10668{
10669 char config_file[MAX_BUF_SIZE] = {0};
10670 struct params list;
10671
10672 list.name = "rrm_neighbor_report";
10673 list.value = activate?"1":"0";
10674 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10675 wifi_hostapdWrite(config_file, &list, 1);
10676
10677 return RETURN_OK;
10678}
10679
10680INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10681{
10682 char buf[32] = {0};
10683 char config_file[MAX_BUF_SIZE] = {0};
10684
10685 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10686 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10687 *activate = (strncmp("1",buf,1) == 0);
10688
10689 return RETURN_OK;
10690}
10691#undef HAL_NETLINK_IMPL
10692#ifdef HAL_NETLINK_IMPL
10693static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10694 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10695 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10696 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10697 char dev[20];
10698 int freq =0 ;
10699 static int i=0;
10700
10701 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10702
10703 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10704 };
10705
10706 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10707
10708 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10709
10710 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10711 fprintf(stderr, "survey data missing!\n");
10712 return NL_SKIP;
10713 }
10714
10715 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10716 {
10717 fprintf(stderr, "failed to parse nested attributes!\n");
10718 return NL_SKIP;
10719 }
10720
10721
10722 if(out[0].array_size == 1 )
10723 {
10724 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10725 {
10726 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10727 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10728 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10729
10730 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10731 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10732 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10733 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10734 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10735 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10736 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10737 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10738 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10739 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10740 if (sinfo[NL80211_SURVEY_INFO_TIME])
10741 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10742 return NL_STOP;
10743 }
10744 }
10745 else
10746 {
10747 if ( i <= out[0].array_size )
10748 {
10749 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10750 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10751 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10752
10753 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10754 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10755 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10756 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10757 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10758 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10759 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10760 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10761 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10762 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10763 if (sinfo[NL80211_SURVEY_INFO_TIME])
10764 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10765 }
10766 }
10767
10768 i++;
10769 return NL_SKIP;
10770}
10771#endif
10772
10773static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10774{
10775 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10776 FILE *fp;
10777
10778 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10779 {
10780 printf("Creating Frequency-Channel Map\n");
10781 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10782 }
10783 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10784 if((fp = popen(command, "r")))
10785 {
10786 fgets(output, sizeof(output), fp);
10787 *freqMHz = atoi(output);
10788 pclose(fp);
10789 }
10790
10791 return 0;
10792}
10793
10794static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10795{
10796 int freqMHz = -1;
10797 char cmd[MAX_CMD_SIZE] = {'\0'};
10798 char interface_name[16] = {0};
10799
10800 ieee80211_channel_to_frequency(channel, &freqMHz);
10801 if (freqMHz == -1) {
10802 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10803 return -1;
10804 }
10805
10806 wifi_GetInterfaceName(radioIndex, interface_name);
10807 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
10808 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10809 radioIndex, freqMHz);
10810 return -1;
10811 }
10812
10813 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10814 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10815 return -1;
10816 }
10817
10818 return 0;
10819}
10820
10821static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10822{
10823 const char *ptr = buf;
10824 char *key = NULL;
10825 char *val = NULL;
10826 char line[256] = { '\0' };
10827
10828 while (ptr = get_line_from_str_buf(ptr, line)) {
10829 if (strstr(line, "Frequency")) continue;
10830
10831 key = strtok(line, ":");
10832 val = strtok(NULL, " ");
10833 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10834
10835 if (!strcmp(key, "noise")) {
10836 sscanf(val, "%d", &stats->ch_noise);
10837 if (stats->ch_noise == 0) {
10838 // Workaround for missing noise information.
10839 // Assume -95 for 2.4G and -103 for 5G
10840 if (radioIndex == 0) stats->ch_noise = -95;
10841 if (radioIndex == 1) stats->ch_noise = -103;
10842 }
10843 }
10844 else if (!strcmp(key, "channel active time")) {
10845 sscanf(val, "%llu", &stats->ch_utilization_total);
10846 }
10847 else if (!strcmp(key, "channel busy time")) {
10848 sscanf(val, "%llu", &stats->ch_utilization_busy);
10849 }
10850 else if (!strcmp(key, "channel receive time")) {
10851 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10852 }
10853 else if (!strcmp(key, "channel transmit time")) {
10854 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10855 }
10856 };
10857
10858 return 0;
10859}
10860
10861INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10862{
10863 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10864#ifdef HAL_NETLINK_IMPL
10865 Netlink nl;
10866 wifi_channelStats_t_loc local[array_size];
10867 char if_name[32];
10868
10869 local[0].array_size = array_size;
10870
10871 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10872 return RETURN_ERR;
10873
10874 nl.id = initSock80211(&nl);
10875
10876 if (nl.id < 0) {
10877 fprintf(stderr, "Error initializing netlink \n");
10878 return -1;
10879 }
10880
10881 struct nl_msg* msg = nlmsg_alloc();
10882
10883 if (!msg) {
10884 fprintf(stderr, "Failed to allocate netlink message.\n");
10885 nlfree(&nl);
10886 return -2;
10887 }
10888
10889 genlmsg_put(msg,
10890 NL_AUTO_PORT,
10891 NL_AUTO_SEQ,
10892 nl.id,
10893 0,
10894 NLM_F_DUMP,
10895 NL80211_CMD_GET_SURVEY,
10896 0);
10897
10898 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10899 nl_send_auto(nl.socket, msg);
10900 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10901 nl_recvmsgs(nl.socket, nl.cb);
10902 nlmsg_free(msg);
10903 nlfree(&nl);
10904 //Copying the Values
10905 for(int i=0;i<array_size;i++)
10906 {
10907 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10908 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10909 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10910 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10911 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10912 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10913 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10914 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10915 }
10916#else
10917 ULONG channel = 0;
10918 int i;
10919 int number_of_channels = array_size;
10920 char buf[512];
10921 INT ret;
10922 wifi_channelStats_t tmp_stats;
10923
10924 if (number_of_channels == 0) {
10925 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10926 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10927 return RETURN_ERR;
10928 }
10929 number_of_channels = 1;
10930 input_output_channelStats_array[0].ch_number = channel;
10931 }
10932
10933 for (i = 0; i < number_of_channels; i++) {
10934
10935 input_output_channelStats_array[i].ch_noise = 0;
10936 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10937 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10938 input_output_channelStats_array[i].ch_utilization_busy = 0;
10939 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10940 input_output_channelStats_array[i].ch_utilization_total = 0;
10941
10942 memset(buf, 0, sizeof(buf));
10943 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10944 return RETURN_ERR;
10945 }
10946 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10947 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10948 return RETURN_ERR;
10949 }
10950
10951 // XXX: fake missing 'self' counter which is not available in iw survey output
10952 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10953 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10954
10955 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10956 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10957 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10958 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10959 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10960
10961 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",
10962 __func__,
10963 input_output_channelStats_array[i].ch_number,
10964 input_output_channelStats_array[i].ch_noise,
10965 input_output_channelStats_array[i].ch_utilization_total,
10966 input_output_channelStats_array[i].ch_utilization_busy,
10967 input_output_channelStats_array[i].ch_utilization_busy_rx,
10968 input_output_channelStats_array[i].ch_utilization_busy_tx,
10969 input_output_channelStats_array[i].ch_utilization_busy_self,
10970 input_output_channelStats_array[i].ch_utilization_busy_ext);
10971 }
10972#endif
10973 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10974 return RETURN_OK;
10975}
10976#define HAL_NETLINK_IMPL
10977
10978/* Hostapd events */
10979
10980#ifndef container_of
10981#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10982#define container_of(ptr, type, member) \
10983 ((type *)((char *)ptr - offset_of(type, member)))
10984#endif /* container_of */
10985
10986struct ctrl {
10987 char sockpath[128];
10988 char sockdir[128];
10989 char bss[IFNAMSIZ];
10990 char reply[4096];
10991 int ssid_index;
10992 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10993 void (*overrun)(struct ctrl *ctrl);
10994 struct wpa_ctrl *wpa;
10995 unsigned int ovfl;
10996 size_t reply_len;
10997 int initialized;
10998 ev_timer retry;
10999 ev_timer watchdog;
11000 ev_stat stat;
11001 ev_io io;
11002};
11003static wifi_newApAssociatedDevice_callback clients_connect_cb;
11004static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
11005static struct ctrl wpa_ctrl[MAX_APS];
11006static int initialized;
11007
11008static unsigned int ctrl_get_drops(struct ctrl *ctrl)
11009{
11010 char cbuf[256] = {};
11011 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
11012 struct cmsghdr *cmsg;
11013 unsigned int ovfl = ctrl->ovfl;
11014 unsigned int drop;
11015
11016 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
11017 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
11018 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
11019 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
11020
11021 drop = ovfl - ctrl->ovfl;
11022 ctrl->ovfl = ovfl;
11023
11024 return drop;
11025}
11026
11027static void ctrl_close(struct ctrl *ctrl)
11028{
11029 if (ctrl->io.cb)
11030 ev_io_stop(EV_DEFAULT_ &ctrl->io);
11031 if (ctrl->retry.cb)
11032 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11033 if (!ctrl->wpa)
11034 return;
11035
11036 wpa_ctrl_detach(ctrl->wpa);
11037 wpa_ctrl_close(ctrl->wpa);
11038 ctrl->wpa = NULL;
11039 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
11040}
11041
11042static void ctrl_process(struct ctrl *ctrl)
11043{
11044 const char *str;
11045 int drops;
11046 int level;
11047 int err;
11048
11049 /* Example events:
11050 *
11051 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
11052 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
11053 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
11054 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
11055 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
11056 */
11057 if (!(str = index(ctrl->reply, '>')))
11058 return;
11059 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
11060 return;
11061
11062 str++;
11063
11064 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
11065 if (!(str = index(ctrl->reply, ' ')))
11066 return;
11067 wifi_associated_dev_t sta;
11068 memset(&sta, 0, sizeof(sta));
11069
11070 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11071 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
11072 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
11073
11074 sta.cli_Active=true;
11075
11076 (clients_connect_cb)(ctrl->ssid_index, &sta);
11077 goto handled;
11078 }
11079
11080 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
11081 if (!(str = index(ctrl->reply, ' ')))
11082 return;
11083
11084 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
11085 goto handled;
11086 }
11087
11088 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
11089 printf("CTRL_WPA: handle TERMINATING event\n");
11090 goto retry;
11091 }
11092
11093 if (strncmp("AP-DISABLED", str, 11) == 0) {
11094 printf("CTRL_WPA: handle AP-DISABLED\n");
11095 goto retry;
11096 }
11097
11098 printf("Event not supported!!\n");
11099
11100handled:
11101
11102 if ((drops = ctrl_get_drops(ctrl))) {
11103 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
11104 if (ctrl->overrun)
11105 ctrl->overrun(ctrl);
11106 }
11107
11108 return;
11109
11110retry:
11111 printf("WPA_CTRL: closing\n");
11112 ctrl_close(ctrl);
11113 printf("WPA_CTRL: retrying from ctrl prcoess\n");
11114 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
11115}
11116
11117static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
11118{
11119 struct ctrl *ctrl = container_of(io, struct ctrl, io);
11120 int err;
11121
11122 memset(ctrl->reply, 0, sizeof(ctrl->reply));
11123 ctrl->reply_len = sizeof(ctrl->reply) - 1;
11124 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
11125 ctrl->reply[ctrl->reply_len] = 0;
11126 if (err < 0) {
11127 if (errno == EAGAIN || errno == EWOULDBLOCK)
11128 return;
11129 ctrl_close(ctrl);
11130 ev_timer_again(EV_A_ &ctrl->retry);
11131 return;
11132 }
11133
11134 ctrl_process(ctrl);
11135}
11136
11137static int ctrl_open(struct ctrl *ctrl)
11138{
11139 int fd;
11140
11141 if (ctrl->wpa)
11142 return 0;
11143
11144 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
11145 if (!ctrl->wpa)
11146 goto err;
11147
11148 if (wpa_ctrl_attach(ctrl->wpa) < 0)
11149 goto err_close;
11150
11151 fd = wpa_ctrl_get_fd(ctrl->wpa);
11152 if (fd < 0)
11153 goto err_detach;
11154
11155 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
11156 goto err_detach;
11157
11158 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
11159 ev_io_start(EV_DEFAULT_ &ctrl->io);
11160
11161 return 0;
11162
11163err_detach:
11164 wpa_ctrl_detach(ctrl->wpa);
11165err_close:
11166 wpa_ctrl_close(ctrl->wpa);
11167err:
11168 ctrl->wpa = NULL;
11169 return -1;
11170}
11171
11172static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
11173{
11174 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
11175
11176 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
11177 ctrl_open(ctrl);
11178}
11179
11180static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
11181{
11182 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
11183
11184 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
11185 if (ctrl_open(ctrl) == 0) {
11186 printf("WPA_CTRL: retry successful\n");
11187 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11188 }
11189}
11190
11191int ctrl_enable(struct ctrl *ctrl)
11192{
11193 if (ctrl->wpa)
11194 return 0;
11195
11196 if (!ctrl->stat.cb) {
11197 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
11198 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
11199 }
11200
11201 if (!ctrl->retry.cb) {
11202 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
11203 }
11204
11205 return ctrl_open(ctrl);
11206}
11207
11208static void
11209ctrl_msg_cb(char *buf, size_t len)
11210{
11211 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
11212
11213 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
11214 ctrl_process(ctrl);
11215}
11216
11217static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
11218{
11219 int err;
11220
11221 if (!ctrl->wpa)
11222 return -1;
11223 if (*reply_len < 2)
11224 return -1;
11225
11226 (*reply_len)--;
11227 ctrl->reply_len = sizeof(ctrl->reply);
11228 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
11229 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
11230 if (err < 0)
11231 return err;
11232
11233 if (ctrl->reply_len > *reply_len)
11234 ctrl->reply_len = *reply_len;
11235
11236 *reply_len = ctrl->reply_len;
11237 memcpy(reply, ctrl->reply, *reply_len);
11238 reply[*reply_len - 1] = 0;
11239 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11240 return 0;
11241}
11242
11243static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11244{
11245 const char *pong = "PONG";
11246 const char *ping = "PING";
11247 char reply[1024];
11248 size_t len = sizeof(reply);
11249 int err;
11250 ULONG s, snum;
11251 INT ret;
11252 BOOL status;
11253
11254 printf("WPA_CTRL: watchdog cb\n");
11255
11256 ret = wifi_getSSIDNumberOfEntries(&snum);
11257 if (ret != RETURN_OK) {
11258 printf("%s: failed to get SSID count", __func__);
11259 return;
11260 }
11261
11262 if (snum > MAX_APS) {
11263 printf("more ssid than supported! %lu\n", snum);
11264 return;
11265 }
11266
11267 for (s = 0; s < snum; s++) {
11268 if (wifi_getApEnable(s, &status) != RETURN_OK) {
11269 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
11270 continue;
11271 }
11272 if (status == false) continue;
11273
11274 memset(reply, 0, sizeof(reply));
11275 len = sizeof(reply);
11276 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
11277 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
11278 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11279 continue;
11280
11281 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11282 ctrl_close(&wpa_ctrl[s]);
11283 printf("WPA_CTRL: ev_timer_again %lu\n", s);
11284 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11285 }
11286}
11287
11288static int init_wpa()
11289{
11290 int ret = 0, i = 0;
11291 ULONG s, snum;
11292
11293 ret = wifi_getSSIDNumberOfEntries(&snum);
11294 if (ret != RETURN_OK) {
11295 printf("%s: failed to get SSID count", __func__);
11296 return RETURN_ERR;
11297 }
11298
11299 if (snum > MAX_APS) {
11300 printf("more ssid than supported! %lu\n", snum);
11301 return RETURN_ERR;
11302 }
11303
11304 for (s = 0; s < snum; s++) {
11305 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11306 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11307 wpa_ctrl[s].ssid_index = s;
11308 ctrl_enable(&wpa_ctrl[s]);
11309 }
11310
11311 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11312 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11313
11314 initialized = 1;
11315 printf("WPA_CTRL: initialized\n");
11316
11317 return RETURN_OK;
11318}
11319
11320void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11321{
11322 clients_connect_cb = callback_proc;
11323 if (!initialized)
11324 init_wpa();
11325}
11326
11327void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11328{
11329 clients_disconnect_cb = callback_proc;
11330 if (!initialized)
11331 init_wpa();
11332}
11333
11334INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11335{
11336 // TODO Implement me!
11337 return RETURN_ERR;
11338}
11339
11340INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11341{
11342 // TODO Implement me!
11343 return RETURN_ERR;
11344}
11345
11346INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11347{
11348 int i;
developer40ba1762023-05-13 11:03:49 +080011349 int phyId = -1;
11350 char cmd[256] = {0};
11351 char channel_numbers_buf[256] = {0};
11352 char dfs_state_buf[256] = {0};
11353 char line[256] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011354 const char *ptr;
developer40ba1762023-05-13 11:03:49 +080011355 BOOL dfs_enable = false;
developer72fb0bb2023-01-11 09:46:29 +080011356
developer40ba1762023-05-13 11:03:49 +080011357 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer72fb0bb2023-01-11 09:46:29 +080011358
developer40ba1762023-05-13 11:03:49 +080011359 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11360 phyId = radio_index_to_phy(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080011361
developer40ba1762023-05-13 11:03:49 +080011362 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\\|");
developer72fb0bb2023-01-11 09:46:29 +080011363
developer40ba1762023-05-13 11:03:49 +080011364 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11365 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11366 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011367 }
11368
developer40ba1762023-05-13 11:03:49 +080011369 ptr = channel_numbers_buf;
11370 i = 0;
11371 while (ptr = get_line_from_str_buf(ptr, line)) {
11372 if (i >= outputMapSize) {
11373 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11374 return RETURN_ERR;
11375 }
11376 sscanf(line, "%d", &outputMap[i].ch_number);
11377
11378 memset(cmd, 0, sizeof(cmd));
11379 // Below command should fetch string for DFS state (usable, available or unavailable)
11380 // Example line: "DFS state: usable (for 78930 sec)"
11381 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) {
11382 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer72fb0bb2023-01-11 09:46:29 +080011383 return RETURN_ERR;
11384 }
11385
developer40ba1762023-05-13 11:03:49 +080011386 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11387 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer72fb0bb2023-01-11 09:46:29 +080011388 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11389 return RETURN_ERR;
11390 }
11391
developer40ba1762023-05-13 11:03:49 +080011392 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer72fb0bb2023-01-11 09:46:29 +080011393
developer40ba1762023-05-13 11:03:49 +080011394 if (!strcmp(dfs_state_buf, "usable")) {
11395 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11396 } else if (!strcmp(dfs_state_buf, "available")) {
11397 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11398 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11399 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11400 } else {
11401 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer72fb0bb2023-01-11 09:46:29 +080011402 }
developer40ba1762023-05-13 11:03:49 +080011403 i++;
developer72fb0bb2023-01-11 09:46:29 +080011404 }
11405
developer40ba1762023-05-13 11:03:49 +080011406 return RETURN_OK;
11407
developer72fb0bb2023-01-11 09:46:29 +080011408 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11409 return RETURN_ERR;
11410}
11411
11412INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11413{
11414 // TODO Implement me!
11415 return RETURN_ERR;
11416}
11417
11418INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11419{
11420 return RETURN_OK;
11421}
11422
11423INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11424{
11425 // TODO Implement me!
11426 return RETURN_ERR;
11427}
11428
11429INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11430{
11431 // TODO API refrence Implementaion is present on RPI hal
11432 return RETURN_ERR;
11433}
11434
11435INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11436{
developera1255e42023-05-13 17:45:02 +080011437/*
developer72fb0bb2023-01-11 09:46:29 +080011438 char interface_name[16] = {0};
11439 char cmd[128]={'\0'};
11440 char buf[128]={'\0'};
11441 char *support;
11442 int maximum_tx = 0, current_tx = 0;
developera1255e42023-05-13 17:45:02 +080011443*/ ULONG pwr_percentage = 0;
developer72fb0bb2023-01-11 09:46:29 +080011444
11445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11446 if(txpwr_pcntg == NULL)
11447 return RETURN_ERR;
11448
developera1255e42023-05-13 17:45:02 +080011449 wifi_getRadioTransmitPower(apIndex, &pwr_percentage);
11450 *txpwr_pcntg = pwr_percentage;
11451/* if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +080011452 return RETURN_ERR;
11453
11454 // Get the maximum tx power of the device
11455 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
11456 _syscmd(cmd, buf, sizeof(buf));
11457 maximum_tx = strtol(buf, NULL, 10);
11458
11459 // Get the current tx power
11460 memset(cmd, 0, sizeof(cmd));
11461 memset(buf, 0, sizeof(buf));
11462 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
11463 _syscmd(cmd, buf, sizeof(buf));
11464 current_tx = strtol(buf, NULL, 10);
11465
11466 // Get the power supported list and find the current power percentage in supported list
11467 memset(buf, 0, sizeof(buf));
11468 wifi_getRadioTransmitPowerSupported(apIndex, buf);
11469 support = strtok(buf, ",");
11470 while(true)
11471 {
11472 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
11473 *txpwr_pcntg = 100;
11474 wifi_dbg_printf("current power is not in supported list\n");
11475 return RETURN_OK;
11476 }
11477 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
11478 if (tmp == current_tx) {
11479 *txpwr_pcntg = strtol(support, NULL, 10);
11480 break;
11481 }
11482 support = strtok(NULL, ",");
11483 }
developera1255e42023-05-13 17:45:02 +080011484*/
developer72fb0bb2023-01-11 09:46:29 +080011485 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11486 return RETURN_OK;
11487}
11488
11489INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11490{
11491 // TODO precac feature.
11492 struct params params = {0};
11493 char config_file[128] = {0};
11494
11495 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11496
11497 params.name = "enable_background_radar";
11498 params.value = enable?"1":"0";
11499 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11500 wifi_hostapdWrite(config_file, &params, 1);
11501 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11502
11503 /* TODO precac feature */
11504
11505 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11506 return RETURN_OK;
11507}
11508
11509INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11510{
11511 char config_file[128] = {0};
11512 char buf[64] = {0};
11513
11514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11515 if (NULL == enable || NULL == precac)
11516 return RETURN_ERR;
11517
11518 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11519 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
11520 if (strncmp(enable, "1", 1) == 0)
11521 *enable = true;
11522 else
11523 *enable = false;
11524
11525 /* TODO precac feature */
11526
11527 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11528 return RETURN_OK;
11529}
11530
11531INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11532{
11533 *supported = TRUE;
11534 return RETURN_OK;
11535}
11536
11537INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11538{
developera1255e42023-05-13 17:45:02 +080011539 UCHAR dat_file[64] = {0};
11540 wifi_band band = band_invalid;
11541 char cmd[128] = {0};
11542 char buf[256] = {0};
11543 char ofdmabuf[32] = {'\0'};
11544 char mimobuf[32] = {'\0'};
11545 char new_ofdmabuf[32] = {'\0'};
11546 char new_mimobuf[32] = {'\0'};
11547 struct params params[2];
11548 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
11549 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
11550 UCHAR bss_cnt = 0;
11551 UCHAR val_cnt = 0;
11552 char *token = NULL;
developer72fb0bb2023-01-11 09:46:29 +080011553
developera1255e42023-05-13 17:45:02 +080011554 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11555 if ((mu_type < WIFI_DL_MU_TYPE_NONE)
11556 || (mu_type > WIFI_DL_MU_TYPE_OFDMA_MIMO)) {
11557 printf("%s:mu_type input Error", __func__);
11558 return RETURN_ERR;
11559 }
11560 band = wifi_index_to_band(radio_index);
11561 if (band == band_invalid) {
11562 printf("%s:Band Error\n", __func__);
11563 return RETURN_ERR;
11564 }
11565 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
11566 /*get current value in dat file*/
11567 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
11568 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
11569 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
11570 get_bssnum_byindex(radio_index, &bss_cnt);
11571 val_cnt = 2*bss_cnt - 1;
11572 WIFI_ENTRY_EXIT_DEBUG("bss number: %d\n", bss_cnt);
11573 if ((val_cnt >= sizeof(new_ofdmabuf))
11574 || (val_cnt >= sizeof(new_mimobuf))) {
11575 printf("%s:bss cnt Error", __func__, bss_cnt);
11576 return RETURN_ERR;
11577 }
11578 /*translate set value*/
11579 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11580 strncpy(new_ofdmabuf, str_zero, val_cnt);
11581 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080011582 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
developera1255e42023-05-13 17:45:02 +080011583 strncpy(new_ofdmabuf, str_one, val_cnt);
11584 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080011585 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
developera1255e42023-05-13 17:45:02 +080011586 strncpy(new_ofdmabuf, str_zero, val_cnt);
11587 strncpy(new_mimobuf, str_one, val_cnt);
11588 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO) {
11589 strncpy(new_ofdmabuf, str_one, val_cnt);
11590 strncpy(new_mimobuf, str_one, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080011591 }
developera1255e42023-05-13 17:45:02 +080011592 WIFI_ENTRY_EXIT_DEBUG("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
11593 /*same value, not operation*/
11594 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
11595 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
11596 printf("%s:Reduntant value\n", __func__);
11597 return RETURN_OK;
11598 }
11599 /*modify dat file to new file*/
11600 params[0].name="MuOfdmaDlEnable";
11601 params[0].value=new_ofdmabuf;
11602 params[1].name="MuMimoDlEnable";
11603 params[1].value=new_mimobuf;
11604 wifi_datfileWrite(dat_file, params, 2);
11605 /*hostapd control restarp ap to take effect on these new value*/
11606 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080011607 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11608 return RETURN_OK;
11609}
11610
11611INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11612{
11613 struct params params={0};
11614 char config_file[64] = {0};
11615 char buf[64] = {0};
11616 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080011617 UCHAR dat_file[64] = {0};
11618 wifi_band band = band_invalid;
11619 char ofdmabuf[32] = {'\0'};
11620 char mimobuf[32] = {'\0'};
11621 char *token = NULL;
11622 UCHAR ofdma = 0;
11623 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080011624
11625 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11626
11627 if (mu_type == NULL)
11628 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080011629 band = wifi_index_to_band(radio_index);
11630 if (band == band_invalid) {
11631 printf("%s:Band Error\n", __func__);
11632 return RETURN_ERR;
11633 }
11634 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
11635 /*get current value in dat file*/
11636 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
11637 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080011638
developera1255e42023-05-13 17:45:02 +080011639 token = strtok(ofdmabuf, ";");
11640 ofdma = strtol(token, NULL, 10);
11641 token = strtok(mimobuf, ";");
11642 mimo = strtol(token, NULL, 10);
11643 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d,mimo=%d\n", __func__, ofdma, mimo);
11644 if ((ofdma == 1) && (mimo == 1))
11645 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11646 else if ((ofdma == 0) && (mimo == 1))
11647 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11648 else if ((ofdma == 1) && (mimo == 0))
11649 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11650 else
11651 *mu_type = WIFI_DL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080011652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11653 return RETURN_OK;
11654}
11655
11656INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11657{
11658 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
developera1255e42023-05-13 17:45:02 +080011659 UCHAR dat_file[64] = {0};
11660 wifi_band band = band_invalid;
11661 char cmd[128] = {0};
11662 char buf[256] = {0};
11663 char ofdmabuf[32] = {'\0'};
11664 char mimobuf[32] = {'\0'};
11665 char new_ofdmabuf[32] = {'\0'};
11666 char new_mimobuf[32] = {'\0'};
11667 struct params params[2];
11668 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
11669 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
11670 UCHAR bss_cnt = 0;
11671 UCHAR val_cnt = 0;
developer72fb0bb2023-01-11 09:46:29 +080011672
developera1255e42023-05-13 17:45:02 +080011673 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11674 band = wifi_index_to_band(radio_index);
11675 if (band == band_invalid) {
11676 printf("%s:Band Error\n", __func__);
11677 return RETURN_ERR;
11678 }
11679 if ((mu_type < WIFI_UL_MU_TYPE_NONE)
11680 || (mu_type > WIFI_UL_MU_TYPE_OFDMA)) {
11681 printf("%s:mu_type input Error\n", __func__);
11682 return RETURN_ERR;
11683 }
11684 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
11685 /*get current value in dat file*/
11686 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
11687 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
11688 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
11689 get_bssnum_byindex(radio_index, &bss_cnt);
11690 val_cnt = 2*bss_cnt - 1;
11691 printf("bssNumber:%d,ValCnt:%d\n", bss_cnt, val_cnt);
11692 if ((val_cnt >= sizeof(new_ofdmabuf))
11693 || (val_cnt >= sizeof(new_mimobuf))) {
11694 printf("%s:bss cnt Error\n", __func__, val_cnt);
11695 return RETURN_ERR;
11696 }
11697 /*translate set value*/
11698 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11699 strncpy(new_ofdmabuf, str_zero, val_cnt);
11700 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080011701 }
developera1255e42023-05-13 17:45:02 +080011702 if (mu_type == WIFI_UL_MU_TYPE_OFDMA) {
11703 strncpy(new_ofdmabuf, str_one, val_cnt);
11704 strncpy(new_mimobuf, str_zero, val_cnt);
11705 }
11706 printf("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
11707 /*same value, not operation*/
11708 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
11709 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
11710 printf("%s:Reduntant value\n", __func__);
11711 return RETURN_OK;
11712 }
11713 /*modify dat file to new file*/
11714 params[0].name="MuOfdmaUlEnable";
11715 params[0].value=new_ofdmabuf;
11716 params[1].name="MuMimoUlEnable";
11717 params[1].value=new_mimobuf;
11718 wifi_datfileWrite(dat_file, params, 2);
11719 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080011720 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11721 return RETURN_OK;
11722}
11723
11724INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11725{
11726 struct params params={0};
11727 char config_file[64] = {0};
11728 char buf[64] = {0};
11729 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080011730 UCHAR dat_file[64] = {0};
11731 wifi_band band = band_invalid;
11732 char ofdmabuf[32] = {'\0'};
11733 char mimobuf[32] = {'\0'};
11734 char *token = NULL;
11735 UCHAR ofdma = 0;
11736 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080011737
11738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11739
11740 if (mu_type == NULL)
11741 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080011742 band = wifi_index_to_band(radio_index);
11743 if (band == band_invalid) {
11744 printf("%s:Band Error", __func__);
11745 return RETURN_ERR;
11746 }
11747 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
11748 /*get current value in dat file*/
11749 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
11750 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080011751
developera1255e42023-05-13 17:45:02 +080011752 token = strtok(ofdmabuf, ";");
11753 ofdma = strtol(token, NULL, 10);
11754 token = strtok(mimobuf, ";");
11755 mimo = strtol(token, NULL, 10);
11756 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d, mimo=%d\n", __func__, ofdma, mimo);
11757 if ((ofdma == 1) && (mimo == 0))
11758 *mu_type = WIFI_UL_MU_TYPE_OFDMA;
11759 else
11760 *mu_type = WIFI_UL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080011761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11762 return RETURN_OK;
11763}
11764
11765
11766INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11767{
11768 char cmd[128] = {0};
11769 char buf[256] = {0};
11770 char config_file[64] = {0};
11771 char GI[8] = {0};
11772 int mode_map = 0;
11773 FILE *f = NULL;
11774 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080011775 char dat_file[64] = {'\0'};
11776 struct params params[3];
developer72fb0bb2023-01-11 09:46:29 +080011777
11778 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11779
11780 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
11781 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11782 return RETURN_ERR;
11783 }
developera1255e42023-05-13 17:45:02 +080011784 /*sanity check*/
11785 if (((guard_interval == wifi_guard_interval_1600)
11786 || (guard_interval == wifi_guard_interval_3200))
11787 && (mode_map & (WIFI_MODE_BE | WIFI_MODE_AX) == 0)) {
11788 wifi_dbg_printf("%s: N/AC Mode not support 1600/3200ns GI\n", __func__);
11789 return RETURN_ERR;
11790 }
developer72fb0bb2023-01-11 09:46:29 +080011791 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
11792 band = wifi_index_to_band(radio_index);
11793
11794 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11795 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
11796 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
11797 _syscmd(cmd, buf, sizeof(buf));
11798 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11799 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11800 if (strstr(buf, "[SHORT-GI-") == NULL) {
11801 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
11802 _syscmd(cmd, buf, sizeof(buf));
11803 }
11804 if (band == band_5) {
11805 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11806 if (strstr(buf, "[SHORT-GI-") == NULL) {
11807 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
11808 _syscmd(cmd, buf, sizeof(buf));
11809 }
11810 }
11811 }
developera1255e42023-05-13 17:45:02 +080011812 /*wifi_reloadAp(radio_index);
11813 caller "wifi_setRadioOperatingParameters" have done this step.
11814 */
11815 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
11816 if (guard_interval == wifi_guard_interval_400) {
11817 params[0].name = "HT_GI";
11818 params[0].value = "1";
11819 params[1].name = "VHT_SGI";
11820 params[1].value = "1";
11821 wifi_datfileWrite(dat_file, params, 2);
developer72fb0bb2023-01-11 09:46:29 +080011822 strcpy(GI, "0.4");
developera1255e42023-05-13 17:45:02 +080011823 } else {
11824 params[0].name = "HT_GI";
11825 params[0].value = "0";
11826 params[1].name = "VHT_SGI";
11827 params[1].value = "0";
11828 /*should enable FIXED_HE_GI_SUPPORT in driver*/
11829 params[2].name = "FgiFltf";
11830 if (guard_interval == wifi_guard_interval_800) {
11831 params[2].value = "800";
11832 strcpy(GI, "0.8");
11833 } else if (guard_interval == wifi_guard_interval_1600) {
11834 params[2].value = "1600";
11835 strcpy(GI, "1.6");
11836 } else if (guard_interval == wifi_guard_interval_3200) {
11837 params[2].value = "3200";
11838 strcpy(GI, "3.2");
11839 } else if (guard_interval == wifi_guard_interval_auto) {
11840 params[2].value = "0";
11841 strcpy(GI, "auto");
11842 }
11843 wifi_datfileWrite(dat_file, params, 3);
11844 }
developer72fb0bb2023-01-11 09:46:29 +080011845 // Record GI for get GI function
11846 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11847 f = fopen(buf, "w");
11848 if (f == NULL)
11849 return RETURN_ERR;
11850 fprintf(f, "%s", GI);
11851 fclose(f);
11852 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11853 return RETURN_OK;
11854}
11855
11856INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11857{
11858 char buf[32] = {0};
11859 char cmd[64] = {0};
11860
11861 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11862
11863 if (guard_interval == NULL)
11864 return RETURN_ERR;
11865
developera1255e42023-05-13 17:45:02 +080011866 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer72fb0bb2023-01-11 09:46:29 +080011867 _syscmd(cmd, buf, sizeof(buf));
11868
11869 if (strncmp(buf, "0.4", 3) == 0)
11870 *guard_interval = wifi_guard_interval_400;
11871 else if (strncmp(buf, "0.8", 3) == 0)
11872 *guard_interval = wifi_guard_interval_800;
11873 else if (strncmp(buf, "1.6", 3) == 0)
11874 *guard_interval = wifi_guard_interval_1600;
11875 else if (strncmp(buf, "3.2", 3) == 0)
11876 *guard_interval = wifi_guard_interval_3200;
11877 else
11878 *guard_interval = wifi_guard_interval_auto;
11879
11880 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11881 return RETURN_OK;
11882}
11883
11884INT wifi_setBSSColor(INT radio_index, UCHAR color)
11885{
11886 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11887 struct params params = {0};
11888 char config_file[128] = {0};
11889 char bss_color[4] ={0};
11890
developera1255e42023-05-13 17:45:02 +080011891 if (color < 1 || color > 63) {
11892 wifi_dbg_printf("color value is err:%d.\n", color);
11893 return RETURN_ERR;
11894 }
developer72fb0bb2023-01-11 09:46:29 +080011895 params.name = "he_bss_color";
11896 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11897 params.value = bss_color;
11898 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11899 wifi_hostapdWrite(config_file, &params, 1);
developera1255e42023-05-13 17:45:02 +080011900 //wifi_hostapdProcessUpdate(radio_index, &params, 1);
11901 wifi_reloadAp(radio_index);
developer69b61b02023-03-07 17:17:44 +080011902
developer72fb0bb2023-01-11 09:46:29 +080011903 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11904 return RETURN_OK;
11905}
11906
11907INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11908{
11909 char config_file[128] = {0};
11910 char buf[64] = {0};
11911 char temp_output[128] = {'\0'};
11912
11913 wifi_dbg_printf("\nFunc=%s\n", __func__);
11914 if (NULL == color)
11915 return RETURN_ERR;
11916
11917 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11918 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11919
11920 if(strlen(buf) > 0) {
11921 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11922 } else {
11923 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11924 }
11925
11926 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11927 wifi_dbg_printf("\noutput_string=%s\n", color);
11928
11929 return RETURN_OK;
11930}
11931
11932/* multi-psk support */
11933INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11934{
11935 char cmd[256];
11936 char interface_name[16] = {0};
11937
11938 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11939 return RETURN_ERR;
11940
11941 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11942 interface_name,
11943 mac[0],
11944 mac[1],
11945 mac[2],
11946 mac[3],
11947 mac[4],
11948 mac[5]
11949 );
11950 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11951 _syscmd(cmd, key->wifi_keyId, 64);
11952
11953
11954 return RETURN_OK;
11955}
11956
11957INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11958{
11959 char interface_name[16] = {0};
11960 FILE *fd = NULL;
11961 char fname[100];
11962 char cmd[128] = {0};
11963 char out[64] = {0};
11964 wifi_key_multi_psk_t * key = NULL;
11965 if(keysNumber < 0)
11966 return RETURN_ERR;
11967
11968 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11969 fd = fopen(fname, "w");
11970 if (!fd) {
11971 return RETURN_ERR;
11972 }
11973 key= (wifi_key_multi_psk_t *) keys;
11974 for(int i=0; i<keysNumber; ++i, key++) {
11975 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11976 }
11977 fclose(fd);
11978
11979 //reload file
11980 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11981 return RETURN_ERR;
11982 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
11983 _syscmd(cmd, out, 64);
11984 return RETURN_OK;
11985}
11986
11987INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11988{
11989 FILE *fd = NULL;
11990 char fname[100];
11991 char * line = NULL;
11992 char * pos = NULL;
11993 size_t len = 0;
11994 ssize_t read = 0;
11995 INT ret = RETURN_OK;
11996 wifi_key_multi_psk_t *keys_it = NULL;
11997
11998 if (keysNumber < 1) {
11999 return RETURN_ERR;
12000 }
12001
12002 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
12003 fd = fopen(fname, "r");
12004 if (!fd) {
12005 return RETURN_ERR;
12006 }
12007
12008 if (keys == NULL) {
12009 ret = RETURN_ERR;
12010 goto close;
12011 }
12012
12013 keys_it = keys;
12014 while ((read = getline(&line, &len, fd)) != -1) {
12015 //Strip trailing new line if present
12016 if (read > 0 && line[read-1] == '\n') {
12017 line[read-1] = '\0';
12018 }
12019
12020 if(strcmp(line,"keyid=")) {
12021 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
12022 if (!(pos = index(line, ' '))) {
12023 ret = RETURN_ERR;
12024 goto close;
12025 }
12026 pos++;
12027 //Here should be 00:00:00:00:00:00
12028 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
12029 printf("Not supported MAC: %s\n", pos);
12030 }
12031 if (!(pos = index(pos, ' '))) {
12032 ret = RETURN_ERR;
12033 goto close;
12034 }
12035 pos++;
12036
12037 //The rest is PSK
12038 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
12039 keys_it++;
12040
12041 if(--keysNumber <= 0)
12042 break;
12043 }
12044 }
12045
12046close:
12047 free(line);
12048 fclose(fd);
12049 return ret;
12050}
12051/* end of multi-psk support */
12052
12053INT wifi_setNeighborReports(UINT apIndex,
12054 UINT numNeighborReports,
12055 wifi_NeighborReport_t *neighborReports)
12056{
12057 char cmd[256] = { 0 };
12058 char hex_bssid[13] = { 0 };
12059 char bssid[18] = { 0 };
12060 char nr[256] = { 0 };
12061 char ssid[256];
12062 char hex_ssid[256];
12063 char interface_name[16] = {0};
12064 INT ret;
12065
12066 /*rmeove all neighbors*/
12067 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
12068 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12069 return RETURN_ERR;
12070 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);
12071 system(cmd);
12072
12073 for(unsigned int i = 0; i < numNeighborReports; i++)
12074 {
12075 memset(ssid, 0, sizeof(ssid));
12076 ret = wifi_getSSIDName(apIndex, ssid);
12077 if (ret != RETURN_OK)
12078 return RETURN_ERR;
12079
12080 memset(hex_ssid, 0, sizeof(hex_ssid));
12081 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
12082 sprintf(hex_ssid + k,"%02x", ssid[j]);
12083
12084 snprintf(hex_bssid, sizeof(hex_bssid),
12085 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
12086 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
12087 snprintf(bssid, sizeof(bssid),
12088 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
12089 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
12090
12091 snprintf(nr, sizeof(nr),
12092 "%s" // bssid
12093 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
12094 "%02hhx" // operclass
12095 "%02hhx" // channel
12096 "%02hhx", // phy_mode
12097 hex_bssid,
12098 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
12099 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
12100 neighborReports[i].opClass,
12101 neighborReports[i].channel,
12102 neighborReports[i].phyTable);
12103
12104 snprintf(cmd, sizeof(cmd),
12105 "hostapd_cli set_neighbor "
12106 "%s " // bssid
12107 "ssid=%s " // ssid
12108 "nr=%s " // nr
12109 "-i %s",
12110 bssid,hex_ssid,nr, interface_name);
12111
12112 if (WEXITSTATUS(system(cmd)) != 0)
12113 {
12114 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
12115 }
12116 }
12117
12118 return RETURN_OK;
12119}
12120
12121INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
12122{
12123 return RETURN_OK;
12124}
12125
12126#ifdef _WIFI_HAL_TEST_
12127int main(int argc,char **argv)
12128{
12129 int index;
12130 INT ret=0;
12131 char buf[1024]="";
12132
12133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12134 if(argc<3)
12135 {
12136 if(argc==2)
12137 {
12138 if(!strcmp(argv[1], "init"))
12139 return wifi_init();
12140 if(!strcmp(argv[1], "reset"))
12141 return wifi_reset();
12142 if(!strcmp(argv[1], "wifi_getHalVersion"))
12143 {
12144 char buffer[64];
12145 if(wifi_getHalVersion(buffer)==RETURN_OK)
12146 printf("Version: %s\n", buffer);
12147 else
12148 printf("Error in wifi_getHalVersion\n");
12149 return RETURN_OK;
12150 }
12151 }
12152 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
12153 exit(-1);
12154 }
12155
12156 index = atoi(argv[2]);
12157 if(strstr(argv[1], "wifi_getApName")!=NULL)
12158 {
12159 wifi_getApName(index,buf);
12160 printf("Ap name is %s \n",buf);
12161 return 0;
12162 }
12163 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
12164 {
12165 BOOL b = FALSE;
12166 BOOL *output_bool = &b;
12167 wifi_getRadioAutoChannelEnable(index,output_bool);
12168 printf("Channel enabled = %d \n",b);
12169 return 0;
12170 }
12171 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
12172 {
12173 wifi_getApWpaEncryptionMode(index,buf);
12174 printf("encryption enabled = %s\n",buf);
12175 return 0;
12176 }
12177 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
12178 {
12179 BOOL b = FALSE;
12180 BOOL *output_bool = &b;
12181 wifi_getApSsidAdvertisementEnable(index,output_bool);
12182 printf("advertisment enabled = %d\n",b);
12183 return 0;
12184 }
12185 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
12186 {
12187 if(argc <= 3 )
12188 {
12189 printf("Insufficient arguments \n");
12190 exit(-1);
12191 }
12192
12193 char sta[20] = {'\0'};
12194 ULLONG handle= 0;
12195 strcpy(sta,argv[3]);
12196 mac_address_t st;
12197 mac_addr_aton(st,sta);
12198
12199 wifi_associated_dev_tid_stats_t tid_stats;
12200 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
12201 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
12202 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);
12203 }
12204
12205 if(strstr(argv[1], "getApEnable")!=NULL) {
12206 BOOL enable;
12207 ret=wifi_getApEnable(index, &enable);
12208 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12209 }
12210 else if(strstr(argv[1], "setApEnable")!=NULL) {
12211 BOOL enable = atoi(argv[3]);
12212 ret=wifi_setApEnable(index, enable);
12213 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12214 }
12215 else if(strstr(argv[1], "getApStatus")!=NULL) {
developer69b61b02023-03-07 17:17:44 +080012216 char status[64];
developer72fb0bb2023-01-11 09:46:29 +080012217 ret=wifi_getApStatus(index, status);
12218 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
12219 }
12220 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
12221 {
12222 wifi_getSSIDNameStatus(index,buf);
12223 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
12224 return 0;
12225 }
12226 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
12227 wifi_ssidTrafficStats2_t stats={0};
12228 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
12229 printf("%s %d: returns %d\n", argv[1], index, ret);
12230 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
12231 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
12232 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
12233 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
12234 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
12235 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
12236 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
12237 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
12238 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
12239 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
12240 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
12241 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
12242 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
12243 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
12244 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
12245 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
12246 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
12247 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
12248 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
12249 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
12250 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
12251 }
12252 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
12253 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
12254 UINT array_size=0;
12255 UINT i=0;
12256 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
12257 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080012258 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080012259 printf(" neighbor %d:\n", i);
12260 printf(" ap_SSID =%s\n", pt->ap_SSID);
12261 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
12262 printf(" ap_Mode =%s\n", pt->ap_Mode);
12263 printf(" ap_Channel =%d\n", pt->ap_Channel);
12264 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
12265 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12266 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
12267 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
12268 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
12269 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
12270 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12271 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
12272 printf(" ap_Noise =%d\n", pt->ap_Noise);
12273 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
12274 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
12275 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
developer69b61b02023-03-07 17:17:44 +080012276 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
developer72fb0bb2023-01-11 09:46:29 +080012277 }
12278 if(neighbor_ap_array)
12279 free(neighbor_ap_array); //make sure to free the list
12280 }
12281 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
12282 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
12283 UINT array_size=0;
12284 UINT i=0;
12285 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
12286 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080012287 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080012288 printf(" associated_dev %d:\n", i);
12289 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
12290 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
12291 printf(" cli_SNR =%d\n", pt->cli_SNR);
12292 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
12293 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
12294 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
12295 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
12296 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
12297 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
12298 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
12299 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
12300 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
12301 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
12302 }
12303 if(associated_dev_array)
12304 free(associated_dev_array); //make sure to free the list
12305 }
12306
12307 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
12308 {
12309#define MAX_ARRAY_SIZE 64
12310 int i, array_size;
12311 char *p, *ch_str;
12312 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
12313
12314 if(argc != 5)
12315 {
12316 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
12317 exit(-1);
12318 }
12319 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
12320
12321 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
12322 {
12323 strtok_r(ch_str, ",", &p);
12324 input_output_channelStats_array[i].ch_number = atoi(ch_str);
12325 }
12326 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
12327 if(!array_size)
12328 array_size=1;//Need to print current channel statistics
12329 for(i=0; i<array_size; i++)
12330 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12331 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12332 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12333 input_output_channelStats_array[i].ch_number,\
12334 input_output_channelStats_array[i].ch_noise,\
12335 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12336 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12337 input_output_channelStats_array[i].ch_utilization_busy,\
12338 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12339 input_output_channelStats_array[i].ch_utilization_total);
12340 }
12341
12342 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12343 {
12344 if(argc <= 3 )
12345 {
12346 printf("Insufficient arguments \n");
12347 exit(-1);
12348 }
12349 char mac_addr[20] = {'\0'};
12350 wifi_device_t output_struct;
12351 int dev_index = atoi(argv[3]);
12352
12353 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12354 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12355 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);
12356 }
12357
12358 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12359 {
12360 if (argc <= 3)
12361 {
12362 printf("Insufficient arguments\n");
12363 exit(-1);
12364 }
12365 char args[256];
12366 wifi_NeighborReport_t *neighborReports;
12367
12368 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12369 if (!neighborReports)
12370 {
12371 printf("Failed to allocate memory");
12372 exit(-1);
12373 }
12374
12375 for (int i = 3; i < argc; ++i)
12376 {
12377 char *val;
12378 int j = 0;
12379 memset(args, 0, sizeof(args));
12380 strncpy(args, argv[i], sizeof(args));
12381 val = strtok(args, ";");
12382 while (val != NULL)
12383 {
12384 if (j == 0)
12385 {
12386 mac_addr_aton(neighborReports[i - 3].bssid, val);
12387 } else if (j == 1)
12388 {
12389 neighborReports[i - 3].info = strtol(val, NULL, 16);
12390 } else if (j == 2)
12391 {
12392 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12393 } else if (j == 3)
12394 {
12395 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12396 } else if (j == 4)
12397 {
12398 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12399 } else {
12400 printf("Insufficient arguments]n\n");
12401 exit(-1);
12402 }
12403 val = strtok(NULL, ";");
12404 j++;
12405 }
12406 }
12407
12408 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12409 if (ret != RETURN_OK)
12410 {
12411 printf("wifi_setNeighborReports ret = %d", ret);
12412 exit(-1);
12413 }
12414 }
12415 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12416 {
12417 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12418 printf("%s.\n", buf);
12419 else
12420 printf("Error returned\n");
12421 }
12422 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12423 {
12424 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12425 printf("%s.\n", buf);
12426 else
12427 printf("Error returned\n");
12428 }
12429 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12430 {
12431 if (argc <= 2)
12432 {
12433 printf("Insufficient arguments\n");
12434 exit(-1);
12435 }
12436 char buf[64]= {'\0'};
12437 wifi_getRadioOperatingChannelBandwidth(index,buf);
12438 printf("Current bandwidth is %s \n",buf);
12439 return 0;
12440 }
12441 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12442 {
12443 if (argc <= 5)
12444 {
12445 printf("Insufficient arguments\n");
12446 exit(-1);
12447 }
12448 UINT channel = atoi(argv[3]);
12449 UINT width = atoi(argv[4]);
12450 UINT beacon = atoi(argv[5]);
12451 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12452 printf("Result = %d", ret);
12453 }
12454
12455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12456 return 0;
12457}
12458
12459#endif
12460
12461#ifdef WIFI_HAL_VERSION_3
12462
12463INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12464{
12465 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12466 if (bitMap & WIFI_BITRATE_1MBPS)
12467 strcat(BasicRate, "1,");
12468 if (bitMap & WIFI_BITRATE_2MBPS)
12469 strcat(BasicRate, "2,");
12470 if (bitMap & WIFI_BITRATE_5_5MBPS)
12471 strcat(BasicRate, "5.5,");
12472 if (bitMap & WIFI_BITRATE_6MBPS)
12473 strcat(BasicRate, "6,");
12474 if (bitMap & WIFI_BITRATE_9MBPS)
12475 strcat(BasicRate, "9,");
12476 if (bitMap & WIFI_BITRATE_11MBPS)
12477 strcat(BasicRate, "11,");
12478 if (bitMap & WIFI_BITRATE_12MBPS)
12479 strcat(BasicRate, "12,");
12480 if (bitMap & WIFI_BITRATE_18MBPS)
12481 strcat(BasicRate, "18,");
12482 if (bitMap & WIFI_BITRATE_24MBPS)
12483 strcat(BasicRate, "24,");
12484 if (bitMap & WIFI_BITRATE_36MBPS)
12485 strcat(BasicRate, "36,");
12486 if (bitMap & WIFI_BITRATE_48MBPS)
12487 strcat(BasicRate, "48,");
12488 if (bitMap & WIFI_BITRATE_54MBPS)
12489 strcat(BasicRate, "54,");
12490 if (strlen(BasicRate) != 0) // remove last comma
12491 BasicRate[strlen(BasicRate) - 1] = '\0';
12492 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12493 return RETURN_OK;
12494}
12495
12496INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12497{
12498 UINT BitMap = 0;
12499 char *rate;
12500
12501 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12502 rate = strtok(BasicRatesList, ",");
12503 while(rate != NULL)
12504 {
12505 if (strcmp(rate, "1") == 0)
12506 BitMap |= WIFI_BITRATE_1MBPS;
12507 else if (strcmp(rate, "2") == 0)
12508 BitMap |= WIFI_BITRATE_2MBPS;
12509 else if (strcmp(rate, "5.5") == 0)
12510 BitMap |= WIFI_BITRATE_5_5MBPS;
12511 else if (strcmp(rate, "6") == 0)
12512 BitMap |= WIFI_BITRATE_6MBPS;
12513 else if (strcmp(rate, "9") == 0)
12514 BitMap |= WIFI_BITRATE_9MBPS;
12515 else if (strcmp(rate, "11") == 0)
12516 BitMap |= WIFI_BITRATE_11MBPS;
12517 else if (strcmp(rate, "12") == 0)
12518 BitMap |= WIFI_BITRATE_12MBPS;
12519 else if (strcmp(rate, "18") == 0)
12520 BitMap |= WIFI_BITRATE_18MBPS;
12521 else if (strcmp(rate, "24") == 0)
12522 BitMap |= WIFI_BITRATE_24MBPS;
12523 else if (strcmp(rate, "36") == 0)
12524 BitMap |= WIFI_BITRATE_36MBPS;
12525 else if (strcmp(rate, "48") == 0)
12526 BitMap |= WIFI_BITRATE_48MBPS;
12527 else if (strcmp(rate, "54") == 0)
12528 BitMap |= WIFI_BITRATE_54MBPS;
12529 rate = strtok(NULL, ",");
12530 }
12531 *basicRateBitMap = BitMap;
12532 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12533 return RETURN_OK;
12534}
12535
12536// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
12537INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12538{
12539 char buf[128] = {0};
12540 char cmd[128] = {0};
12541 char config_file[64] = {0};
12542 int bandwidth;
12543 int set_mode = 0;
12544 wifi_radio_operationParam_t current_param;
12545
12546 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12547
12548 multiple_set = TRUE;
12549 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12550 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12551 return RETURN_ERR;
12552 }
12553 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12554 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12555 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12556 return RETURN_ERR;
12557 }
12558 }
12559
12560 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12561 bandwidth = 20;
12562 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12563 bandwidth = 40;
12564 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12565 bandwidth = 80;
12566 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12567 bandwidth = 160;
12568 if (operationParam->autoChannelEnabled){
12569 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12570 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12571 return RETURN_ERR;
12572 }
developer69b61b02023-03-07 17:17:44 +080012573 }else{
developer72fb0bb2023-01-11 09:46:29 +080012574 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12575 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12576 return RETURN_ERR;
12577 }
12578 }
12579
12580 if (current_param.variant != operationParam->variant) {
12581 // Two different definition bit map, so need to check every bit.
12582 if (operationParam->variant & WIFI_80211_VARIANT_A)
12583 set_mode |= WIFI_MODE_A;
12584 if (operationParam->variant & WIFI_80211_VARIANT_B)
12585 set_mode |= WIFI_MODE_B;
12586 if (operationParam->variant & WIFI_80211_VARIANT_G)
12587 set_mode |= WIFI_MODE_G;
12588 if (operationParam->variant & WIFI_80211_VARIANT_N)
12589 set_mode |= WIFI_MODE_N;
12590 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12591 set_mode |= WIFI_MODE_AC;
12592 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12593 set_mode |= WIFI_MODE_AX;
12594 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12595 memset(buf, 0, sizeof(buf));
12596 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12597 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12598 return RETURN_ERR;
12599 }
12600 }
12601 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12602 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12603 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12604 return RETURN_ERR;
12605 }
12606 }
12607 if (current_param.beaconInterval != operationParam->beaconInterval) {
12608 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12609 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12610 return RETURN_ERR;
12611 }
12612 }
12613 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12614 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12615 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12616 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12617 return RETURN_ERR;
12618 }
12619 }
12620 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12621 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12622 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12623 return RETURN_ERR;
12624 }
12625 }
12626 if (current_param.guardInterval != operationParam->guardInterval) {
12627 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12628 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12629 return RETURN_ERR;
12630 }
12631 }
12632 if (current_param.transmitPower != operationParam->transmitPower) {
12633 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12634 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12635 return RETURN_ERR;
12636 }
12637 }
12638 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12639 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12640 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12641 return RETURN_ERR;
12642 }
12643 }
12644 if (current_param.obssCoex != operationParam->obssCoex) {
12645 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12646 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12647 return RETURN_ERR;
12648 }
12649 }
12650 if (current_param.stbcEnable != operationParam->stbcEnable) {
12651 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12652 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12653 return RETURN_ERR;
12654 }
12655 }
12656 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12657 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12658 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12659 return RETURN_ERR;
12660 }
12661 }
12662
12663 // if enable is true, then restart the radio
12664 wifi_setRadioEnable(index, FALSE);
12665 if (operationParam->enable == TRUE)
12666 wifi_setRadioEnable(index, TRUE);
12667 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12668
12669 return RETURN_OK;
12670}
12671
12672INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12673{
12674 char band[64] = {0};
12675 char buf[256] = {0};
12676 char config_file[64] = {0};
12677 char cmd[128] = {0};
12678 int ret = RETURN_ERR;
12679 int mode = 0;
12680 ULONG channel = 0;
12681 BOOL enabled = FALSE;
12682
12683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12684 printf("Entering %s index = %d\n", __func__, (int)index);
12685
12686 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12687 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12688 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
12689 {
12690 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
12691 return RETURN_ERR;
12692 }
12693 operationParam->enable = enabled;
12694
12695 memset(band, 0, sizeof(band));
12696 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
12697 {
12698 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
12699 return RETURN_ERR;
12700 }
12701
12702 if (!strcmp(band, "2.4GHz"))
12703 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
12704 else if (!strcmp(band, "5GHz"))
12705 operationParam->band = WIFI_FREQUENCY_5_BAND;
12706 else if (!strcmp(band, "6GHz"))
12707 operationParam->band = WIFI_FREQUENCY_6_BAND;
12708 else
12709 {
12710 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
12711 band);
12712 }
12713
12714 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12715 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12716 operationParam->channel = 0;
12717 operationParam->autoChannelEnabled = TRUE;
12718 } else {
12719 operationParam->channel = strtol(buf, NULL, 10);
12720 operationParam->autoChannelEnabled = FALSE;
12721 }
12722
12723 memset(buf, 0, sizeof(buf));
12724 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12725 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12726 return RETURN_ERR;
12727 }
12728 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12729 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12730 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
12731 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
12732 else
12733 {
12734 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12735 return false;
12736 }
12737
12738 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12739 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12740 return RETURN_ERR;
12741 }
12742 // Two different definition bit map, so need to check every bit.
12743 if (mode & WIFI_MODE_A)
12744 operationParam->variant |= WIFI_80211_VARIANT_A;
12745 if (mode & WIFI_MODE_B)
12746 operationParam->variant |= WIFI_80211_VARIANT_B;
12747 if (mode & WIFI_MODE_G)
12748 operationParam->variant |= WIFI_80211_VARIANT_G;
12749 if (mode & WIFI_MODE_N)
12750 operationParam->variant |= WIFI_80211_VARIANT_N;
12751 if (mode & WIFI_MODE_AC)
12752 operationParam->variant |= WIFI_80211_VARIANT_AC;
12753 if (mode & WIFI_MODE_AX)
12754 operationParam->variant |= WIFI_80211_VARIANT_AX;
12755 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12756 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12757 return RETURN_ERR;
12758 }
12759 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12760 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12761 return RETURN_ERR;
12762 }
12763 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12764 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12765 return RETURN_ERR;
12766 }
12767
12768 memset(buf, 0, sizeof(buf));
12769 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12770 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12771 return RETURN_ERR;
12772 }
12773 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12774
12775 memset(buf, 0, sizeof(buf));
12776 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12777 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12778 return RETURN_ERR;
12779 }
12780 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12781
12782 memset(buf, 0, sizeof(buf));
12783 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12784 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12785
12786 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12787 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12788 return RETURN_ERR;
12789 }
developera1255e42023-05-13 17:45:02 +080012790 if (wifi_getRadioPercentageTransmitPower(index, (ULONG *)&operationParam->transmitPower) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080012791 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12792 return RETURN_ERR;
12793 }
12794
12795 memset(buf, 0, sizeof(buf));
12796 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12797 if (strcmp(buf, "-1") == 0) {
12798 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12799 operationParam->ctsProtection = FALSE;
12800 } else {
12801 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12802 operationParam->ctsProtection = TRUE;
12803 }
12804
12805 memset(buf, 0, sizeof(buf));
12806 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12807 if (strcmp(buf, "0") == 0)
12808 operationParam->obssCoex = FALSE;
12809 else
12810 operationParam->obssCoex = TRUE;
12811
12812 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12813 _syscmd(cmd, buf, sizeof(buf));
12814 if (strlen(buf) != 0)
12815 operationParam->stbcEnable = TRUE;
12816 else
12817 operationParam->stbcEnable = FALSE;
12818
12819 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12820 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12821 return RETURN_ERR;
12822 }
12823
12824 // Below value is hardcoded
12825
12826 operationParam->numSecondaryChannels = 0;
12827 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12828 operationParam->channelSecondary[i] = 0;
12829 }
12830 operationParam->csa_beacon_count = 15;
12831 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
12832
12833 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12834 return RETURN_OK;
12835}
12836
12837static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12838{
12839 int max_radio_num = 0;
12840
12841 wifi_getMaxRadioNumber(&max_radio_num);
12842 if (radioIndex >= max_radio_num) {
12843 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12844 return RETURN_ERR;
12845 }
12846
12847 return (arrayIndex * max_radio_num) + radioIndex;
12848}
12849
developer96b38512023-02-22 11:17:45 +080012850static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex)
12851{
12852 int max_radio_num = 0;
12853
12854 if ((vapIndex < 0) || (vapIndex > MAX_NUM_VAP_PER_RADIO*MAX_NUM_RADIOS))
12855 return -1;
12856
12857 wifi_getMaxRadioNumber(&max_radio_num);
12858
12859 (*radioIndex) = vapIndex % max_radio_num;
12860 (*arrayIndex) = vapIndex / max_radio_num;
12861
12862 return 0;
12863}
12864
12865
developer72fb0bb2023-01-11 09:46:29 +080012866wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12867 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12868 return WIFI_BITRATE_1MBPS;
12869 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12870 return WIFI_BITRATE_2MBPS;
12871 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12872 return WIFI_BITRATE_5_5MBPS;
12873 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12874 return WIFI_BITRATE_6MBPS;
12875 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12876 return WIFI_BITRATE_9MBPS;
12877 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12878 return WIFI_BITRATE_11MBPS;
12879 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12880 return WIFI_BITRATE_12MBPS;
12881 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12882 return WIFI_BITRATE_18MBPS;
12883 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12884 return WIFI_BITRATE_24MBPS;
12885 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12886 return WIFI_BITRATE_36MBPS;
12887 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12888 return WIFI_BITRATE_48MBPS;
12889 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12890 return WIFI_BITRATE_54MBPS;
12891 return WIFI_BITRATE_DEFAULT;
12892}
12893
12894INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12895{
12896 if (beacon == WIFI_BITRATE_1MBPS)
12897 strcpy(beacon_str, "1Mbps");
12898 else if (beacon == WIFI_BITRATE_2MBPS)
12899 strcpy(beacon_str, "2Mbps");
12900 else if (beacon == WIFI_BITRATE_5_5MBPS)
12901 strcpy(beacon_str, "5.5Mbps");
12902 else if (beacon == WIFI_BITRATE_6MBPS)
12903 strcpy(beacon_str, "6Mbps");
12904 else if (beacon == WIFI_BITRATE_9MBPS)
12905 strcpy(beacon_str, "9Mbps");
12906 else if (beacon == WIFI_BITRATE_11MBPS)
12907 strcpy(beacon_str, "11Mbps");
12908 else if (beacon == WIFI_BITRATE_12MBPS)
12909 strcpy(beacon_str, "12Mbps");
12910 else if (beacon == WIFI_BITRATE_18MBPS)
12911 strcpy(beacon_str, "18Mbps");
12912 else if (beacon == WIFI_BITRATE_24MBPS)
12913 strcpy(beacon_str, "24Mbps");
12914 else if (beacon == WIFI_BITRATE_36MBPS)
12915 strcpy(beacon_str, "36Mbps");
12916 else if (beacon == WIFI_BITRATE_48MBPS)
12917 strcpy(beacon_str, "48Mbps");
12918 else if (beacon == WIFI_BITRATE_54MBPS)
12919 strcpy(beacon_str, "54Mbps");
12920 return RETURN_OK;
12921}
12922
12923INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12924{
12925 INT mode = 0;
12926 INT ret = -1;
12927 INT output = 0;
12928 int i = 0;
12929 int vap_index = 0;
12930 BOOL enabled = FALSE;
12931 char buf[256] = {0};
12932 wifi_vap_security_t security = {0};
12933 map->num_vaps = 5; // Hardcoded
12934
12935 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12936 printf("Entering %s index = %d\n", __func__, (int)index);
12937
12938 for (i = 0; i < 5; i++)
12939 {
12940 map->vap_array[i].radio_index = index;
12941
12942 vap_index = array_index_to_vap_index(index, i);
12943 if (vap_index < 0)
12944 return RETURN_ERR;
12945
12946 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
12947
12948 map->vap_array[i].vap_index = vap_index;
12949
12950 memset(buf, 0, sizeof(buf));
12951 ret = wifi_getApName(vap_index, buf);
12952 if (ret != RETURN_OK) {
12953 printf("%s: wifi_getApName return error\n", __func__);
12954 return RETURN_ERR;
12955 }
12956 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12957
12958 memset(buf, 0, sizeof(buf));
12959 ret = wifi_getSSIDName(vap_index, buf);
12960 if (ret != RETURN_OK) {
12961 printf("%s: wifi_getSSIDName return error\n", __func__);
12962 return RETURN_ERR;
12963 }
12964 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
12965
12966 ret = wifi_getSSIDEnable(vap_index, &enabled);
12967 if (ret != RETURN_OK) {
12968 printf("%s: wifi_getSSIDEnable return error\n", __func__);
12969 return RETURN_ERR;
12970 }
12971 map->vap_array[i].u.bss_info.enabled = enabled;
12972
12973 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12974 if (ret != RETURN_OK) {
12975 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12976 return RETURN_ERR;
12977 }
12978 map->vap_array[i].u.bss_info.showSsid = enabled;
developer69b61b02023-03-07 17:17:44 +080012979
developer72fb0bb2023-01-11 09:46:29 +080012980 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12981 if (ret != RETURN_OK) {
12982 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12983 return RETURN_ERR;
12984 }
12985 map->vap_array[i].u.bss_info.isolation = enabled;
12986
12987 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12988 if (ret != RETURN_OK) {
12989 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12990 return RETURN_ERR;
12991 }
12992 map->vap_array[i].u.bss_info.bssMaxSta = output;
12993
12994 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12995 if (ret != RETURN_OK) {
12996 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12997 return RETURN_ERR;
12998 }
12999 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
13000
13001 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
13002 if (ret != RETURN_OK) {
13003 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
13004 return RETURN_ERR;
13005 }
13006 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
13007
13008 ret = wifi_getApSecurity(vap_index, &security);
13009 if (ret != RETURN_OK) {
13010 printf("%s: wifi_getApSecurity return error\n", __func__);
13011 return RETURN_ERR;
13012 }
13013 map->vap_array[i].u.bss_info.security = security;
13014
13015 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
13016 if (ret != RETURN_OK) {
13017 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
13018 return RETURN_ERR;
13019 }
developer69b61b02023-03-07 17:17:44 +080013020 if (mode == 0)
developer72fb0bb2023-01-11 09:46:29 +080013021 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
developer69b61b02023-03-07 17:17:44 +080013022 else
developer72fb0bb2023-01-11 09:46:29 +080013023 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
developer69b61b02023-03-07 17:17:44 +080013024 if (mode == 1)
developer72fb0bb2023-01-11 09:46:29 +080013025 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
developer69b61b02023-03-07 17:17:44 +080013026 else if (mode == 2)
developer72fb0bb2023-01-11 09:46:29 +080013027 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
13028
13029 ret = wifi_getApWmmEnable(vap_index, &enabled);
13030 if (ret != RETURN_OK) {
13031 printf("%s: wifi_getApWmmEnable return error\n", __func__);
13032 return RETURN_ERR;
13033 }
13034 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
13035
13036 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
13037 if (ret != RETURN_OK) {
13038 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
13039 return RETURN_ERR;
13040 }
13041 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
13042
13043 memset(buf, 0, sizeof(buf));
13044 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
13045 if (ret != RETURN_OK) {
13046 printf("%s: wifi_getApBeaconRate return error\n", __func__);
13047 return RETURN_ERR;
13048 }
13049 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
13050
13051 memset(buf, 0, sizeof(buf));
13052 ret = wifi_getBaseBSSID(vap_index, buf);
13053 if (ret != RETURN_OK) {
13054 printf("%s: wifi_getBaseBSSID return error\n", __func__);
13055 return RETURN_ERR;
13056 }
13057 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
13058 &map->vap_array[i].u.bss_info.bssid[0],
13059 &map->vap_array[i].u.bss_info.bssid[1],
13060 &map->vap_array[i].u.bss_info.bssid[2],
13061 &map->vap_array[i].u.bss_info.bssid[3],
13062 &map->vap_array[i].u.bss_info.bssid[4],
13063 &map->vap_array[i].u.bss_info.bssid[5]);
13064 // 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]);
13065
13066 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
13067 if (ret != RETURN_OK) {
13068 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
13069 return RETURN_ERR;
13070 }
13071 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
13072
13073 // TODO: wps, noack
13074 }
13075 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13076 return RETURN_OK;
13077}
13078
13079void checkVapStatus(int apIndex, bool *enable)
13080{
13081 char if_name[16] = {0};
13082 char cmd[128] = {0};
13083 char buf[128] = {0};
13084
13085 *enable = FALSE;
13086 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
13087 return;
13088
13089 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
13090 _syscmd(cmd, buf, sizeof(buf));
13091 if (strlen(buf) > 0)
13092 *enable = TRUE;
13093 return;
13094}
13095
13096static int prepareInterface(UINT apIndex, char *new_interface)
13097{
13098 char cur_interface[16] = {0};
13099 char config_file[128] = {0};
developer8a3bbbf2023-03-15 17:47:23 +080013100 char cmd[MAX_CMD_SIZE] = {0};
13101 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013102 int max_radio_num = 0;
13103 int radioIndex = -1;
13104 int phyIndex = -1;
developer8a3bbbf2023-03-15 17:47:23 +080013105 struct params params;
developer72fb0bb2023-01-11 09:46:29 +080013106
13107 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
13108 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
13109
13110 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
developer8a3bbbf2023-03-15 17:47:23 +080013111 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +080013112 radioIndex = apIndex % max_radio_num;
13113 phyIndex = radio_index_to_phy(radioIndex);
13114 // disable and del old interface, then add new interface
13115 wifi_setApEnable(apIndex, FALSE);
developer8a3bbbf2023-03-15 17:47:23 +080013116
13117 params.name = "interface";
13118 params.value = new_interface;
13119 wifi_hostapdWrite(config_file, &params, 1);
13120
13121 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyIndex, config_file);
13122 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080013123 }
developer8a3bbbf2023-03-15 17:47:23 +080013124
developer72fb0bb2023-01-11 09:46:29 +080013125 // update the vap status file
13126 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
13127 _syscmd(cmd, buf, sizeof(buf));
13128 return RETURN_OK;
13129}
13130
13131INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13132{
13133 char interface_name[16] = {0};
13134 unsigned int i;
13135 wifi_vap_info_t *vap_info = NULL;
13136 int acl_mode;
13137 int ret = 0;
13138 char *sec_str = NULL;
13139 char buf[256] = {0};
13140 char cmd[128] = {0};
13141 char config_file[64] = {0};
13142 char bssid[32] = {0};
13143 char psk_file[64] = {0};
13144 bool enable = FALSE;
13145
13146 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13147 printf("Entering %s index = %d\n", __func__, (int)index);
13148 for (i = 0; i < map->num_vaps; i++)
13149 {
13150 multiple_set = TRUE;
13151 vap_info = &map->vap_array[i];
13152
13153 // Check vap status file to enable multiple ap if the system boot.
13154 checkVapStatus(vap_info->vap_index, &enable);
13155 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
13156 continue;
13157
13158 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
13159
13160 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
13161 enable = FALSE;
13162
13163 // multi-ap first up need to copy current radio config
13164 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
13165 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
13166 _syscmd(cmd, buf, sizeof(buf));
13167 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
13168 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
13169 } else {
13170 // Check whether the interface name is valid or this ap change it.
13171 int apIndex = -1;
13172 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
13173 if (apIndex != -1 && apIndex != vap_info->vap_index)
13174 continue;
13175 prepareInterface(vap_info->vap_index, vap_info->vap_name);
13176 }
13177
13178 struct params params[3];
13179 params[0].name = "interface";
13180 params[0].value = vap_info->vap_name;
13181 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
13182 params[1].name = "bssid";
13183 params[1].value = bssid;
13184 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
13185 params[2].name = "wpa_psk_file";
13186 params[2].value = psk_file;
13187
13188 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
13189 wifi_hostapdWrite(config_file, params, 3);
13190
13191 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
13192 _syscmd(cmd, buf, sizeof(buf));
13193
13194 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
13195 if (ret != RETURN_OK) {
13196 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
13197 return RETURN_ERR;
13198 }
13199
13200 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
13201 if (ret != RETURN_OK) {
13202 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
13203 return RETURN_ERR;
13204 }
13205
13206 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
13207 if (ret != RETURN_OK) {
13208 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
13209 return RETURN_ERR;
13210 }
13211
13212 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
13213 if (ret != RETURN_OK) {
13214 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
13215 return RETURN_ERR;
13216 }
13217
13218 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
13219 if (ret != RETURN_OK) {
13220 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
13221 return RETURN_ERR;
13222 }
13223
13224 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
13225 if (ret != RETURN_OK) {
13226 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
13227 return RETURN_ERR;
13228 }
13229
13230 if (vap_info->u.bss_info.mac_filter_enable == false){
13231 acl_mode = 0;
13232 }else {
13233 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
13234 acl_mode = 2;
13235 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13236 _syscmd(cmd, buf, sizeof(buf));
13237 }else{
13238 acl_mode = 1;
13239 }
13240 }
13241
13242 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13243 if (ret != RETURN_OK) {
13244 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13245 return RETURN_ERR;
13246 }
13247
13248 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13249 if (ret != RETURN_OK) {
13250 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13251 return RETURN_ERR;
13252 }
13253
developered997d32023-04-18 22:45:39 +080013254 /*TBD: we need refine beacon rate setting flow*/
13255 //memset(buf, 0, sizeof(buf));
13256 //beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
developer72fb0bb2023-01-11 09:46:29 +080013257 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
developered997d32023-04-18 22:45:39 +080013258 //ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13259 //if (ret != RETURN_OK) {
13260 // fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13261 // return RETURN_ERR;
13262 //}
developer72fb0bb2023-01-11 09:46:29 +080013263
13264 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13265 if (ret != RETURN_OK) {
13266 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
13267 return RETURN_ERR;
13268 }
13269
developer72fb0bb2023-01-11 09:46:29 +080013270 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13271 if (ret != RETURN_OK) {
13272 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13273 return RETURN_ERR;
13274 }
13275
developer23e71282023-01-18 10:25:19 +080013276 wifi_setApEnable(vap_info->vap_index, FALSE);
13277 wifi_setApEnable(vap_info->vap_index, TRUE);
13278 multiple_set = FALSE;
13279
13280 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080013281 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13282 if (ret != RETURN_OK) {
13283 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13284 return RETURN_ERR;
13285 }
13286
13287 // TODO mgmtPowerControl, interworking, wps
13288 }
13289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13290 return RETURN_OK;
13291}
13292
13293int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13294{
13295 char *token, *next;
13296 const char s[2] = ",";
13297 int count =0;
13298
13299 /* get the first token */
13300 token = strtok_r(pchannels, s, &next);
13301
13302 /* walk through other tokens */
13303 while( token != NULL && count < MAX_CHANNELS) {
13304 chlistptr->channels_list[count++] = atoi(token);
13305 token = strtok_r(NULL, s, &next);
13306 }
13307
13308 return count;
13309}
13310
13311static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13312{
13313 INT status;
13314 wifi_channels_list_t *chlistp;
13315 CHAR output_string[64];
13316 CHAR pchannels[128];
13317 CHAR interface_name[16] = {0};
13318 wifi_band band;
13319
13320 if(rcap == NULL)
13321 {
13322 return RETURN_ERR;
13323 }
13324
13325 rcap->numSupportedFreqBand = 1;
13326 band = wifi_index_to_band(radioIndex);
13327
13328 if (band == band_2_4)
13329 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13330 else if (band == band_5)
13331 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13332 else if (band == band_6)
13333 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
13334
13335 chlistp = &(rcap->channel_list[0]);
13336 memset(pchannels, 0, sizeof(pchannels));
13337
13338 /* possible number of radio channels */
13339 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13340 {
13341 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13342 }
13343 /* Number of channels and list*/
13344 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13345
13346 /* autoChannelSupported */
13347 /* always ON with wifi_getRadioAutoChannelSupported */
13348 rcap->autoChannelSupported = TRUE;
13349
13350 /* DCSSupported */
13351 /* always ON with wifi_getRadioDCSSupported */
13352 rcap->DCSSupported = TRUE;
13353
13354 /* zeroDFSSupported - TBD */
13355 rcap->zeroDFSSupported = FALSE;
13356
13357 /* Supported Country List*/
13358 memset(output_string, 0, sizeof(output_string));
13359 status = wifi_getRadioCountryCode(radioIndex, output_string);
13360 if( status != 0 ) {
13361 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13362 return RETURN_ERR;
13363 } else {
13364 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13365 }
13366 if(!strcmp(output_string,"US")){
13367 rcap->countrySupported[0] = wifi_countrycode_US;
13368 rcap->countrySupported[1] = wifi_countrycode_CA;
13369 } else if (!strcmp(output_string,"CA")) {
13370 rcap->countrySupported[0] = wifi_countrycode_CA;
13371 rcap->countrySupported[1] = wifi_countrycode_US;
13372 } else {
13373 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13374 }
13375
13376 rcap->numcountrySupported = 2;
13377
13378 /* csi */
13379 rcap->csi.maxDevices = 8;
13380 rcap->csi.soudingFrameSupported = TRUE;
13381
13382 wifi_GetInterfaceName(radioIndex, interface_name);
13383 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
13384
13385 /* channelWidth - all supported bandwidths */
13386 int i=0;
13387 rcap->channelWidth[i] = 0;
13388 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13389 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13390 WIFI_CHANNELBANDWIDTH_40MHZ);
13391
13392 }
13393 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
13394 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13395 WIFI_CHANNELBANDWIDTH_40MHZ |
13396 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
13397 }
13398
13399
13400 /* mode - all supported variants */
13401 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13402 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
13403 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
13404 }
13405 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
13406 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
13407 }
13408 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13409 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
13410 }
13411 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13412 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13413
13414 /* supportedBitRate - all supported bitrates */
13415 rcap->supportedBitRate[i] = 0;
13416 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13417 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13418 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13419 }
13420 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
13421 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13422 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13423 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13424 }
13425
13426
13427 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13428 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13429 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13430 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13431 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13432 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13433 rcap->cipherSupported = 0;
13434 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13435 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13436
13437 return RETURN_OK;
13438}
13439
13440INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13441{
13442 INT status = 0, radioIndex = 0;
13443 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
13444 int iter = 0;
13445 unsigned int j = 0;
13446 int max_num_radios;
13447 wifi_interface_name_idex_map_t *iface_info = NULL;
13448
13449 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13450
13451 memset(cap, 0, sizeof(wifi_hal_capability_t));
13452
13453 /* version */
13454 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13455 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13456
13457 /* number of radios platform property */
13458 wifi_getMaxRadioNumber(&max_num_radios);
13459 cap->wifi_prop.numRadios = max_num_radios;
13460
13461 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13462 {
13463 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13464 if (status != 0) {
13465 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13466 return RETURN_ERR;
13467 }
13468
13469 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13470 {
13471 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
13472 {
13473 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13474 return RETURN_ERR;
13475 }
13476 iface_info = &cap->wifi_prop.interface_map[iter];
13477 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13478 iface_info->rdk_radio_index = radioIndex;
13479 memset(output, 0, sizeof(output));
13480 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13481 {
13482 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13483 }
13484 // TODO: bridge name
13485 // TODO: vlan id
13486 // TODO: primary
13487 iface_info->index = array_index_to_vap_index(radioIndex, j);
13488 memset(output, 0, sizeof(output));
13489 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
13490 {
13491 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13492 }
13493 iter++;
13494 }
13495 }
13496
13497 cap->BandSteeringSupported = FALSE;
13498 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13499 return RETURN_OK;
13500}
13501
13502INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13503{
13504 struct params h_config={0};
13505 char config_file[64] = {0};
13506
13507 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13508
13509 h_config.name = "okc";
13510 h_config.value = okc_enable?"1":"0";
13511
13512 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13513 wifi_hostapdWrite(config_file, &h_config, 1);
13514 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13515
13516 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13517 return RETURN_OK;
13518}
13519
13520INT wifi_setSAEMFP(int ap_index, BOOL enable)
13521{
13522 struct params h_config={0};
13523 char config_file[64] = {0};
13524 char buf[128] = {0};
13525
13526 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13527
13528 h_config.name = "sae_require_mfp";
13529 h_config.value = enable?"1":"0";
13530
13531 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13532 wifi_hostapdWrite(config_file, &h_config, 1);
13533 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13534
13535 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13536 return RETURN_OK;
13537}
13538
13539INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13540{
13541 struct params h_config={0};
13542 char config_file[64] = {0};
13543 char buf[128] = {0};
13544
13545 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13546
13547 h_config.name = "sae_pwe";
13548 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13549 h_config.value = buf;
13550
13551 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13552 wifi_hostapdWrite(config_file, &h_config, 1);
13553 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13554
13555 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13556 return RETURN_OK;
13557}
13558
13559INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13560{
13561 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13562 struct params h_config={0};
13563 char config_file[64] = {0};
13564
13565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13566
13567 h_config.name = "wpa_disable_eapol_key_retries";
13568 h_config.value = disable_EAPOL_retries?"1":"0";
13569
13570 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13571 wifi_hostapdWrite(config_file, &h_config, 1);
13572 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13573
13574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13575 return RETURN_OK;
13576}
13577
13578INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13579{
13580 char buf[128] = {0};
13581 char config_file[128] = {0};
13582 char password[64] = {0};
13583 char mfp[32] = {0};
13584 char wpa_mode[32] = {0};
13585 BOOL okc_enable = FALSE;
13586 BOOL sae_MFP = FALSE;
13587 BOOL disable_EAPOL_retries = TRUE;
13588 int sae_pwe = 0;
13589 struct params params = {0};
13590 wifi_band band = band_invalid;
13591
13592 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13593
13594 multiple_set = TRUE;
13595 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13596 if (security->mode == wifi_security_mode_none) {
13597 strcpy(wpa_mode, "None");
13598 } else if (security->mode == wifi_security_mode_wpa_personal)
13599 strcpy(wpa_mode, "WPA-Personal");
13600 else if (security->mode == wifi_security_mode_wpa2_personal)
13601 strcpy(wpa_mode, "WPA2-Personal");
13602 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13603 strcpy(wpa_mode, "WPA-WPA2-Personal");
13604 else if (security->mode == wifi_security_mode_wpa_enterprise)
13605 strcpy(wpa_mode, "WPA-Enterprise");
13606 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13607 strcpy(wpa_mode, "WPA2-Enterprise");
13608 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13609 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
13610 else if (security->mode == wifi_security_mode_wpa3_personal) {
13611 strcpy(wpa_mode, "WPA3-Personal");
13612 okc_enable = TRUE;
13613 sae_MFP = TRUE;
13614 sae_pwe = 2;
13615 disable_EAPOL_retries = FALSE;
13616 } else if (security->mode == wifi_security_mode_wpa3_transition) {
13617 strcpy(wpa_mode, "WPA3-Personal-Transition");
13618 okc_enable = TRUE;
13619 sae_MFP = TRUE;
13620 sae_pwe = 2;
13621 disable_EAPOL_retries = FALSE;
13622 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
13623 strcpy(wpa_mode, "WPA3-Enterprise");
13624 sae_MFP = TRUE;
13625 sae_pwe = 2;
13626 disable_EAPOL_retries = FALSE;
developerd01e3e82023-04-26 19:10:38 +080013627 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer3086e2f2023-01-17 09:40:01 +080013628 strcpy(wpa_mode, "OWE");
13629 sae_MFP = TRUE;
13630 sae_pwe = 2;
13631 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080013632 }
13633
13634 band = wifi_index_to_band(ap_index);
13635 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13636 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13637 return RETURN_ERR;
13638 }
13639
13640 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
13641 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
13642 wifi_setSAEMFP(ap_index, sae_MFP);
13643 wifi_setSAEpwe(ap_index, sae_pwe);
13644 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
13645
developerd01e3e82023-04-26 19:10:38 +080013646 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developer72fb0bb2023-01-11 09:46:29 +080013647 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
13648 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
13649 password[63] = '\0';
13650 wifi_setApSecurityKeyPassphrase(ap_index, password);
13651 }
13652 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13653 params.name = "sae_password";
13654 params.value = security->u.key.key;
13655 wifi_hostapdWrite(config_file, &params, 1);
13656 }
13657 }
13658
13659 if (security->mode != wifi_security_mode_none) {
13660 memset(&params, 0, sizeof(params));
13661 params.name = "wpa_pairwise";
13662 if (security->encr == wifi_encryption_tkip)
13663 params.value = "TKIP";
13664 else if (security->encr == wifi_encryption_aes)
13665 params.value = "CCMP";
13666 else if (security->encr == wifi_encryption_aes_tkip)
13667 params.value = "TKIP CCMP";
13668 wifi_hostapdWrite(config_file, &params, 1);
13669 }
13670
13671 if (security->mfp == wifi_mfp_cfg_disabled)
13672 strcpy(mfp, "Disabled");
13673 else if (security->mfp == wifi_mfp_cfg_optional)
13674 strcpy(mfp, "Optional");
13675 else if (security->mfp == wifi_mfp_cfg_required)
13676 strcpy(mfp, "Required");
13677 wifi_setApSecurityMFPConfig(ap_index, mfp);
13678
13679 memset(&params, 0, sizeof(params));
13680 params.name = "transition_disable";
13681 if (security->wpa3_transition_disable == TRUE)
13682 params.value = "0x01";
13683 else
13684 params.value = "0x00";
13685 wifi_hostapdWrite(config_file, &params, 1);
13686
13687 memset(&params, 0, sizeof(params));
13688 params.name = "wpa_group_rekey";
13689 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13690 params.value = buf;
13691 wifi_hostapdWrite(config_file, &params, 1);
13692
13693 memset(&params, 0, sizeof(params));
13694 params.name = "wpa_strict_rekey";
13695 params.value = security->strict_rekey?"1":"0";
13696 wifi_hostapdWrite(config_file, &params, 1);
13697
13698 memset(&params, 0, sizeof(params));
13699 params.name = "wpa_pairwise_update_count";
13700 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13701 params.value = buf;
13702 wifi_hostapdWrite(config_file, &params, 1);
13703
13704 memset(&params, 0, sizeof(params));
13705 params.name = "disable_pmksa_caching";
13706 params.value = security->disable_pmksa_caching?"1":"0";
13707 wifi_hostapdWrite(config_file, &params, 1);
13708
developer23e71282023-01-18 10:25:19 +080013709 if (multiple_set == FALSE) {
13710 wifi_setApEnable(ap_index, FALSE);
13711 wifi_setApEnable(ap_index, TRUE);
13712 }
developer72fb0bb2023-01-11 09:46:29 +080013713
13714 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13715
13716 return RETURN_OK;
13717}
13718
13719INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13720{
13721 char buf[256] = {0};
13722 char config_file[128] = {0};
13723 int disable = 0;
13724 // struct params params = {0};
13725
13726 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13727 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13728 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13729 security->mode = wifi_security_mode_none;
13730 if (strlen(buf) != 0) {
13731 if (!strcmp(buf, "WPA-Personal"))
13732 security->mode = wifi_security_mode_wpa_personal;
13733 else if (!strcmp(buf, "WPA2-Personal"))
13734 security->mode = wifi_security_mode_wpa2_personal;
13735 else if (!strcmp(buf, "WPA-WPA2-Personal"))
13736 security->mode = wifi_security_mode_wpa_wpa2_personal;
13737 else if (!strcmp(buf, "WPA-Enterprise"))
13738 security->mode = wifi_security_mode_wpa_enterprise;
13739 else if (!strcmp(buf, "WPA2-Enterprise"))
13740 security->mode = wifi_security_mode_wpa2_enterprise;
13741 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
13742 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
13743 else if (!strcmp(buf, "WPA3-Personal"))
13744 security->mode = wifi_security_mode_wpa3_personal;
13745 else if (!strcmp(buf, "WPA3-Personal-Transition"))
13746 security->mode = wifi_security_mode_wpa3_transition;
13747 else if (!strcmp(buf, "WPA3-Enterprise"))
13748 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080013749 else if (!strcmp(buf, "OWE"))
developerd01e3e82023-04-26 19:10:38 +080013750 security->mode = wifi_security_mode_enhanced_open;
developer72fb0bb2023-01-11 09:46:29 +080013751 }
13752
13753 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13754 if (security->mode == wifi_security_mode_none)
13755 security->encr = wifi_encryption_none;
13756 else {
13757 if (strcmp(buf, "TKIP") == 0)
13758 security->encr = wifi_encryption_tkip;
13759 else if (strcmp(buf, "CCMP") == 0)
13760 security->encr = wifi_encryption_aes;
13761 else
13762 security->encr = wifi_encryption_aes_tkip;
13763 }
13764
13765 if (security->mode != wifi_encryption_none) {
13766 memset(buf, 0, sizeof(buf));
13767 // wpa3 can use one or both configs as password, so we check sae_password first.
13768 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
13769 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
13770 security->u.key.type = wifi_security_key_type_sae;
13771 } else {
13772 security->u.key.type = wifi_security_key_type_psk;
13773 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13774 }
13775 strncpy(security->u.key.key, buf, sizeof(buf));
13776 security->u.key.key[255] = '\0';
13777 }
13778
13779 memset(buf, 0, sizeof(buf));
13780 wifi_getApSecurityMFPConfig(ap_index, buf);
13781 if (strcmp(buf, "Disabled") == 0)
13782 security->mfp = wifi_mfp_cfg_disabled;
13783 else if (strcmp(buf, "Optional") == 0)
13784 security->mfp = wifi_mfp_cfg_optional;
13785 else if (strcmp(buf, "Required") == 0)
13786 security->mfp = wifi_mfp_cfg_required;
13787
13788 memset(buf, 0, sizeof(buf));
13789 security->wpa3_transition_disable = FALSE;
13790 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13791 disable = strtol(buf, NULL, 16);
13792 if (disable != 0)
13793 security->wpa3_transition_disable = TRUE;
13794
13795 memset(buf, 0, sizeof(buf));
13796 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13797 if (strlen(buf) == 0)
13798 security->rekey_interval = 86400;
13799 else
13800 security->rekey_interval = strtol(buf, NULL, 10);
13801
13802 memset(buf, 0, sizeof(buf));
13803 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13804 if (strlen(buf) == 0)
13805 security->strict_rekey = 1;
13806 else
13807 security->strict_rekey = strtol(buf, NULL, 10);
13808
13809 memset(buf, 0, sizeof(buf));
13810 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13811 if (strlen(buf) == 0)
13812 security->eapol_key_retries = 4;
13813 else
13814 security->eapol_key_retries = strtol(buf, NULL, 10);
13815
13816 memset(buf, 0, sizeof(buf));
13817 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13818 if (strlen(buf) == 0)
13819 security->disable_pmksa_caching = FALSE;
13820 else
13821 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13822
13823 /* TODO
13824 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13825 */
13826 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13827 security->eap_identity_req_timeout = 0;
13828 security->eap_identity_req_retries = 0;
13829 security->eap_req_timeout = 0;
13830 security->eap_req_retries = 0;
13831 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13832 return RETURN_OK;
13833}
13834
13835#endif /* WIFI_HAL_VERSION_3 */
13836
13837#ifdef WIFI_HAL_VERSION_3_PHASE2
13838INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13839{
13840 char interface_name[16] = {0};
13841 char cmd[128] = {0};
13842 char buf[128] = {0};
13843 char *mac_addr = NULL;
13844 BOOL status = FALSE;
13845 size_t len = 0;
13846
13847 if(ap_index > MAX_APS)
13848 return RETURN_ERR;
13849
13850 *output_numDevices = 0;
13851 wifi_getApEnable(ap_index, &status);
13852 if (status == FALSE)
13853 return RETURN_OK;
13854
13855 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13856 return RETURN_ERR;
13857 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
13858 _syscmd(cmd, buf, sizeof(buf));
13859
13860 mac_addr = strtok(buf, "\n");
13861 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13862 *output_numDevices = i + 1;
13863 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13864 addr_ptr = output_deviceMacAddressArray[i];
13865 mac_addr_aton(addr_ptr, mac_addr);
13866 mac_addr = strtok(NULL, "\n");
13867 }
13868
13869 return RETURN_OK;
13870}
13871#else
13872INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13873{
13874 char interface_name[16] = {0};
13875 char cmd[128];
13876 BOOL status = false;
13877
13878 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13879 return RETURN_ERR;
13880
13881 output_buf[0] = '\0';
13882
13883 wifi_getApEnable(ap_index,&status);
13884 if (!status)
13885 return RETURN_OK;
13886
13887 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13888 return RETURN_ERR;
13889 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
13890 _syscmd(cmd, output_buf, output_buf_size);
developer69b61b02023-03-07 17:17:44 +080013891
developer72fb0bb2023-01-11 09:46:29 +080013892 return RETURN_OK;
13893}
13894#endif
13895
13896INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13897{
13898 char output[16]={'\0'};
13899 char config_file[MAX_BUF_SIZE] = {0};
13900
13901 if (!enable)
13902 return RETURN_ERR;
13903
13904 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13905 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13906
13907 if (strlen(output) == 0)
13908 *enable = FALSE;
13909 else if (strncmp(output, "1", 1) == 0)
13910 *enable = TRUE;
13911 else
13912 *enable = FALSE;
13913
13914 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13915 return RETURN_OK;
13916}
13917
13918INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13919{
13920 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
13921 return RETURN_ERR;
13922 *output_enable=TRUE;
13923 return RETURN_OK;
13924}
13925
13926INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13927{
13928 char cmd[128] = {0};
13929 char buf[128] = {0};
13930 char line[128] = {0};
13931 size_t len = 0;
13932 FILE *f = NULL;
13933 int index = 0;
13934 int exp = 0;
13935 int mantissa = 0;
13936 int duration = 0;
13937 int radio_index = 0;
13938 int max_radio_num = 0;
13939 uint twt_wake_interval = 0;
13940 int phyId = 0;
13941 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13942
13943 wifi_getMaxRadioNumber(&max_radio_num);
13944
13945 radio_index = ap_index % max_radio_num;
13946
13947 phyId = radio_index_to_phy(radio_index);
13948 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
13949 _syscmd(cmd, buf, sizeof(buf));
13950 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13951 if (*numSessionReturned > maxNumberSessions)
13952 *numSessionReturned = maxNumberSessions;
13953 else if (*numSessionReturned < 1) {
13954 *numSessionReturned = 0;
13955 return RETURN_OK;
13956 }
13957
13958 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
13959 if ((f = popen(cmd, "r")) == NULL) {
13960 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13961 return RETURN_ERR;
13962 }
13963
13964 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
13965 while((fgets(line, sizeof(line), f)) != NULL) {
13966 char *tmp = NULL;
13967 strcpy(buf, line);
13968 tmp = strtok(buf, " ");
13969 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13970 tmp = strtok(NULL, " ");
13971 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13972 tmp = strtok(NULL, " ");
13973 if (strstr(tmp, "t")) {
13974 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13975 }
13976 if (strstr(tmp, "a")) {
13977 twtSessions[index].twtParameters.operation.announced = TRUE;
13978 }
13979 tmp = strtok(NULL, " ");
13980 exp = strtol(tmp, NULL, 10);
13981 tmp = strtok(NULL, " ");
13982 mantissa = strtol(tmp, NULL, 10);
13983 tmp = strtok(NULL, " ");
13984 duration = strtol(tmp, NULL, 10);
13985
13986 // only implicit supported
13987 twtSessions[index].twtParameters.operation.implicit = TRUE;
13988 // only individual agreement supported
13989 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13990
13991 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13992 twt_wake_interval = mantissa * (1 << exp);
13993 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
13994 // Overflow handling
13995 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13996 } else {
13997 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13998 }
13999 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
14000 index++;
14001 }
14002
14003 pclose(f);
14004 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14005 return RETURN_OK;
14006}