blob: c6fab23d0008606da93f61a12b691674668cd259 [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>
developer8dd72532023-05-17 19:58:35 +080057#include <net/if.h>
58#include <unl.h>
59#include "mtk_vendor_nl80211.h"
developer72fb0bb2023-01-11 09:46:29 +080060#endif
61
62#include <ev.h>
63#include <wpa_ctrl.h>
64#include <errno.h>
65#include <time.h>
66#define MAC_ALEN 6
67
68#define MAX_BUF_SIZE 256
69#define MAX_CMD_SIZE 256
70#define IF_NAME_SIZE 16
71#define CONFIG_PREFIX "/nvram/hostapd"
72#define ACL_PREFIX "/nvram/hostapd-acl"
73#define DENY_PREFIX "/nvram/hostapd-deny"
74//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
75#define SOCK_PREFIX "/var/run/hostapd/wifi"
76#define VAP_STATUS_FILE "/nvram/vap-status"
77#define ESSID_FILE "/tmp/essid"
78#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
79#define CHANNEL_STATS_FILE "/tmp/channel_stats"
80#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
81#define VLAN_FILE "/nvram/hostapd.vlan"
82#define PSK_FILE "/nvram/hostapd"
83#define MCS_FILE "/tmp/MCS"
developera1255e42023-05-13 17:45:02 +080084#define POWER_PERCENTAGE "/tmp/POWER"
85#define MGMT_POWER_CTRL "/tmp/mgmt_power_ctrl"
86/*LOGAN_DAT_FILE: may be different on customer's platform.*/
87#define LOGAN_DAT_FILE "/etc/wireless/mediatek/mt7990.b"
88
developer72fb0bb2023-01-11 09:46:29 +080089#define NOACK_MAP_FILE "/tmp/NoAckMap"
developerf6a87542023-05-16 15:47:28 +080090
developer72fb0bb2023-01-11 09:46:29 +080091#define BRIDGE_NAME "brlan0"
developerd1824452023-05-18 12:30:04 +080092#define BASE_PHY_INDEX 1
93#define BASE_RADIO_INDEX 0
developer72fb0bb2023-01-11 09:46:29 +080094
95/*
96 MAX_APS - Number of all AP available in system
97 2x Home AP
98 2x Backhaul AP
99 2x Guest AP
100 2x Secure Onboard AP
101 2x Service AP
102
103*/
104
105
106#define MAX_APS MAX_NUM_RADIOS*5
developer7e4a2a62023-04-06 19:56:03 +0800107
108#define PREFIX_WIFI2G "ra"
109#define PREFIX_WIFI5G "rai"
110#define PREFIX_WIFI6G "rax"
developer72fb0bb2023-01-11 09:46:29 +0800111
developer47cc27a2023-05-17 23:09:58 +0800112#define PREFIX_SSID_2G "RDKB_2G"
113#define PREFIX_SSID_5G "RDKB_5G"
114#define PREFIX_SSID_6G "RDKB_6G"
115
developer72fb0bb2023-01-11 09:46:29 +0800116#ifndef RADIO_PREFIX
117#define RADIO_PREFIX "wlan"
118#endif
119
120#define MAX_ASSOCIATED_STA_NUM 2007
121
122//Uncomment to enable debug logs
123//#define WIFI_DEBUG
124
125#ifdef WIFI_DEBUG
126#define wifi_dbg_printf printf
127#define WIFI_ENTRY_EXIT_DEBUG printf
128#else
129#define wifi_dbg_printf(format, args...) printf("")
130#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
131#endif
132
133#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
134#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
135#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
136#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
137#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
138#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
139#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
140#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
141#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
142#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
143
144#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
145
146#define BW_FNAME "/nvram/bw_file.txt"
147
148#define PS_MAX_TID 16
149
developer96b38512023-02-22 11:17:45 +0800150#define MAX_CARD_INDEX 3
151
developer72fb0bb2023-01-11 09:46:29 +0800152static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
153 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
154 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
155 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
156 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
157 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
158 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
159 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
160 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
161 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
162 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
163 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
164 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
165 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
166 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
167 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
168 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
169};
170
171typedef unsigned long long u64;
172
173/* Enum to define WiFi Bands */
174typedef enum
175{
176 band_invalid = -1,
177 band_2_4 = 0,
178 band_5 = 1,
179 band_6 = 2,
180} wifi_band;
181
developer17038e62023-03-02 14:43:43 +0800182char* wifi_band_str[] = {
183 "2G",
184 "5G",
185 "6G",
186};
187
developer72fb0bb2023-01-11 09:46:29 +0800188typedef enum {
189 WIFI_MODE_A = 0x01,
190 WIFI_MODE_B = 0x02,
191 WIFI_MODE_G = 0x04,
192 WIFI_MODE_N = 0x08,
193 WIFI_MODE_AC = 0x10,
194 WIFI_MODE_AX = 0x20,
developera1255e42023-05-13 17:45:02 +0800195 WIFI_MODE_BE = 0x40,
developer72fb0bb2023-01-11 09:46:29 +0800196} wifi_ieee80211_Mode;
197
developerd1824452023-05-18 12:30:04 +0800198typedef enum ht_config_bw{
199 HT_BW_20,
200 HT_BW_40,
201};
202
203typedef enum vht_config_bw{
204 VHT_BW_2040,
205 VHT_BW_80,
206 VHT_BW_160,
207 VHT_BW_8080,
208};
209
210typedef enum eht_config_bw{
211 EHT_BW_20,
212 EHT_BW_40,
213 EHT_BW_80,
214 EHT_BW_160,
215 EHT_BW_320,
216};
217
developer72fb0bb2023-01-11 09:46:29 +0800218#ifdef WIFI_HAL_VERSION_3
219
220// Return number of elements in array
221#ifndef ARRAY_SIZE
222#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
223#endif /* ARRAY_SIZE */
224
225#ifndef ARRAY_AND_SIZE
226#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
227#endif /* ARRAY_AND_SIZE */
228
229#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
230
231typedef struct {
232 int32_t value;
233 int32_t param;
234 intptr_t key;
235 intptr_t data;
236} wifi_secur_list;
237
238static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
239static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
240wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
241wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
242char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
243static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer47cc27a2023-05-17 23:09:58 +0800244static void wifi_PrepareDefaultHostapdConfigs(void);
245static void wifi_psk_file_reset();
246
developer72fb0bb2023-01-11 09:46:29 +0800247
248static wifi_secur_list map_security[] =
249{
250 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
251 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
252 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
253 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
254 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
255 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
256 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
257 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
258 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
259 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
260 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
261 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
262};
263
264wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
265{
266 wifi_secur_list *item;
267 int i;
268
269 for (item = list,i = 0;i < list_sz; item++, i++) {
270 if ((int)(item->key) == key) {
271 return item;
272 }
273 }
274
275 return NULL;
276}
277
278char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
279{
280 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
281
282 if (!item) {
283 return "";
284 }
285
286 return (char *)(item->data);
287}
288
289wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
290{
291 wifi_secur_list *item;
292 int i;
293
294 for (item = list,i = 0;i < list_sz; item++, i++) {
295 if (strcmp((char *)(item->data), str) == 0) {
296 return item;
297 }
298 }
299
300 return NULL;
301}
302#endif /* WIFI_HAL_VERSION_3 */
303
developer96b38512023-02-22 11:17:45 +0800304
305static char l1profile[32] = "/etc/wireless/l1profile.dat";
developer17038e62023-03-02 14:43:43 +0800306char main_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
307char ext_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
308#define MAX_SSID_LEN 64
309char default_ssid[MAX_NUM_RADIOS][MAX_SSID_LEN];;
developer745f0bd2023-03-06 14:32:53 +0800310int radio_band[MAX_NUM_RADIOS];
developer17038e62023-03-02 14:43:43 +0800311
312static int array_index_to_vap_index(UINT radioIndex, int arrayIndex);
313static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex);
314
developer96b38512023-02-22 11:17:45 +0800315
316static int
317get_value(const char *conf_file, const char *param, char *value, int len)
318{
319 FILE *fp;
320 int ret = -1;
321 int param_len = strlen(param);
322 int buf_len;
323 char buf[256];
324
325 fp = fopen(conf_file, "r");
326 if (!fp) {
327 return -1;
328 }
329
330 while (fgets(buf, sizeof(buf), fp)) {
331 buf_len = strlen(buf);
332 if (buf[buf_len - 1] == '\n') {
333 buf_len--;
334 buf[buf_len] = '\0';
335 }
336 if ((buf_len > param_len) &&
337 (strncmp(buf, param, param_len) == 0) &&
338 (buf[param_len] == '=')) {
339
340 if (buf_len == (param_len + 1)) {
341 value[0] = '\0';
342 ret = 0;
343 } else {
344 ret = snprintf(value, len, "%s", buf + (param_len + 1));
345 }
346 fclose(fp);
347 return ret;
348 }
349 }
350 fclose(fp);
351 return -1;
352}
353
354static int
355get_value_by_idx(const char *conf_file, const char *param, int idx, char *value, int len)
356{
357 char buf[256];
358 int ret;
359 char *save_ptr = NULL;
360 char *tok = NULL;
361
362 ret = get_value(conf_file, param, buf, sizeof(buf));
363 if (ret < 0)
364 return ret;
365
366 tok = strtok_r(buf, ";", &save_ptr);
367 do {
368 if (idx == 0 || tok == NULL)
369 break;
370 else
371 idx--;
372
373 tok = strtok_r(NULL, ";", &save_ptr);
374 } while (tok != NULL);
375
376 if (tok) {
377 ret = snprintf(value, len, "%s", tok);
378 } else {
379 ret = 0;
380 value[0] = '\0';
381 }
382
383 return ret;
384}
385
386
developer72fb0bb2023-01-11 09:46:29 +0800387#ifdef HAL_NETLINK_IMPL
388typedef struct {
389 int id;
390 struct nl_sock* socket;
391 struct nl_cb* cb;
392} Netlink;
393
394static int mac_addr_aton(unsigned char *mac_addr, char *arg)
395{
396 unsigned int mac_addr_int[6]={};
397 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);
398 mac_addr[0] = mac_addr_int[0];
399 mac_addr[1] = mac_addr_int[1];
400 mac_addr[2] = mac_addr_int[2];
401 mac_addr[3] = mac_addr_int[3];
402 mac_addr[4] = mac_addr_int[4];
403 mac_addr[5] = mac_addr_int[5];
404 return 0;
405}
406
407static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
408{
409 unsigned int mac_addr_int[6]={};
410 mac_addr_int[0] = arg[0];
411 mac_addr_int[1] = arg[1];
412 mac_addr_int[2] = arg[2];
413 mac_addr_int[3] = arg[3];
414 mac_addr_int[4] = arg[4];
415 mac_addr_int[5] = arg[5];
416 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]);
417 return;
418}
419
420static int ieee80211_frequency_to_channel(int freq)
421{
422 /* see 802.11-2007 17.3.8.3.2 and Annex J */
423 if (freq == 2484)
424 return 14;
425 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
426 else if (freq == 5935)
427 return 2;
428 else if (freq < 2484)
429 return (freq - 2407) / 5;
430 else if (freq >= 4910 && freq <= 4980)
431 return (freq - 4000) / 5;
432 else if (freq < 5950)
433 return (freq - 5000) / 5;
434 else if (freq <= 45000) /* DMG band lower limit */
435 /* see 802.11ax D6.1 27.3.23.2 */
436 return (freq - 5950) / 5;
437 else if (freq >= 58320 && freq <= 70200)
438 return (freq - 56160) / 2160;
439 else
440 return 0;
441}
442
443static int initSock80211(Netlink* nl) {
444 nl->socket = nl_socket_alloc();
445 if (!nl->socket) {
446 fprintf(stderr, "Failing to allocate the sock\n");
447 return -ENOMEM;
448 }
449
450 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
451
452 if (genl_connect(nl->socket)) {
453 fprintf(stderr, "Failed to connect\n");
454 nl_close(nl->socket);
455 nl_socket_free(nl->socket);
456 return -ENOLINK;
457 }
458
459 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
460 if (nl->id< 0) {
461 fprintf(stderr, "interface not found.\n");
462 nl_close(nl->socket);
463 nl_socket_free(nl->socket);
464 return -ENOENT;
465 }
466
467 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
468 if ((!nl->cb)) {
469 fprintf(stderr, "Failed to allocate netlink callback.\n");
470 nl_close(nl->socket);
471 nl_socket_free(nl->socket);
472 return ENOMEM;
473 }
474
475 return nl->id;
476}
477
478static int nlfree(Netlink *nl)
479{
480 nl_cb_put(nl->cb);
481 nl_close(nl->socket);
482 nl_socket_free(nl->socket);
483 return 0;
484}
485
486static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
487 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
488 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
489 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
490};
491
492static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
493};
494
495static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
496};
497
498typedef struct _wifi_channelStats_loc {
499 INT array_size;
500 INT ch_number;
501 BOOL ch_in_pool;
502 INT ch_noise;
503 BOOL ch_radar_noise;
504 INT ch_max_80211_rssi;
505 INT ch_non_80211_noise;
506 INT ch_utilization;
507 ULLONG ch_utilization_total;
508 ULLONG ch_utilization_busy;
509 ULLONG ch_utilization_busy_tx;
510 ULLONG ch_utilization_busy_rx;
511 ULLONG ch_utilization_busy_self;
512 ULLONG ch_utilization_busy_ext;
513} wifi_channelStats_t_loc;
514
515typedef struct wifi_device_info {
516 INT wifi_devIndex;
517 UCHAR wifi_devMacAddress[6];
518 CHAR wifi_devIPAddress[64];
519 BOOL wifi_devAssociatedDeviceAuthentiationState;
520 INT wifi_devSignalStrength;
521 INT wifi_devTxRate;
522 INT wifi_devRxRate;
523} wifi_device_info_t;
524
525#endif
526
527//For 5g Alias Interfaces
528static BOOL priv_flag = TRUE;
529static BOOL pub_flag = TRUE;
530static BOOL Radio_flag = TRUE;
531//wifi_setApBeaconRate(1, beaconRate);
532
533BOOL multiple_set = FALSE;
534
535struct params
536{
537 char * name;
538 char * value;
539};
540
541static int _syscmd(char *cmd, char *retBuf, int retBufSize)
542{
543 FILE *f;
544 char *ptr = retBuf;
545 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
546
547 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
548 if((f = popen(cmd, "r")) == NULL) {
549 fprintf(stderr,"\npopen %s error\n", cmd);
550 return RETURN_ERR;
551 }
552
553 while(!feof(f))
554 {
555 *ptr = 0;
556 if(bufSize>=128) {
557 bufbytes=128;
558 } else {
559 bufbytes=bufSize-1;
560 }
561
562 fgets(ptr,bufbytes,f);
563 readbytes=strlen(ptr);
564
565 if(!readbytes)
566 break;
567
568 bufSize-=readbytes;
569 ptr += readbytes;
570 }
571 cmd_ret = pclose(f);
572 retBuf[retBufSize-1]=0;
573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
574
575 return cmd_ret >> 8;
576}
577
578INT radio_index_to_phy(int radioIndex)
579{
developer17038e62023-03-02 14:43:43 +0800580 /* TODO */
581 return radioIndex;
developer72fb0bb2023-01-11 09:46:29 +0800582}
583
584INT wifi_getMaxRadioNumber(INT *max_radio_num)
585{
586 char cmd[64] = {0};
587 char buf[4] = {0};
588
589 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
590
591 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
592 _syscmd(cmd, buf, sizeof(buf));
593 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
594
595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
596
597 return RETURN_OK;
598}
599
developer17038e62023-03-02 14:43:43 +0800600wifi_band radio_index_to_band(int radioIndex)
601{
developer745f0bd2023-03-06 14:32:53 +0800602 return radio_band[radioIndex];
developer17038e62023-03-02 14:43:43 +0800603}
604
developer72fb0bb2023-01-11 09:46:29 +0800605wifi_band wifi_index_to_band(int apIndex)
606{
607 char cmd[128] = {0};
608 char buf[64] = {0};
609 int nl80211_band = 0;
610 int i = 0;
611 int phyIndex = 0;
612 int radioIndex = 0;
613 int max_radio_num = 0;
614 wifi_band band = band_invalid;
615
616 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
617
618 wifi_getMaxRadioNumber(&max_radio_num);
619 radioIndex = apIndex % max_radio_num;
620 phyIndex = radio_index_to_phy(radioIndex);
621 while(i < 10){
622 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
623 _syscmd(cmd, buf, sizeof(buf));
624 nl80211_band = strtol(buf, NULL, 10);
625 if (nl80211_band == 1)
626 band = band_2_4;
627 else if (nl80211_band == 2)
628 band = band_5;
629 else if (nl80211_band == 4) // band == 3 is 60GHz
630 band = band_6;
631
632 if(band != band_invalid)
633 break;
developer69b61b02023-03-07 17:17:44 +0800634
developer72fb0bb2023-01-11 09:46:29 +0800635 i++;
636 sleep(1);
637 }
638
639 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
640 return band;
641}
642
643static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
644{
developer7e4a2a62023-04-06 19:56:03 +0800645 char cmd[MAX_CMD_SIZE] = {0};
646 char buf[MAX_BUF_SIZE] = {0};
647 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +0800648
developer7e4a2a62023-04-06 19:56:03 +0800649 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
650 conf_file, param);
developer72fb0bb2023-01-11 09:46:29 +0800651
developer7e4a2a62023-04-06 19:56:03 +0800652 if (ret < 0) {
653 printf("%s: snprintf error!", __func__);
654 return -1;
655 }
656
657 ret = _syscmd(cmd, buf, sizeof(buf));
658 if ((ret != 0) && (strlen(buf) == 0)) {
659 printf("%s: _syscmd error!", __func__);
660 return -1;
661 }
662
663 snprintf(output, output_size, "%s", buf);
664
665 return 0;
developer72fb0bb2023-01-11 09:46:29 +0800666}
667
668static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
669{
developer7e4a2a62023-04-06 19:56:03 +0800670 char cmd[MAX_CMD_SIZE] = {0};
671 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +0800672
developer7e4a2a62023-04-06 19:56:03 +0800673 for (int i = 0; i < item_count; i++) {
developer72fb0bb2023-01-11 09:46:29 +0800674 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +0800675 if (strlen(buf) == 0) /*no such item, insert it*/
developera1255e42023-05-13 17:45:02 +0800676 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 +0800677 else /*find the item, update it*/
developer72fb0bb2023-01-11 09:46:29 +0800678 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 +0800679
developer72fb0bb2023-01-11 09:46:29 +0800680 if(_syscmd(cmd, buf, sizeof(buf)))
681 return -1;
682 }
683
developera1255e42023-05-13 17:45:02 +0800684 return 0;
685}
686static int wifi_datfileRead(char *conf_file, char *param, char *output, int output_size)
687{
688 char cmd[MAX_CMD_SIZE] = {0};
689 char buf[MAX_BUF_SIZE] = {0};
690 int ret = 0;
691
692 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
693 conf_file, param);
694
695 if (ret < 0) {
696 printf("%s: snprintf error!", __func__);
697 return -1;
698 }
699
700 ret = _syscmd(cmd, buf, sizeof(buf));
701 if ((ret != 0) && (strlen(buf) == 0)) {
702 printf("%s: _syscmd error!", __func__);
703 return -1;
704 }
705
706 snprintf(output, output_size, "%s", buf);
707
developer72fb0bb2023-01-11 09:46:29 +0800708 return 0;
709}
710
developera1255e42023-05-13 17:45:02 +0800711static int wifi_datfileWrite(char *conf_file, struct params *list, int item_count)
712{
713 char cmd[MAX_CMD_SIZE] = {0};
714 char buf[MAX_BUF_SIZE] = {0};
715
716 for (int i = 0; i < item_count; i++) {
717 wifi_datfileRead(conf_file, list[i].name, buf, sizeof(buf));
718 if (strlen(buf) == 0) /*no such item, insert it*/
719 snprintf(cmd, sizeof(cmd), "sed -i -e '$a %s=%s' %s", list[i].name, list[i].value, conf_file);
720 else /*find the item, update it*/
721 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
722
723 if(_syscmd(cmd, buf, sizeof(buf)))
724 return -1;
725 }
726
727 return 0;
728}
729
developer72fb0bb2023-01-11 09:46:29 +0800730//For Getting Current Interface Name from corresponding hostapd configuration
731static int wifi_GetInterfaceName(int apIndex, char *interface_name)
732{
733 char config_file[128] = {0};
734
735 if (interface_name == NULL)
736 return RETURN_ERR;
737
738 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
739
740 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
741 wifi_hostapdRead(config_file, "interface", interface_name, 16);
742 if (strlen(interface_name) == 0)
743 return RETURN_ERR;
744
745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
746 return RETURN_OK;
747}
748
developera1255e42023-05-13 17:45:02 +0800749static UCHAR get_bssnum_byindex(INT radio_index, UCHAR *bss_cnt)
750{
751 char interface_name[IF_NAME_SIZE] = {0};
752 char cmd[MAX_BUF_SIZE]={'\0'};
753 char buf[MAX_CMD_SIZE]={'\0'};
754 UCHAR channel = 0;
755
756 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
757 return RETURN_ERR;
758 /*interface name to channel number*/
759 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep -i 'channel' | cut -d ' ' -f2", interface_name);
760 _syscmd(cmd, buf, sizeof(buf));
761 channel = atoi(buf);
762 WIFI_ENTRY_EXIT_DEBUG("%s:channel=%d\n", __func__, channel);
763 /*count dev number with the same channel*/
764 snprintf(cmd, sizeof(cmd), "iw dev | grep -i 'channel %d' | wc -l", channel);
765 _syscmd(cmd, buf, sizeof(buf));
766 *bss_cnt = atoi(buf) - 1;/*1 for apcli interface*/
767 WIFI_ENTRY_EXIT_DEBUG("%s:bss_cnt=%d\n", __func__, *bss_cnt);
768 return RETURN_OK;
769}
developer72fb0bb2023-01-11 09:46:29 +0800770
developerd1824452023-05-18 12:30:04 +0800771/* index: radio index or phy index
772 phy: true-> base phy command
773 false-> base radio command */
774static int wifi_mwctlSet(int index, struct params *mwctl, bool phy)
775{
776 char cmd[MAX_CMD_SIZE]={'\0'};
777 char buf[MAX_BUF_SIZE]={'\0'};
778 char interface_name[16] = {0};
779
780 if (phy == TRUE)
781 snprintf(cmd, sizeof(cmd), "mwctl phy phy%d set %s%s", index, mwctl->name, mwctl->value);
782 else {
783 if (wifi_GetInterfaceName(index, interface_name) != RETURN_OK)
784 return RETURN_ERR;
785 snprintf(cmd, sizeof(cmd), "mwctl %s set %s%s", interface_name, mwctl->name, mwctl->value);
786 }
787 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
788 return RETURN_ERR;
789
790 return RETURN_OK;
791}
792
developer72fb0bb2023-01-11 09:46:29 +0800793static 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 {
developerf6a87542023-05-16 15:47:28 +0800806 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer72fb0bb2023-01-11 09:46:29 +0800807 if((fp = popen(cmd, "r"))==NULL)
808 {
809 perror("popen failed");
810 return -1;
811 }
812 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
813 {
814 pclose(fp);
815 perror("fgets failed");
816 return -1;
817 }
818 pclose(fp);
819 }
820 return 0;
821}
822
developer7e4a2a62023-04-06 19:56:03 +0800823static int wifi_quick_reload_ap(int apIndex)
824{
825 char interface_name[IF_NAME_SIZE] = {0};
826 char cmd[MAX_CMD_SIZE] = {0};
827 char buf[MAX_BUF_SIZE] = {0};
828
829 if (multiple_set == TRUE)
830 return RETURN_OK;
831
832 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
833 return RETURN_ERR;
834
835 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
836 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
837 return RETURN_ERR;
838
839 return RETURN_OK;
840}
841
developer72fb0bb2023-01-11 09:46:29 +0800842static int wifi_reloadAp(int apIndex)
843{
844 char interface_name[16] = {0};
845 if (multiple_set == TRUE)
846 return RETURN_OK;
847 char cmd[MAX_CMD_SIZE]="";
848 char buf[MAX_BUF_SIZE]="";
849
850 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
851 return RETURN_ERR;
852 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
853 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
854 return RETURN_ERR;
855
856 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
857 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
858 return RETURN_ERR;
859
860 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
861 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
862 return RETURN_ERR;
863
864 return RETURN_OK;
865}
866
867INT File_Reading(CHAR *file, char *Value)
868{
869 FILE *fp = NULL;
870 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
871 int count = 0;
872
873 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
874 fp = popen(file,"r");
875 if(fp == NULL)
876 return RETURN_ERR;
877
878 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
879 {
880 for(count=0;buf[count]!='\n';count++)
881 copy_buf[count]=buf[count];
882 copy_buf[count]='\0';
883 }
884 strcpy(Value,copy_buf);
885 pclose(fp);
886 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
887
888 return RETURN_OK;
889}
890
891void wifi_RestartHostapd_2G()
892{
893 int Public2GApIndex = 4;
894
895 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
896 wifi_setApEnable(Public2GApIndex, FALSE);
897 wifi_setApEnable(Public2GApIndex, TRUE);
898 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
899}
900
901void wifi_RestartHostapd_5G()
902{
903 int Public5GApIndex = 5;
904
905 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
906 wifi_setApEnable(Public5GApIndex, FALSE);
907 wifi_setApEnable(Public5GApIndex, TRUE);
908 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
909}
910
911void wifi_RestartPrivateWifi_2G()
912{
913 int PrivateApIndex = 0;
914
915 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
916 wifi_setApEnable(PrivateApIndex, FALSE);
917 wifi_setApEnable(PrivateApIndex, TRUE);
918 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
919}
920
921void wifi_RestartPrivateWifi_5G()
922{
923 int Private5GApIndex = 1;
924
925 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
926 wifi_setApEnable(Private5GApIndex, FALSE);
927 wifi_setApEnable(Private5GApIndex, TRUE);
928 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
929}
930
931static int writeBandWidth(int radioIndex,char *bw_value)
932{
933 char buf[MAX_BUF_SIZE];
934 char cmd[MAX_CMD_SIZE];
935
936 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
937 if(_syscmd(cmd, buf, sizeof(buf)))
938 {
939 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
940 _syscmd(cmd, buf, sizeof(buf));
941 return RETURN_OK;
942 }
943
944 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
945 _syscmd(cmd,buf,sizeof(buf));
946 return RETURN_OK;
947}
948
949static int readBandWidth(int radioIndex,char *bw_value)
950{
951 char buf[MAX_BUF_SIZE] = {0};
952 char cmd[MAX_CMD_SIZE] = {0};
953 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
954 _syscmd(cmd,buf,sizeof(buf));
955 if(NULL!=strstr(buf,"20MHz"))
developer72fb0bb2023-01-11 09:46:29 +0800956 strcpy(bw_value,"20MHz");
developer72fb0bb2023-01-11 09:46:29 +0800957 else if(NULL!=strstr(buf,"40MHz"))
developer72fb0bb2023-01-11 09:46:29 +0800958 strcpy(bw_value,"40MHz");
developer72fb0bb2023-01-11 09:46:29 +0800959 else if(NULL!=strstr(buf,"80MHz"))
developer72fb0bb2023-01-11 09:46:29 +0800960 strcpy(bw_value,"80MHz");
developerd1824452023-05-18 12:30:04 +0800961 else if(NULL!=strstr(buf,"160MHz"))
962 strcpy(bw_value,"160MHz");
963 else if(NULL!=strstr(buf,"320MHz"))
964 strcpy(bw_value,"320MHz");
developer72fb0bb2023-01-11 09:46:29 +0800965 else
developer72fb0bb2023-01-11 09:46:29 +0800966 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +0800967 return RETURN_OK;
968}
969
970// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
971INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
972{
973 struct params params={'\0'};
974 char config_file[MAX_BUF_SIZE] = {0};
975 char buf[MAX_BUF_SIZE] = {'\0'};
976
977 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
978 // Copy the numeric value
979 if (strlen (beaconRate) >= 5) {
980 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
981 buf[strlen(beaconRate) - 4] = '\0';
982 } else if (strlen(beaconRate) > 0)
983 strcpy(buf, beaconRate);
984 else
985 return RETURN_ERR;
986
987 params.name = "beacon_rate";
988 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
989 if (strncmp(buf, "5.5", 3) == 0) {
990 snprintf(buf, sizeof(buf), "55");
991 params.value = buf;
992 } else {
993 strcat(buf, "0");
994 params.value = buf;
995 }
996
997 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
998 wifi_hostapdWrite(config_file, &params, 1);
999 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1000 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1001
1002 return RETURN_OK;
1003}
1004
1005INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
1006{
1007 char config_file[128] = {'\0'};
1008 char temp_output[128] = {'\0'};
1009 char buf[128] = {'\0'};
1010 char cmd[128] = {'\0'};
1011 int rate = 0;
1012 int phyId = 0;
1013
1014 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1015 if (NULL == beaconRate)
1016 return RETURN_ERR;
1017
1018 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1019 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
1020 phyId = radio_index_to_phy(radioIndex);
1021 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
1022 if(strlen(buf) > 0) {
1023 if (strncmp(buf, "55", 2) == 0)
1024 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
1025 else {
1026 rate = strtol(buf, NULL, 10)/10;
1027 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
1028 }
1029 } else {
1030 // config not set, so we would use lowest rate as default
1031 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
1032 _syscmd(cmd, buf, sizeof(buf));
1033 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
1034 }
1035 strncpy(beaconRate, temp_output, sizeof(temp_output));
1036 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1037
1038 return RETURN_OK;
1039}
1040
1041INT wifi_setLED(INT radioIndex, BOOL enable)
1042{
1043 return 0;
1044}
1045INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
1046{
1047 return RETURN_OK;
1048}
1049/**********************************************************************************
1050 *
developer69b61b02023-03-07 17:17:44 +08001051 * Wifi Subsystem level function prototypes
developer72fb0bb2023-01-11 09:46:29 +08001052 *
1053**********************************************************************************/
1054//---------------------------------------------------------------------------------------------------
1055//Wifi system api
1056//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 +08001057INT wifi_getHalVersion(CHAR *output_string) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08001058{
1059 if(!output_string)
1060 return RETURN_ERR;
1061 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
1062
1063 return RETURN_OK;
1064}
1065
1066
1067/* wifi_factoryReset() function */
1068/**
developer69b61b02023-03-07 17:17:44 +08001069* @description Clears internal variables to implement a factory reset of the Wi-Fi
developer72fb0bb2023-01-11 09:46:29 +08001070* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
1071*
1072* @param None
1073*
1074* @return The status of the operation.
1075* @retval RETURN_OK if successful.
1076* @retval RETURN_ERR if any error is detected
1077*
1078* @execution Synchronous
1079* @sideeffect None
1080*
1081* @note This function must not suspend and must not invoke any blocking system
1082* calls. It should probably just send a message to a driver event handler task.
1083*
1084*/
1085INT wifi_factoryReset()
1086{
developer47cc27a2023-05-17 23:09:58 +08001087 char cmd[MAX_CMD_SIZE] = {0};
1088 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001089
developer47cc27a2023-05-17 23:09:58 +08001090 /*delete running hostapd conf files*/
1091 wifi_dbg_printf("\n[%s]: deleting hostapd conf file.", __func__);
1092 snprintf(cmd, MAX_CMD_SIZE, "rm -rf /nvram/*.conf");
1093 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08001094
developer47cc27a2023-05-17 23:09:58 +08001095 wifi_PrepareDefaultHostapdConfigs();
1096 wifi_psk_file_reset();
1097
1098 memset(cmd, 0, MAX_CMD_SIZE);
1099 memset(buf, 0, MAX_BUF_SIZE);
1100
1101 snprintf(cmd, MAX_CMD_SIZE, "systemctl restart hostapd.service");
1102 _syscmd(cmd, buf, sizeof(buf));
1103
1104 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001105}
1106
1107/* wifi_factoryResetRadios() function */
1108/**
1109* @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.
1110*
1111* @param None
1112* @return The status of the operation
1113* @retval RETURN_OK if successful
1114* @retval RETURN_ERR if any error is detected
1115*
1116* @execution Synchronous
1117*
1118* @sideeffect None
1119*
1120* @note This function must not suspend and must not invoke any blocking system
1121* calls. It should probably just send a message to a driver event handler task.
1122*
1123*/
1124INT wifi_factoryResetRadios()
1125{
1126 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
1127 return RETURN_OK;
1128
1129 return RETURN_ERR;
1130}
1131
1132
1133/* wifi_factoryResetRadio() function */
1134/**
1135* @description Restore selected radio parameters without touching access point parameters
1136*
1137* @param radioIndex - Index of Wi-Fi Radio channel
1138*
1139* @return The status of the operation.
1140* @retval RETURN_OK if successful.
1141* @retval RETURN_ERR if any error is detected
1142*
1143* @execution Synchronous.
1144* @sideeffect None.
1145*
1146* @note This function must not suspend and must not invoke any blocking system
1147* calls. It should probably just send a message to a driver event handler task.
1148*
1149*/
1150INT wifi_factoryResetRadio(int radioIndex) //RDKB
1151{
developer47cc27a2023-05-17 23:09:58 +08001152 char cmd[MAX_CMD_SIZE] = {0};
1153 char buf[MAX_BUF_SIZE] = {0};
1154 char vap_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08001155
developer47cc27a2023-05-17 23:09:58 +08001156 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001157
developer47cc27a2023-05-17 23:09:58 +08001158 snprintf(cmd, MAX_CMD_SIZE, "systemctl stop hostapd.service");
1159 _syscmd(cmd, buf, sizeof(buf));
1160
1161 memset(cmd, 0, MAX_CMD_SIZE);
1162 memset(buf, 0, MAX_BUF_SIZE);
1163
1164 for (vap_idx = radioIndex; vap_idx < MAX_APS; vap_idx += MAX_NUM_RADIOS)
1165 wifi_factoryResetAP(vap_idx);
1166
1167 snprintf(cmd, MAX_CMD_SIZE, "systemctl start hostapd.service");
1168 _syscmd(cmd, buf, sizeof(buf));
1169
1170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1171 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001172}
1173
1174/* wifi_initRadio() function */
1175/**
1176* Description: This function call initializes the specified radio.
developer69b61b02023-03-07 17:17:44 +08001177* Implementation specifics may dictate the functionality since
developer72fb0bb2023-01-11 09:46:29 +08001178* different hardware implementations may have different initilization requirements.
1179* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
1180*
1181* @return The status of the operation.
1182* @retval RETURN_OK if successful.
1183* @retval RETURN_ERR if any error is detected
1184*
1185* @execution Synchronous.
1186* @sideeffect None.
1187*
1188* @note This function must not suspend and must not invoke any blocking system
1189* calls. It should probably just send a message to a driver event handler task.
1190*
1191*/
1192INT wifi_initRadio(INT radioIndex)
1193{
1194 //TODO: Initializes the wifi subsystem (for specified radio)
1195 return RETURN_OK;
1196}
1197void macfilter_init()
1198{
1199 char count[4]={'\0'};
1200 char buf[253]={'\0'};
1201 char tmp[19]={'\0'};
1202 int dev_count,block,mac_entry=0;
1203 char res[4]={'\0'};
1204 char acl_file_path[64] = {'\0'};
1205 FILE *fp = NULL;
1206 int index=0;
1207 char iface[10]={'\0'};
1208 char config_file[MAX_BUF_SIZE] = {0};
1209
1210
1211 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1212
1213 fp=fopen(acl_file_path,"w+");
1214 if (fp == NULL) {
1215 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
developer17038e62023-03-02 14:43:43 +08001216 return;
developer72fb0bb2023-01-11 09:46:29 +08001217 }
1218 sprintf(buf,"#!/bin/sh \n");
1219 fprintf(fp,"%s\n",buf);
1220
1221 system("chmod 0777 /tmp/mac_filter.sh");
1222
1223 for(index=0;index<=1;index++)
1224 {
1225 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1226 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1227 sprintf(buf,"syscfg get %dcountfilter",index);
1228 _syscmd(buf,count,sizeof(count));
1229 mac_entry=atoi(count);
1230
1231 sprintf(buf,"syscfg get %dblockall",index);
1232 _syscmd(buf,res,sizeof(res));
1233 block = atoi(res);
1234
1235 //Allow only those macs mentioned in ACL
1236 if(block==1)
1237 {
1238 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1239 fprintf(fp,"%s\n",buf);
1240 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1241 {
1242 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1243 _syscmd(buf,tmp,sizeof(tmp));
1244 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1245 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1246 fprintf(fp,"%s\n",buf);
1247 }
1248 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1249 fprintf(fp,"%s\n",buf);
1250 }
1251
1252 //Block all the macs mentioned in ACL
1253 else if(block==2)
1254 {
1255 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1256 fprintf(fp,"%s\n",buf);
1257
1258 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1259 {
1260 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1261 _syscmd(buf,tmp,sizeof(tmp));
1262 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1263 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1264 fprintf(fp,"%s\n",buf);
1265 }
1266 }
1267 }
1268 fclose(fp);
1269}
1270
developer17038e62023-03-02 14:43:43 +08001271
1272static void
1273wifi_ParseProfile(void)
1274{
1275 int i;
1276 int max_radio_num = 0;
1277 int card_idx;
1278 int band_idx;
1279 int phy_idx = 0;
developer745f0bd2023-03-06 14:32:53 +08001280 int wireless_mode = 0;
developer17038e62023-03-02 14:43:43 +08001281 char buf[MAX_BUF_SIZE] = {0};
1282 char chip_name[12];
1283 char card_profile[MAX_BUF_SIZE] = {0};
1284 char band_profile[MAX_BUF_SIZE] = {0};
1285 FILE* fp;
1286
1287 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1288
1289 memset(main_prefix, 0, sizeof(main_prefix));
1290 memset(ext_prefix, 0, sizeof(ext_prefix));
1291 memset(default_ssid, 0, sizeof(default_ssid));
developer745f0bd2023-03-06 14:32:53 +08001292 for (i = 0; i < MAX_NUM_RADIOS; i++)
1293 radio_band[i] = band_invalid;
developer17038e62023-03-02 14:43:43 +08001294
1295 if (wifi_getMaxRadioNumber(&max_radio_num) != RETURN_OK) {
1296 /* LOG */
1297 return;
1298 }
1299
1300 for (card_idx = 0; card_idx < 3; card_idx++) {
1301 snprintf(buf, sizeof(buf), "INDEX%d", card_idx);
1302 if (get_value(l1profile, buf, chip_name, sizeof(chip_name)) < 0) {
1303 break;
1304 }
1305 snprintf(buf, sizeof(buf), "INDEX%d_profile_path", card_idx);
1306 if (get_value(l1profile, buf, card_profile, sizeof(card_profile)) < 0) {
1307 break;
1308 }
1309 for (band_idx = 0; band_idx < 3; band_idx++) {
1310 snprintf(buf, sizeof(buf), "BN%d_profile_path", band_idx);
1311 if (get_value(card_profile, buf, band_profile, sizeof(band_profile)) < 0) {
1312 /* LOG */
1313 break;
1314 }
1315
1316 snprintf(buf, sizeof(buf), "INDEX%d_main_ifname", card_idx);
1317 if (get_value_by_idx(l1profile, buf, band_idx, main_prefix[phy_idx], IFNAMSIZ) < 0) {
1318 /* LOG */
1319 }
1320
1321 snprintf(buf, sizeof(buf), "INDEX%d_ext_ifname", card_idx);
1322 if (get_value_by_idx(l1profile, buf, band_idx, ext_prefix[phy_idx], IFNAMSIZ) < 0) {
1323 /* LOG */
1324 }
1325
1326 if (get_value(band_profile, "SSID1", default_ssid[phy_idx], sizeof(default_ssid[phy_idx])) < 0) {
1327 /* LOG */
1328 }
developer745f0bd2023-03-06 14:32:53 +08001329 if (get_value(band_profile, "WirelessMode", buf, sizeof(buf)) < 0) {
1330 /* LOG */
1331 }
1332
1333 wireless_mode = atoi(buf);
1334 switch (wireless_mode) {
1335 case 22:
1336 case 16:
1337 case 6:
1338 case 4:
1339 case 1:
1340 radio_band[phy_idx] = band_2_4;
1341 break;
1342 case 23:
1343 case 17:
1344 case 14:
1345 case 11:
1346 case 2:
1347 radio_band[phy_idx] = band_5;
1348 break;
1349 case 24:
1350 case 18:
1351 radio_band[phy_idx] = band_6;
1352 break;
1353 }
developer17038e62023-03-02 14:43:43 +08001354 phy_idx++;
1355 }
1356 }
1357
1358 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1359}
1360
1361static void
1362wifi_PrepareDefaultHostapdConfigs(void)
1363{
developer0132ed92023-03-21 13:48:53 +08001364 int radio_idx;
1365 int bss_idx;
1366 int ap_idx;
developer0132ed92023-03-21 13:48:53 +08001367 char buf[MAX_BUF_SIZE] = {0};
1368 char config_file[MAX_BUF_SIZE] = {0};
1369 char ssid[MAX_BUF_SIZE] = {0};
1370 char interface[32] = {0};
1371 char ret_buf[MAX_BUF_SIZE] = {0};
1372 char psk_file[64] = {0};
1373 struct params params[3];
developer47cc27a2023-05-17 23:09:58 +08001374 char *band_str[3] = {"2G", "5G", "6G"};
developer17038e62023-03-02 14:43:43 +08001375
developer0132ed92023-03-21 13:48:53 +08001376 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1377 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001378
developer0132ed92023-03-21 13:48:53 +08001379 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001380 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
developer0132ed92023-03-21 13:48:53 +08001381
developer47cc27a2023-05-17 23:09:58 +08001382 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1383 snprintf(buf, sizeof(buf), "cp /etc/hostapd-%s.conf %s", band_str[radio_idx], config_file);
1384 _syscmd(buf, ret_buf, sizeof(ret_buf));
developer17038e62023-03-02 14:43:43 +08001385
developer47cc27a2023-05-17 23:09:58 +08001386 if (radio_idx == band_2_4) {
1387 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
1388 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
1389 } else if (radio_idx == band_5) {
1390 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
1391 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
1392 } else if (radio_idx == band_6) {
1393 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
1394 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
1395 }
developer17038e62023-03-02 14:43:43 +08001396
developer47cc27a2023-05-17 23:09:58 +08001397 /* fix wpa_psk_file path */
1398 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", ap_idx);
developer17038e62023-03-02 14:43:43 +08001399
developer47cc27a2023-05-17 23:09:58 +08001400 params[0].name = "ssid";
1401 params[0].value = ssid;
1402 params[1].name = "interface";
1403 params[1].value = interface;
1404 params[2].name = "wpa_psk_file";
1405 params[2].value = psk_file;
developer17038e62023-03-02 14:43:43 +08001406
developer47cc27a2023-05-17 23:09:58 +08001407 wifi_hostapdWrite(config_file, params, 3);
developer0132ed92023-03-21 13:48:53 +08001408 }
1409 }
1410 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001411}
1412
1413static void
1414wifiBringUpInterfacesForRadio(int radio_idx)
1415{
developer0132ed92023-03-21 13:48:53 +08001416 int bss_idx;
1417 int ap_idx;
1418 int band_idx;
1419 char cmd[MAX_CMD_SIZE] = {0};
1420 char config_file[MAX_BUF_SIZE] = {0};
1421 char ret_buf[MAX_BUF_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001422 char inf_name[IF_NAME_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001423
1424 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer8a3bbbf2023-03-15 17:47:23 +08001425
developered997d32023-04-18 22:45:39 +08001426 bss_idx = 0;
1427 /*TBD: we need refine setup flow and mbss flow*/
1428// for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer0132ed92023-03-21 13:48:53 +08001429 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1430
1431 snprintf(cmd, sizeof(cmd), "touch %s%d.psk", PSK_FILE, ap_idx);
1432 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1433
1434 memset(cmd, 0, MAX_CMD_SIZE);
1435 memset(ret_buf, 0, MAX_BUF_SIZE);
developer17038e62023-03-02 14:43:43 +08001436
developer0132ed92023-03-21 13:48:53 +08001437 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1438 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radio_idx, config_file);
1439 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer8a3bbbf2023-03-15 17:47:23 +08001440
1441 wifi_GetInterfaceName(ap_idx, inf_name);
1442
1443 memset(cmd, 0, MAX_CMD_SIZE);
1444 memset(ret_buf, 0, MAX_BUF_SIZE);
1445
1446 /* fix vap-status file */
1447 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=1/\" %s", inf_name, inf_name, VAP_STATUS_FILE);
1448 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developered997d32023-04-18 22:45:39 +08001449// }
1450
1451 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001452}
1453
1454static void
1455wifi_BringUpInterfaces(void)
1456{
1457 int radio_idx;
1458 int bss_idx;
1459 int ap_idx;
1460 int band_idx;
1461 char cmd[MAX_BUF_SIZE] = {0};
1462 char config_file[MAX_BUF_SIZE] = {0};
1463 char ret_buf[MAX_BUF_SIZE]={'\0'};
1464
1465 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1466 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1467 band_idx = radio_index_to_band(radio_idx);
1468 if (band_idx < 0) {
1469 break;
1470 }
1471 wifiBringUpInterfacesForRadio(radio_idx);
1472 }
1473 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1474}
1475
1476static void
1477wifi_BringDownInterfacesForRadio(int radio_idx)
1478{
1479 int bss_idx;
1480 int ap_idx;
1481 int band_idx;
1482 char cmd[MAX_BUF_SIZE] = {0};
1483 char config_file[MAX_BUF_SIZE] = {0};
1484 char ret_buf[MAX_BUF_SIZE]={'\0'};
1485
1486 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001487
developer8a3bbbf2023-03-15 17:47:23 +08001488 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radio_idx]);
1489 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1490
1491
developer17038e62023-03-02 14:43:43 +08001492 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1493}
1494
1495
1496static void
1497wifi_BringDownInterfaces(void)
1498{
1499 int radio_idx;
1500 int bss_idx;
1501 int ap_idx;
1502 int band_idx;
1503 char cmd[MAX_BUF_SIZE] = {0};
1504 char config_file[MAX_BUF_SIZE] = {0};
1505 char ret_buf[MAX_BUF_SIZE]={'\0'};
1506
1507 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1508 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1509 band_idx = radio_index_to_band(radio_idx);
1510 if (band_idx < 0) {
1511 break;
1512 }
1513 wifi_BringDownInterfacesForRadio(radio_idx);
1514 }
1515 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1516}
1517
developer47cc27a2023-05-17 23:09:58 +08001518static void wifi_psk_file_reset()
1519{
1520 char cmd[MAX_CMD_SIZE] = {0};
1521 char ret_buf[MAX_BUF_SIZE] = {0};
1522 char psk_file[MAX_CMD_SIZE]= {0};
1523 char vap_idx = 0;
1524
1525 for (vap_idx = 0; vap_idx < MAX_APS; vap_idx++) {
1526 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, vap_idx);
1527
1528 if (access(psk_file, F_OK) != 0) {
1529 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
1530 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1531 } else {
1532 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
1533 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1534 }
1535 }
1536}
1537
developer8a3bbbf2023-03-15 17:47:23 +08001538static void wifi_vap_status_reset()
1539{
1540 char cmd[MAX_CMD_SIZE] = {0};
1541 char ret_buf[MAX_BUF_SIZE] = {0};
1542 char radio_idx = 0;
1543 char bss_idx = 0;
developer8666b312023-03-24 14:05:31 +08001544
developer8a3bbbf2023-03-15 17:47:23 +08001545 if (access(VAP_STATUS_FILE, F_OK) != 0) {
1546 snprintf(cmd, MAX_CMD_SIZE, "touch %s", VAP_STATUS_FILE);
1547 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1548 } else {
1549 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", VAP_STATUS_FILE);
1550 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1551 }
1552
1553 memset(cmd, 0, MAX_CMD_SIZE);
1554 memset(ret_buf, 0, MAX_BUF_SIZE);
1555
1556 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
1557 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1558 snprintf(cmd, MAX_CMD_SIZE, "echo %s%d=0 >> %s", ext_prefix[radio_idx], bss_idx, VAP_STATUS_FILE);
1559 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1560 }
1561
1562}
developer17038e62023-03-02 14:43:43 +08001563
developer72fb0bb2023-01-11 09:46:29 +08001564// Initializes the wifi subsystem (all radios)
1565INT wifi_init() //RDKB
1566{
developer96b38512023-02-22 11:17:45 +08001567 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1568 //Not intitializing macfilter for Turris-Omnia Platform for now
1569 //macfilter_init();
developer17038e62023-03-02 14:43:43 +08001570 wifi_ParseProfile();
1571 wifi_PrepareDefaultHostapdConfigs();
developer47cc27a2023-05-17 23:09:58 +08001572 wifi_psk_file_reset();
developer17038e62023-03-02 14:43:43 +08001573 //system("/usr/sbin/iw reg set US");
1574 system("systemctl start hostapd.service");
1575 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001576
1577 wifi_vap_status_reset();
1578
developer17038e62023-03-02 14:43:43 +08001579 wifi_BringUpInterfaces();
developer96b38512023-02-22 11:17:45 +08001580
developer96b38512023-02-22 11:17:45 +08001581
1582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001583
1584 return RETURN_OK;
1585}
1586
1587/* wifi_reset() function */
1588/**
1589* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
developer69b61b02023-03-07 17:17:44 +08001590* Implementation specifics may dictate what is actualy reset since
developer72fb0bb2023-01-11 09:46:29 +08001591* different hardware implementations may have different requirements.
1592* Parameters : None
1593*
1594* @return The status of the operation.
1595* @retval RETURN_OK if successful.
1596* @retval RETURN_ERR if any error is detected
1597*
1598* @execution Synchronous.
1599* @sideeffect None.
1600*
1601* @note This function must not suspend and must not invoke any blocking system
1602* calls. It should probably just send a message to a driver event handler task.
1603*
1604*/
1605INT wifi_reset()
1606{
developer17038e62023-03-02 14:43:43 +08001607
1608 wifi_BringDownInterfaces();
1609 sleep(2);
1610
developer96b38512023-02-22 11:17:45 +08001611 //TODO: resets the wifi subsystem, deletes all APs
1612 system("systemctl stop hostapd.service");
1613 sleep(2);
developer17038e62023-03-02 14:43:43 +08001614
developer96b38512023-02-22 11:17:45 +08001615 system("systemctl start hostapd.service");
1616 sleep(5);
developer17038e62023-03-02 14:43:43 +08001617
1618 wifi_PrepareDefaultHostapdConfigs();
developer47cc27a2023-05-17 23:09:58 +08001619 wifi_psk_file_reset();
developer17038e62023-03-02 14:43:43 +08001620 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001621
1622 wifi_vap_status_reset();
1623
developer17038e62023-03-02 14:43:43 +08001624 wifi_BringUpInterfaces();
1625
developer72fb0bb2023-01-11 09:46:29 +08001626 return RETURN_OK;
1627}
1628
1629/* wifi_down() function */
1630/**
1631* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
developer69b61b02023-03-07 17:17:44 +08001632* Implementation specifics may dictate some functionality since
developer72fb0bb2023-01-11 09:46:29 +08001633* different hardware implementations may have different requirements.
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_down()
1649{
developer96b38512023-02-22 11:17:45 +08001650 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer17038e62023-03-02 14:43:43 +08001651 wifi_BringDownInterfaces();
1652 sleep(2);
1653
developer96b38512023-02-22 11:17:45 +08001654 system("systemctl stop hostapd.service");
1655 sleep(2);
developer72fb0bb2023-01-11 09:46:29 +08001656 return RETURN_OK;
1657}
1658
1659
1660/* wifi_createInitialConfigFiles() function */
1661/**
1662* @description This function creates wifi configuration files. The format
developer69b61b02023-03-07 17:17:44 +08001663* and content of these files are implementation dependent. This function call is
1664* used to trigger this task if necessary. Some implementations may not need this
1665* function. If an implementation does not need to create config files the function call can
developer72fb0bb2023-01-11 09:46:29 +08001666* do nothing and return RETURN_OK.
1667*
1668* @param None
1669*
1670* @return The status of the operation
1671* @retval RETURN_OK if successful
1672* @retval RETURN_ERR if any error is detected
1673*
1674* @execution Synchronous
1675* @sideeffect None
1676*
1677* @note This function must not suspend and must not invoke any blocking system
1678* calls. It should probably just send a message to a driver event handler task.
1679*
1680*/
1681INT wifi_createInitialConfigFiles()
1682{
1683 //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)
1684 return RETURN_OK;
1685}
1686
developer7e4a2a62023-04-06 19:56:03 +08001687/* outputs the country code to a max 64 character string */
developer72fb0bb2023-01-11 09:46:29 +08001688INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1689{
developer7e4a2a62023-04-06 19:56:03 +08001690 char interface_name[IF_NAME_SIZE] = {0};
1691 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer72fb0bb2023-01-11 09:46:29 +08001692
developer7e4a2a62023-04-06 19:56:03 +08001693 if (!output_string || (radioIndex >= MAX_NUM_RADIOS)) {
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 (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK) {
1699 printf("%s: get inf_name error!!!\n", __func__);
1700 return RETURN_ERR;
1701 }
1702
1703 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i %s status driver | grep country | cut -d '=' -f2 | tr -d '\\n'",
1704 interface_name);
1705 _syscmd(cmd, buf, sizeof(buf));
1706
1707 if(strlen(buf))
1708 snprintf(output_string, 64, "%s", buf);
1709 else
1710 return RETURN_ERR;
1711
1712 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001713}
1714
1715INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1716{
developer7e4a2a62023-04-06 19:56:03 +08001717 /*Set wifi config. Wait for wifi reset to apply*/
1718 char str[MAX_BUF_SIZE] = {0};
1719 char cmd[MAX_CMD_SIZE] = {0};
1720 struct params params;
1721 char config_file[MAX_BUF_SIZE] = {0};
1722 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08001723
developer7e4a2a62023-04-06 19:56:03 +08001724 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001725
developer7e4a2a62023-04-06 19:56:03 +08001726 if(NULL == CountryCode || strlen(CountryCode) >= 32 ) {
1727 printf("%s: input para error!!!\n", __func__);
1728 return RETURN_ERR;
1729 }
developer72fb0bb2023-01-11 09:46:29 +08001730
developer7e4a2a62023-04-06 19:56:03 +08001731 if (!strlen(CountryCode))
1732 strncpy(CountryCode, "US", sizeof("US")); /*default set the code to US*/
developer72fb0bb2023-01-11 09:46:29 +08001733
developer7e4a2a62023-04-06 19:56:03 +08001734 params.name = "country_code";
1735 params.value = CountryCode;
developer72fb0bb2023-01-11 09:46:29 +08001736
developer7e4a2a62023-04-06 19:56:03 +08001737 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1738 ret = wifi_hostapdWrite(config_file, &params, 1);
1739
1740 if (ret) {
1741 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n",
1742 __func__, ret);
1743 }
1744
1745 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1746
1747 if (ret) {
1748 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n",
1749 __func__, ret);
1750 }
1751
1752 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1753
1754 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001755}
1756
1757INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1758{
1759 char interface_name[16] = {0};
1760 char channel_util_file[64] = {0};
1761 char cmd[128] = {0};
1762 char buf[128] = {0};
1763 char line[128] = {0};
1764 char *param = NULL, *value = NULL;
1765 int read = 0;
1766 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1767 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1768 size_t len = 0;
1769 FILE *f = NULL;
1770
1771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1772
1773 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1774 return RETURN_ERR;
1775 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
1776 _syscmd(cmd, buf, sizeof(buf));
1777 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1778
1779 memset(cmd, 0, sizeof(cmd));
1780 memset(buf, 0, sizeof(buf));
1781 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
1782 if ((f = popen(cmd, "r")) == NULL) {
1783 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1784 return RETURN_ERR;
1785 }
1786
1787 read = getline(&line, &len, f);
1788 while (read != -1) {
1789 param = strtok(line, ":\t");
1790 value = strtok(NULL, " ");
1791 if(strstr(param, "frequency") != NULL) {
1792 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1793 }
1794 if(strstr(param, "noise") != NULL) {
1795 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1796 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1797 }
1798 if(strstr(param, "channel active time") != NULL) {
1799 ActiveTime = strtol(value, NULL, 10);
1800 }
1801 if(strstr(param, "channel busy time") != NULL) {
1802 BusyTime = strtol(value, NULL, 10);
1803 }
1804 if(strstr(param, "channel transmit time") != NULL) {
1805 TransmitTime = strtol(value, NULL, 10);
1806 }
1807 read = getline(&line, &len, f);
1808 }
1809 pclose(f);
1810
1811 // The file should store the last active, busy and transmit time
1812 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1813 f = fopen(channel_util_file, "r");
1814 if (f != NULL) {
1815 read = getline(&line, &len, f);
1816 preActiveTime = strtol(line, NULL, 10);
1817 read = getline(&line, &len, f);
1818 preBusyTime = strtol(line, NULL, 10);
1819 read = getline(&line, &len, f);
1820 preTransmitTime = strtol(line, NULL, 10);
1821 fclose(f);
1822 }
1823
1824 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1825 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1826
1827 f = fopen(channel_util_file, "w");
1828 if (f != NULL) {
1829 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1830 fclose(f);
1831 }
1832 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1833 return RETURN_OK;
1834}
1835
1836/**********************************************************************************
1837 *
1838 * Wifi radio level function prototypes
1839 *
1840**********************************************************************************/
1841
1842//Get the total number of radios in this wifi subsystem
1843INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1844{
1845 if (NULL == output)
1846 return RETURN_ERR;
1847 *output = MAX_NUM_RADIOS;
1848
1849 return RETURN_OK;
1850}
1851
developer69b61b02023-03-07 17:17:44 +08001852//Get the total number of SSID entries in this wifi subsystem
developer72fb0bb2023-01-11 09:46:29 +08001853INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1854{
1855 if (NULL == output)
1856 return RETURN_ERR;
1857 *output = MAX_APS;
1858
1859 return RETURN_OK;
1860}
1861
1862//Get the Radio enable config parameter
1863INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1864{
1865 char interface_name[16] = {0};
1866 char buf[128] = {0}, cmd[128] = {0};
1867
1868 if (NULL == output_bool)
1869 return RETURN_ERR;
1870
1871 *output_bool = FALSE;
1872 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
1873 return RETURN_ERR;
1874
1875 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1876 return RETURN_ERR;
1877 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1878 _syscmd(cmd, buf, sizeof(buf));
1879
1880 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1881 *output_bool = TRUE;
1882 return RETURN_OK;
1883}
1884
developere82c0ca2023-05-10 16:25:35 +08001885typedef long time_t;
1886static time_t radio_up_time[MAX_NUM_RADIOS];
1887
developer72fb0bb2023-01-11 09:46:29 +08001888INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1889{
1890 char interface_name[16] = {0};
1891 char cmd[MAX_CMD_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001892 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001893 int apIndex, ret;
developer69b61b02023-03-07 17:17:44 +08001894 int max_radio_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08001895 int phyId = 0;
1896
1897 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1898
1899 phyId = radio_index_to_phy(radioIndex);
1900
1901 wifi_getMaxRadioNumber(&max_radio_num);
1902
developer8a3bbbf2023-03-15 17:47:23 +08001903 if(enable == FALSE) {
developer47cc27a2023-05-17 23:09:58 +08001904
1905 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1906 return RETURN_ERR;
1907
1908 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08001909 _syscmd(cmd, buf, sizeof(buf));
developere82c0ca2023-05-10 16:25:35 +08001910 if(strncmp(buf, "OK", 2))
1911 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08001912 } else {
developere82c0ca2023-05-10 16:25:35 +08001913 for (apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
developer72fb0bb2023-01-11 09:46:29 +08001914 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1915 return RETURN_ERR;
1916
developer8a3bbbf2023-03-15 17:47:23 +08001917 memset(cmd, 0, MAX_CMD_SIZE);
1918 memset(buf, 0, MAX_BUF_SIZE);
1919
developer72fb0bb2023-01-11 09:46:29 +08001920 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
1921 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08001922
1923 if(*buf == '1') {
1924
1925 memset(cmd, 0, MAX_CMD_SIZE);
1926 memset(buf, 0, MAX_BUF_SIZE);
1927
developer72fb0bb2023-01-11 09:46:29 +08001928 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1929 phyId, apIndex);
1930 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08001931
developer72fb0bb2023-01-11 09:46:29 +08001932 }
1933 }
developere82c0ca2023-05-10 16:25:35 +08001934 time(&radio_up_time[radioIndex]);
developer72fb0bb2023-01-11 09:46:29 +08001935 }
1936
1937 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1938 return RETURN_OK;
1939}
1940
1941//Get the Radio enable status
1942INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1943{
1944 if (NULL == output_bool)
1945 return RETURN_ERR;
1946
1947 return wifi_getRadioEnable(radioIndex, output_bool);
1948}
1949
1950//Get the Radio Interface name from platform, eg "wlan0"
1951INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1952{
1953 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
1954 return RETURN_ERR;
1955 return wifi_GetInterfaceName(radioIndex, output_string);
1956}
1957
1958//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1959//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.
1960INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1961{
1962 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1963 // For max bit rate, we should always choose the best MCS
1964 char mode[64] = {0};
1965 char channel_bandwidth_str[64] = {0};
1966 char *tmp = NULL;
1967 UINT mode_map = 0;
1968 UINT num_subcarrier = 0;
1969 UINT code_bits = 0;
1970 float code_rate = 0; // use max code rate
1971 int NSS = 0;
1972 UINT Symbol_duration = 0;
developer69b61b02023-03-07 17:17:44 +08001973 UINT GI_duration = 0;
developer72fb0bb2023-01-11 09:46:29 +08001974 wifi_band band = band_invalid;
1975 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1976 BOOL enable = FALSE;
1977 float bit_rate = 0;
developera1255e42023-05-13 17:45:02 +08001978 int ant_bitmap = 0;
developer72fb0bb2023-01-11 09:46:29 +08001979
1980 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1981 if (NULL == output_string)
1982 return RETURN_ERR;
1983
1984 wifi_getRadioEnable(radioIndex, &enable);
1985 if (enable == FALSE) {
1986 snprintf(output_string, 64, "0 Mb/s");
1987 return RETURN_OK;
1988 }
1989
1990 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1991 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1992 return RETURN_ERR;
1993 }
1994
1995 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1996 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1997 return RETURN_ERR;
1998 }
1999
2000 if (gi == wifi_guard_interval_3200)
2001 GI_duration = 32;
2002 else if (gi == wifi_guard_interval_1600)
2003 GI_duration = 16;
2004 else if (gi == wifi_guard_interval_800)
2005 GI_duration = 8;
2006 else // auto, 400
2007 GI_duration = 4;
2008
2009 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
2010 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
2011 return RETURN_ERR;
2012 }
2013
2014 if (strstr(channel_bandwidth_str, "80+80") != NULL)
2015 strcpy(channel_bandwidth_str, "160");
2016
2017 if (mode_map & WIFI_MODE_AX) {
2018 if (strstr(channel_bandwidth_str, "160") != NULL)
2019 num_subcarrier = 1960;
2020 else if (strstr(channel_bandwidth_str, "80") != NULL)
2021 num_subcarrier = 980;
2022 else if (strstr(channel_bandwidth_str, "40") != NULL)
2023 num_subcarrier = 468;
2024 else if (strstr(channel_bandwidth_str, "20") != NULL)
2025 num_subcarrier = 234;
2026 code_bits = 10;
2027 code_rate = (float)5/6;
2028 Symbol_duration = 128;
developera1255e42023-05-13 17:45:02 +08002029 GI_duration = 8;/*HE no GI 400ns*/
developer72fb0bb2023-01-11 09:46:29 +08002030 } else if (mode_map & WIFI_MODE_AC) {
2031 if (strstr(channel_bandwidth_str, "160") != NULL)
2032 num_subcarrier = 468;
2033 else if (strstr(channel_bandwidth_str, "80") != NULL)
2034 num_subcarrier = 234;
2035 else if (strstr(channel_bandwidth_str, "40") != NULL)
2036 num_subcarrier = 108;
2037 else if (strstr(channel_bandwidth_str, "20") != NULL)
2038 num_subcarrier = 52;
2039 code_bits = 8;
2040 code_rate = (float)5/6;
2041 Symbol_duration = 32;
2042 } else if (mode_map & WIFI_MODE_N) {
2043 if (strstr(channel_bandwidth_str, "160") != NULL)
2044 num_subcarrier = 468;
2045 else if (strstr(channel_bandwidth_str, "80") != NULL)
2046 num_subcarrier = 234;
2047 else if (strstr(channel_bandwidth_str, "40") != NULL)
2048 num_subcarrier = 108;
2049 else if (strstr(channel_bandwidth_str, "20") != NULL)
2050 num_subcarrier = 52;
2051 code_bits = 6;
2052 code_rate = (float)3/4;
2053 Symbol_duration = 32;
2054 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
2055 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
2056 snprintf(output_string, 64, "65 Mb/s");
2057 return RETURN_OK;
2058 } else {
2059 snprintf(output_string, 64, "0 Mb/s");
2060 return RETURN_OK;
2061 }
2062
2063 // Spatial streams
developera1255e42023-05-13 17:45:02 +08002064 if (wifi_getRadioTxChainMask(radioIndex, &ant_bitmap) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +08002065 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
2066 return RETURN_ERR;
2067 }
developera1255e42023-05-13 17:45:02 +08002068 for (; ant_bitmap > 0; ant_bitmap >>= 1)
2069 NSS += ant_bitmap & 1;
developer72fb0bb2023-01-11 09:46:29 +08002070
2071 // multiple 10 is to align duration unit (0.1 us)
2072 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
2073 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
developera1255e42023-05-13 17:45:02 +08002074 WIFI_ENTRY_EXIT_DEBUG("%s:num_subcarrier=%d, code_bits=%d, code_rate=%.3f, nss=%d, symbol time=%u, %.1f Mb/s\n",
2075 __func__, num_subcarrier, code_bits, code_rate, NSS, Symbol_duration + GI_duration, bit_rate);
developer72fb0bb2023-01-11 09:46:29 +08002076 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2077
2078 return RETURN_OK;
2079}
2080#if 0
2081INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2082{
2083 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2084 char cmd[64];
2085 char buf[1024];
2086 int apIndex;
2087
developer69b61b02023-03-07 17:17:44 +08002088 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002089 return RETURN_ERR;
2090
2091 apIndex=(radioIndex==0)?0:1;
2092
2093 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
2094 _syscmd(cmd,buf, sizeof(buf));
2095
2096 snprintf(output_string, 64, "%s", buf);
2097 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2098 return RETURN_OK;
2099}
2100#endif
2101
2102
2103//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
2104//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.
2105INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
2106{
2107 wifi_band band = band_invalid;
2108
2109 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2110 if (NULL == output_string)
2111 return RETURN_ERR;
2112
2113 band = wifi_index_to_band(radioIndex);
2114
2115 memset(output_string, 0, 10);
2116 if (band == band_2_4)
2117 strcpy(output_string, "2.4GHz");
2118 else if (band == band_5)
2119 strcpy(output_string, "5GHz");
2120 else if (band == band_6)
2121 strcpy(output_string, "6GHz");
2122 else
2123 return RETURN_ERR;
2124 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2125
2126 return RETURN_OK;
2127#if 0
2128 char buf[MAX_BUF_SIZE]={'\0'};
2129 char str[MAX_BUF_SIZE]={'\0'};
2130 char cmd[MAX_CMD_SIZE]={'\0'};
2131 char *ch=NULL;
2132 char *ch2=NULL;
2133
2134 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2135 if (NULL == output_string)
2136 return RETURN_ERR;
2137
2138
2139 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2140
2141 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2142 {
2143 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2144 return RETURN_ERR;
2145 }
2146 ch=strchr(buf,'\n');
2147 *ch='\0';
2148 ch=strchr(buf,'=');
2149 if(ch==NULL)
2150 return RETURN_ERR;
2151
2152
2153 ch++;
2154
2155 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
2156 strcpy(buf,"0");
2157 if(strlen(ch) == 1)
2158 ch=strcat(buf,ch);
2159
2160
2161 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2162
2163 if(_syscmd(cmd,str,64) == RETURN_ERR)
2164 {
2165 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2166 return RETURN_ERR;
2167 }
2168
2169
2170 ch2=strchr(str,'\n');
2171 //replace \n with \0
2172 *ch2='\0';
2173 ch2=strchr(str,'=');
2174 if(ch2==NULL)
2175 {
2176 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2177 return RETURN_ERR;
2178 }
2179 else
2180 wifi_dbg_printf("%s",ch2+1);
2181
2182
2183 ch2++;
2184
2185
2186 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
2187
2188 memset(buf,'\0',sizeof(buf));
2189 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2190 {
2191 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2192 return RETURN_ERR;
2193 }
2194 if (strstr(buf,"2.4") != NULL )
2195 strcpy(output_string,"2.4GHz");
2196 else if(strstr(buf,"5.") != NULL )
2197 strcpy(output_string,"5GHz");
2198 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2199
2200 return RETURN_OK;
2201#endif
2202}
2203
2204//Get the frequency band at which the radio is operating, eg: "2.4GHz"
2205//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.
2206INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
2207{
2208 wifi_band band = band_invalid;
2209 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2210 if (NULL == output_string)
2211 return RETURN_ERR;
2212 band = wifi_index_to_band(radioIndex);
2213
developer69b61b02023-03-07 17:17:44 +08002214 if (band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08002215 snprintf(output_string, 64, "2.4GHz");
2216 else if (band == band_5)
developer69b61b02023-03-07 17:17:44 +08002217 snprintf(output_string, 64, "5GHz");
developer72fb0bb2023-01-11 09:46:29 +08002218 else if (band == band_6)
2219 snprintf(output_string, 64, "6GHz");
2220
2221 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2222
2223 return RETURN_OK;
2224#if 0
2225 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2226 char buf[MAX_BUF_SIZE]={'\0'};
2227 char str[MAX_BUF_SIZE]={'\0'};
2228 char cmd[MAX_CMD_SIZE]={'\0'};
2229 char *ch=NULL;
2230 char *ch2=NULL;
2231 char ch1[5]="0";
2232
2233 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2234
2235 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2236 {
2237 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2238 return RETURN_ERR;
2239 }
2240
2241 ch=strchr(buf,'\n');
2242 *ch='\0';
2243 ch=strchr(buf,'=');
2244 if(ch==NULL)
2245 return RETURN_ERR;
2246 ch++;
2247
2248 if(strlen(ch)==1)
2249 {
2250 strcat(ch1,ch);
2251
2252 }
2253 else
2254 {
2255 strcpy(ch1,ch);
2256 }
2257
2258
2259
2260 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2261 if(_syscmd(cmd,str,64) == RETURN_ERR)
2262 {
2263 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2264 return RETURN_ERR;
2265 }
2266
2267
2268 ch2=strchr(str,'\n');
2269 //replace \n with \0
2270 *ch2='\0';
2271 ch2=strchr(str,'=');
2272 if(ch2==NULL)
2273 {
2274 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2275 return RETURN_ERR;
2276 }
2277 else
2278 wifi_dbg_printf("%s",ch2+1);
2279 ch2++;
2280
2281
2282 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
2283 memset(buf,'\0',sizeof(buf));
2284 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2285 {
2286 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2287 return RETURN_ERR;
2288 }
2289
2290
2291 if(strstr(buf,"2.4")!=NULL)
2292 {
2293 strcpy(output_string,"2.4GHz");
2294 }
2295 if(strstr(buf,"5.")!=NULL)
2296 {
2297 strcpy(output_string,"5GHz");
2298 }
2299 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2300 return RETURN_OK;
2301#endif
2302}
2303
2304//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
2305//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.
2306INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
2307{
2308 char cmd[128]={0};
2309 char buf[128]={0};
2310 char temp_output[128] = {0};
2311 wifi_band band;
2312 int phyId = 0;
2313
2314 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002315 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002316 return RETURN_ERR;
2317
2318 band = wifi_index_to_band(radioIndex);
2319 if (band == band_2_4) {
2320 strcat(temp_output, "b,g,");
2321 } else if (band == band_5) {
2322 strcat(temp_output, "a,");
2323 }
2324 phyId = radio_index_to_phy(radioIndex);
2325 // ht capabilities
2326 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);
2327 _syscmd(cmd, buf, sizeof(buf));
2328 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
2329 strcat(temp_output, "n,");
2330 }
2331
2332 // vht capabilities
2333 if (band == band_5) {
2334 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
2335 _syscmd(cmd, buf, sizeof(buf));
2336 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
2337 strcat(temp_output, "ac,");
2338 }
2339 }
2340
2341 // he capabilities
2342 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);
2343 _syscmd(cmd, buf, sizeof(buf));
2344 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2345 strcat(temp_output, "ax,");
2346 }
2347
developere82c0ca2023-05-10 16:25:35 +08002348 // eht capabilities
2349 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);
2350 _syscmd(cmd, buf, sizeof(buf));
2351 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2352 strcat(temp_output, "be,");
2353 }
2354
developer72fb0bb2023-01-11 09:46:29 +08002355 // Remove the last comma
2356 if (strlen(temp_output) != 0)
2357 temp_output[strlen(temp_output)-1] = '\0';
2358 strncpy(output_string, temp_output, strlen(temp_output));
2359 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2360 return RETURN_OK;
2361}
2362
2363//Get the radio operating mode, and pure mode flag. eg: "ac"
2364//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.
2365INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
2366{
2367 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2368 if (NULL == output_string)
2369 return RETURN_ERR;
2370
2371 if (radioIndex == 0) {
2372 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
2373 *gOnly = FALSE;
2374 *nOnly = TRUE;
2375 *acOnly = FALSE;
2376 } else {
2377 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
2378 *gOnly = FALSE;
2379 *nOnly = FALSE;
2380 *acOnly = FALSE;
2381 }
2382 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2383
2384 return RETURN_OK;
2385#if 0
2386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2387 char buf[64] = {0};
2388 char config_file[MAX_BUF_SIZE] = {0};
2389
developer69b61b02023-03-07 17:17:44 +08002390 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
developer72fb0bb2023-01-11 09:46:29 +08002391 return RETURN_ERR;
2392
2393 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2394 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
2395
2396 wifi_dbg_printf("\nhw_mode=%s\n",buf);
developer69b61b02023-03-07 17:17:44 +08002397 if (strlen(buf) == 0)
developer72fb0bb2023-01-11 09:46:29 +08002398 {
2399 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
2400 return RETURN_ERR;
2401 }
2402 if(strcmp(buf,"g")==0)
2403 {
2404 wifi_dbg_printf("\nG\n");
2405 *gOnly=TRUE;
2406 *nOnly=FALSE;
2407 *acOnly=FALSE;
2408 }
2409 else if(strcmp(buf,"n")==0)
2410 {
2411 wifi_dbg_printf("\nN\n");
2412 *gOnly=FALSE;
2413 *nOnly=TRUE;
2414 *acOnly=FALSE;
2415 }
2416 else if(strcmp(buf,"ac")==0)
2417 {
2418 wifi_dbg_printf("\nac\n");
2419 *gOnly=FALSE;
2420 *nOnly=FALSE;
2421 *acOnly=TRUE;
2422 }
2423 /* hostapd-5G.conf has "a" as hw_mode */
2424 else if(strcmp(buf,"a")==0)
2425 {
2426 wifi_dbg_printf("\na\n");
2427 *gOnly=FALSE;
2428 *nOnly=FALSE;
2429 *acOnly=FALSE;
2430 }
2431 else
2432 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
2433
2434 //for a,n mode
2435 if(radioIndex == 1)
2436 {
2437 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
2438 if(strcmp(buf,"1")==0)
2439 {
2440 strncpy(output_string, "n", 1);
2441 *nOnly=FALSE;
2442 }
2443 }
2444
2445 wifi_dbg_printf("\nReturning from getRadioStandard\n");
2446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2447 return RETURN_OK;
2448#endif
2449}
2450
developer0f10c772023-05-16 21:43:39 +08002451enum WIFI_MODE {
2452 WMODE_INVALID = 0,
2453 WMODE_A = 1 << 0,
2454 WMODE_B = 1 << 1,
2455 WMODE_G = 1 << 2,
2456 WMODE_GN = 1 << 3,
2457 WMODE_AN = 1 << 4,
2458 WMODE_AC = 1 << 5,
2459 WMODE_AX_24G = 1 << 6,
2460 WMODE_AX_5G = 1 << 7,
2461 WMODE_AX_6G = 1 << 8,
2462 WMODE_BE_24G = 1 << 9,
2463 WMODE_BE_5G = 1 << 10,
2464 WMODE_BE_6G = 1 << 11,
2465 /*
2466 * total types of supported wireless mode,
2467 * add this value once yow add new type
2468 */
2469 WMODE_COMP = 12,
2470};
2471
2472#define RADIO_MODE_LEN 32
developer72fb0bb2023-01-11 09:46:29 +08002473INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
2474{
developer0f10c772023-05-16 21:43:39 +08002475 char cmd[MAX_CMD_SIZE] = {0};
2476 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002477 wifi_band band;
developer0f10c772023-05-16 21:43:39 +08002478 unsigned int phymode;
2479 unsigned char radio_mode_tem_len;
2480 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002481
2482 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2483 if(NULL == output_string || NULL == pureMode)
2484 return RETURN_ERR;
2485
developer0f10c772023-05-16 21:43:39 +08002486 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2487 return RETURN_ERR;
2488
2489 snprintf(cmd, sizeof(cmd), "mwctl %s dump radio_info | grep 'phymode' | cut -d ' ' -f2", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08002490 _syscmd(cmd, buf, sizeof(buf));
2491
developer0f10c772023-05-16 21:43:39 +08002492 phymode = strtoul(buf, NULL, 10);
2493 band = wifi_index_to_band(radioIndex);
2494
2495 // puremode is a bit map
developer72fb0bb2023-01-11 09:46:29 +08002496 *pureMode = 0;
developer0f10c772023-05-16 21:43:39 +08002497 memset(output_string, 0, RADIO_MODE_LEN);
2498
2499 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2500
2501 switch (band) {
2502 case band_2_4:
2503 if (phymode & WMODE_B) {
2504 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "b,");
2505 *pureMode |= WIFI_MODE_B;
2506 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2507 }
2508 if (phymode & WMODE_G) {
2509 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "g,");
2510 *pureMode |= WIFI_MODE_G;
2511 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2512 }
2513 if (phymode & WMODE_GN) {
2514 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
2515 *pureMode |= WIFI_MODE_N;
2516 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2517 }
2518 if (phymode & WMODE_AX_24G) {
2519 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
2520 *pureMode |= WIFI_MODE_AX;
2521 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2522 }
2523 if (phymode & WMODE_BE_24G) {
2524 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
2525 *pureMode |= WIFI_MODE_BE;
2526 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2527 }
2528 break;
2529 case band_5:
2530 if (phymode & WMODE_A) {
2531 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "a,");
2532 *pureMode |= WIFI_MODE_A;
2533 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2534 }
2535 if (phymode & WMODE_AN) {
2536 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
2537 *pureMode |= WIFI_MODE_N;
2538 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2539 }
2540 if (phymode & WMODE_AC) {
2541 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ac,");
2542 *pureMode |= WIFI_MODE_AC;
2543 }
2544 if (phymode & WMODE_AX_5G) {
2545 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
2546 *pureMode |= WIFI_MODE_AX;
2547 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2548 }
2549 if (phymode & WMODE_BE_5G) {
2550 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
2551 *pureMode |= WIFI_MODE_BE;
2552 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2553 }
2554 break;
2555 case band_6:
2556 if (phymode & WMODE_AX_6G) {
2557 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
2558 *pureMode |= WIFI_MODE_AX;
2559 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2560 }
2561 if (phymode & WMODE_BE_6G) {
2562 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
2563 *pureMode |= WIFI_MODE_BE;
2564 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2565 }
2566 break;
2567 default:
2568 fprintf(stderr, "%s band_idx invalid\n", __func__);
2569 break;
2570 }
2571
2572 /* Remove the last comma */
2573 if (strlen(output_string) != 0)
2574 output_string[strlen(output_string)-1] = '\0';
developer72fb0bb2023-01-11 09:46:29 +08002575
2576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2577 return RETURN_OK;
2578}
2579
2580// Set the radio operating mode, and pure mode flag.
2581INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2582{
developer69b61b02023-03-07 17:17:44 +08002583 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002584 if (strcmp (channelMode,"11A") == 0)
2585 {
2586 writeBandWidth(radioIndex,"20MHz");
2587 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2588 printf("\nChannel Mode is 802.11a (5GHz)\n");
2589 }
2590 else if (strcmp (channelMode,"11NAHT20") == 0)
2591 {
2592 writeBandWidth(radioIndex,"20MHz");
2593 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2594 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2595 }
2596 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2597 {
2598 writeBandWidth(radioIndex,"40MHz");
2599 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2600 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2601 }
2602 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2603 {
2604 writeBandWidth(radioIndex,"40MHz");
2605 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2606 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2607 }
2608 else if (strcmp (channelMode,"11ACVHT20") == 0)
2609 {
2610 writeBandWidth(radioIndex,"20MHz");
2611 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2612 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2613 }
2614 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2615 {
2616 writeBandWidth(radioIndex,"40MHz");
2617 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2618 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2619 }
2620 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2621 {
2622 writeBandWidth(radioIndex,"40MHz");
2623 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2624 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2625 }
2626 else if (strcmp (channelMode,"11ACVHT80") == 0)
2627 {
2628 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2629 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2630 }
2631 else if (strcmp (channelMode,"11ACVHT160") == 0)
2632 {
2633 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2634 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
developer69b61b02023-03-07 17:17:44 +08002635 }
developer72fb0bb2023-01-11 09:46:29 +08002636 else if (strcmp (channelMode,"11B") == 0)
2637 {
2638 writeBandWidth(radioIndex,"20MHz");
2639 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2640 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2641 }
2642 else if (strcmp (channelMode,"11G") == 0)
2643 {
2644 writeBandWidth(radioIndex,"20MHz");
2645 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2646 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2647 }
2648 else if (strcmp (channelMode,"11NGHT20") == 0)
2649 {
2650 writeBandWidth(radioIndex,"20MHz");
2651 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2652 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2653 }
2654 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2655 {
2656 writeBandWidth(radioIndex,"40MHz");
2657 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2658 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2659 }
2660 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2661 {
2662 writeBandWidth(radioIndex,"40MHz");
2663 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2664 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2665 }
developer69b61b02023-03-07 17:17:44 +08002666 else
developer72fb0bb2023-01-11 09:46:29 +08002667 {
2668 return RETURN_ERR;
2669 }
2670 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2671
2672 return RETURN_OK;
2673}
2674
developer0f10c772023-05-16 21:43:39 +08002675typedef enum _RT_802_11_PHY_MODE {
2676 PHY_11BG_MIXED = 0,
2677 PHY_11B = 1,
2678 PHY_11A = 2,
2679 PHY_11ABG_MIXED = 3,
2680 PHY_11G = 4,
2681 PHY_11ABGN_MIXED = 5, /* both band 5 */
2682 PHY_11N_2_4G = 6, /* 11n-only with 2.4G band 6 */
2683 PHY_11GN_MIXED = 7, /* 2.4G band 7 */
2684 PHY_11AN_MIXED = 8, /* 5G band 8 */
2685 PHY_11BGN_MIXED = 9, /* if check 802.11b. 9 */
2686 PHY_11AGN_MIXED = 10, /* if check 802.11b. 10 */
2687 PHY_11N_5G = 11, /* 11n-only with 5G band 11 */
2688 PHY_11VHT_N_ABG_MIXED = 12, /* 12 -> AC/A/AN/B/G/GN mixed */
2689 PHY_11VHT_N_AG_MIXED = 13, /* 13 -> AC/A/AN/G/GN mixed */
2690 PHY_11VHT_N_A_MIXED = 14, /* 14 -> AC/AN/A mixed in 5G band */
2691 PHY_11VHT_N_MIXED = 15, /* 15 -> AC/AN mixed in 5G band */
2692 PHY_11AX_24G = 16,
2693 PHY_11AX_5G = 17,
2694 PHY_11AX_6G = 18,
2695 PHY_11AX_24G_6G = 19,
2696 PHY_11AX_5G_6G = 20,
2697 PHY_11AX_24G_5G_6G = 21,
2698 PHY_11BE_24G = 22,
2699 PHY_11BE_5G = 23,
2700 PHY_11BE_6G = 24,
2701 PHY_11BE_24G_6G = 25,
2702 PHY_11BE_5G_6G = 26,
2703 PHY_11BE_24G_5G_6G = 27,
2704 PHY_MODE_MAX,
2705} RT_802_11_PHY_MODE;
2706
2707unsigned int puremode_to_wireless_mode(INT radioIndex, UINT pureMode)
2708{
2709 int band_idx = 0;
2710 unsigned int wireless_mode = PHY_MODE_MAX;
2711
2712 band_idx = radio_index_to_band(radioIndex);
2713
2714 switch (band_idx) {
2715 case band_2_4:
2716 if (pureMode == (WIFI_MODE_G | WIFI_MODE_N))
2717 wireless_mode = PHY_11GN_MIXED;
2718 if (pureMode == (WIFI_MODE_B | WIFI_MODE_G | WIFI_MODE_N))
2719 wireless_mode = PHY_11BGN_MIXED;
2720 if (pureMode & WIFI_MODE_AX)
2721 wireless_mode = PHY_11AX_24G;
2722 if (pureMode & WIFI_MODE_BE)
2723 wireless_mode = PHY_11BE_24G;
2724 break;
2725 case band_5:
2726 if (pureMode == WIFI_MODE_N)
2727 wireless_mode = PHY_11N_5G;
2728 if ((pureMode == WIFI_MODE_AC) || (pureMode == (WIFI_MODE_N | WIFI_MODE_AC)))
2729 wireless_mode = PHY_11VHT_N_MIXED;
2730 if (pureMode == (WIFI_MODE_A | WIFI_MODE_N | WIFI_MODE_AC))
2731 wireless_mode = PHY_11VHT_N_A_MIXED;
2732 if (pureMode & WIFI_MODE_AX)
2733 wireless_mode = PHY_11AX_5G;
2734 if (pureMode & WIFI_MODE_BE)
2735 wireless_mode = PHY_11BE_5G;
2736 break;
2737 case band_6:
2738 if (pureMode & WIFI_MODE_AX)
2739 wireless_mode = PHY_11AX_6G;
2740 if (pureMode & WIFI_MODE_BE)
2741 wireless_mode = PHY_11BE_6G;
2742 break;
2743 default:
2744 fprintf(stderr, "%s band_idx invalid\n", __func__);
2745 break;
2746 }
2747
2748 return wireless_mode;
2749}
2750
developer72fb0bb2023-01-11 09:46:29 +08002751// Set the radio operating mode, and pure mode flag.
2752INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2753{
developer0f10c772023-05-16 21:43:39 +08002754 unsigned int wireless_mode = PHY_MODE_MAX;
developer69b61b02023-03-07 17:17:44 +08002755
developer0f10c772023-05-16 21:43:39 +08002756 char interface_name[IF_NAME_SIZE] = {0};
2757 char cmd[MAX_CMD_SIZE] = {0};
2758 char buf[MAX_BUF_SIZE] = {0};
2759 int i;
developer72fb0bb2023-01-11 09:46:29 +08002760
developer0f10c772023-05-16 21:43:39 +08002761 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002762
developer0f10c772023-05-16 21:43:39 +08002763 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
developer72fb0bb2023-01-11 09:46:29 +08002764
developer0f10c772023-05-16 21:43:39 +08002765 if (wireless_mode == PHY_MODE_MAX) {
2766 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
2767 return RETURN_ERR;
2768 }
developer72fb0bb2023-01-11 09:46:29 +08002769
developer0f10c772023-05-16 21:43:39 +08002770 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2771 return RETURN_ERR;
2772 snprintf(cmd, sizeof(cmd), "mwctl %s set phymode %d", interface_name, wireless_mode);
2773 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08002774
developer0f10c772023-05-16 21:43:39 +08002775 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2776
2777 return RETURN_OK;
2778}
2779
2780INT wifi_setRadioMode_by_dat(INT radioIndex, UINT pureMode)
2781{
2782 unsigned int wireless_mode = PHY_MODE_MAX;
2783 char interface_name[IF_NAME_SIZE] = {0};
2784 char cmd[MAX_CMD_SIZE] = {0};
2785 char buf[MAX_BUF_SIZE] = {0};
2786 int i;
2787 char dat_file[MAX_BUF_SIZE] = {0};
2788 struct params params={0};
2789
2790 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, pureMode, __LINE__);
2791
2792 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
2793
2794 if (wireless_mode == PHY_MODE_MAX) {
2795 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
2796 return RETURN_ERR;
2797 }
2798
2799 params.name = "WirelessMode";
2800 snprintf(buf, sizeof(buf), "%d", wireless_mode);
2801 params.value = buf;
2802
2803 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
2804 wifi_datfileWrite(dat_file, &params, 1);
2805
developer72fb0bb2023-01-11 09:46:29 +08002806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2807
2808 return RETURN_OK;
2809}
2810
2811INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2812
2813 char config_file[64] = {0};
2814 char buf[64] = {0};
2815 struct params params = {0};
2816 wifi_band band = band_invalid;
2817
2818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2819
2820 band = wifi_index_to_band(radioIndex);
2821
2822 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
2823 return RETURN_ERR;
2824 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2825 return RETURN_ERR;
2826 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2827 return RETURN_ERR;
2828
2829 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2830 params.name = "hw_mode";
2831 params.value = hw_mode;
2832 wifi_hostapdWrite(config_file, &params, 1);
2833 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2834
2835 if (band == band_2_4) {
2836 if (strncmp(hw_mode, "b", 1) == 0) {
2837 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2838 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2839 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2840 snprintf(buf, sizeof(buf), "%s", "1,2");
2841 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2842 } else {
2843 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2844
2845 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2846 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2847 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2848 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2849 }
2850 }
2851
2852 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2853 return RETURN_OK;
2854}
2855
2856INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2857{
2858 char config_file[64] = {0};
2859 struct params params = {0};
2860 wifi_band band = band_invalid;
2861
2862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2863
2864 band = wifi_index_to_band(radioIndex);
2865 if (band != band_2_4)
2866 return RETURN_OK;
2867
2868 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2869 params.name = "noscan";
2870 params.value = noscan;
2871 wifi_hostapdWrite(config_file, &params, 1);
2872 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2873
2874 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2875 return RETURN_OK;
2876}
2877
2878//Get the list of supported channel. eg: "1-11"
2879//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.
2880INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2881{
2882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002883 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002884 return RETURN_ERR;
2885 char cmd[256] = {0};
2886 char buf[128] = {0};
2887 BOOL dfs_enable = false;
2888 int phyId = 0;
2889
2890 // Parse possible channel number and separate them with commas.
2891 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2892 phyId = radio_index_to_phy(radioIndex);
2893 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
2894 if (dfs_enable)
2895 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 +08002896 else
developer72fb0bb2023-01-11 09:46:29 +08002897 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);
2898
2899 _syscmd(cmd,buf,sizeof(buf));
2900 strncpy(output_string, buf, sizeof(buf));
2901
2902 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2903 return RETURN_OK;
2904}
developerd1824452023-05-18 12:30:04 +08002905//Getting current radio extension channel
2906INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2907{
2908 CHAR buf[150] = {0};
2909 CHAR cmd[150] = {0};
2910
2911 wifi_datfileRead(file, "HT_EXTCHA", buf, sizeof(buf));
2912 if (strncmp(buf, "0", 1) == 0) //bewlow
2913 strcpy(Value,"BelowControlChannel");
2914 if(strncmp(buf, "1", 1) == 0) //above
2915 strcpy(Value,"AboveControlChannel");
2916 return RETURN_OK;
2917}
developerf6a87542023-05-16 15:47:28 +08002918
developer72fb0bb2023-01-11 09:46:29 +08002919//Get the list for used channel. eg: "1,6,9,11"
2920//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.
2921INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2922{
2923 char interface_name[16] = {0};
2924 char cmd[128] = {0};
2925 char buf[128] = {0};
2926 char config_file[64] = {0};
2927 int channel = 0;
2928 int freq = 0;
2929 int bandwidth = 0;
2930 int center_freq = 0;
2931 int center_channel = 0;
2932 int channel_delta = 0;
2933 wifi_band band = band_invalid;
2934
2935 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2936
2937 if (NULL == output_string)
2938 return RETURN_ERR;
2939
2940 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2941 return RETURN_ERR;
2942 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
2943 _syscmd(cmd, buf, sizeof(buf));
2944 if (strlen(buf) == 0) {
2945 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2946 return RETURN_ERR;
2947 }
2948 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2949
2950 if (bandwidth == 20) {
2951 snprintf(output_string, 256, "%d", channel);
2952 return RETURN_OK;
2953 }
2954
2955 center_channel = ieee80211_frequency_to_channel(center_freq);
2956
2957 band = wifi_index_to_band(radioIndex);
2958 if (band == band_2_4 && bandwidth == 40) {
developerd1824452023-05-18 12:30:04 +08002959 sprintf(config_file, "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08002960 memset(buf, 0, sizeof(buf));
2961 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2962
2963 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
2964 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2965 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
2966 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2967 } else {
2968 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2969 return RETURN_ERR;
2970 }
2971 } else if (band == band_5 || band == band_6){
2972 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
developerd1824452023-05-18 12:30:04 +08002973 // 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 +08002974 channel_delta = (bandwidth-20)/10;
developerd1824452023-05-18 12:30:04 +08002975 memset(output_string, 0, 256);
2976 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
2977 // If i is not the last channel, we add a comma.
2978 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
2979 strncat(output_string, buf, strlen(buf));
2980 }
developer72fb0bb2023-01-11 09:46:29 +08002981 } else
2982 return RETURN_ERR;
2983
2984 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2985 return RETURN_OK;
2986}
2987
developer69b61b02023-03-07 17:17:44 +08002988//Get the running channel number
developerd1824452023-05-18 12:30:04 +08002989INT wifi_getRadioChannel(INT radioIndex, ULONG *output_ulong) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08002990{
2991 char channel_str[16] = {0};
2992 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +08002993 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08002994
2995 if (output_ulong == NULL)
2996 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08002997 band = wifi_index_to_band(radioIndex);
2998 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
2999 wifi_datfileRead(config_file, "Channel", channel_str, sizeof(channel_str));
developer72fb0bb2023-01-11 09:46:29 +08003000
3001 *output_ulong = strtoul(channel_str, NULL, 10);
3002
3003 return RETURN_OK;
3004}
3005
3006
3007INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
3008{
3009 char cmd[1024] = {0}, buf[5] = {0};
3010 char interface_name[16] = {0};
3011
3012 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3013 if (NULL == output_ulong)
3014 return RETURN_ERR;
3015
3016 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
3017 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
3018 return RETURN_ERR;
3019 _syscmd(cmd,buf,sizeof(buf));
3020 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
3021 if (*output_ulong == 0) {
3022 return RETURN_ERR;
3023 }
3024
3025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3026 return RETURN_OK;
3027}
3028
3029//Storing the previous channel value
3030INT wifi_storeprevchanval(INT radioIndex)
3031{
3032 char buf[256] = {0};
3033 char output[4]={'\0'};
3034 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08003035 wifi_band band = band_invalid;
3036
3037 band = wifi_index_to_band(radioIndex);
3038 if (band == band_invalid) {
3039 return RETURN_ERR;
3040 wifi_dbg_printf("[%s]: Invalid radio index", __func__);
3041 }
3042 snprintf(config_file, sizeof(config_file), "%s%d.dat",LOGAN_DAT_FILE, band);
3043 wifi_datfileRead(config_file, "Channel", output, sizeof(output));
3044
3045 if(band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08003046 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003047 else if(band == band_5)
developer72fb0bb2023-01-11 09:46:29 +08003048 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003049 else
3050 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval6G_AutoChannelEnable");
developer72fb0bb2023-01-11 09:46:29 +08003051 system(buf);
3052 Radio_flag = FALSE;
3053 return RETURN_OK;
3054}
3055
3056//Set the running channel number
3057INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
3058{
3059 // We only write hostapd config here
3060 char str_channel[8]={0};
3061 char *list_channel;
3062 char config_file[128] = {0};
3063 char possible_channels[256] = {0};
developerd1824452023-05-18 12:30:04 +08003064 char config_file_dat[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003065 int max_radio_num = 0;
3066 struct params list = {0};
developerd1824452023-05-18 12:30:04 +08003067 struct params dat = {0};
3068 struct params acs = {0};
3069 wifi_band band = band_invalid;
3070 bool acs_channel = false;
developer72fb0bb2023-01-11 09:46:29 +08003071
3072 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3073
developerd1824452023-05-18 12:30:04 +08003074 if (channel == 0)
3075 acs_channel = true;
developer72fb0bb2023-01-11 09:46:29 +08003076 // Check valid
3077 sprintf(str_channel, "%lu", channel);
3078
developerd1824452023-05-18 12:30:04 +08003079
developer72fb0bb2023-01-11 09:46:29 +08003080 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
3081 list_channel = strtok(possible_channels, ",");
3082 while(true)
3083 {
3084 if(list_channel == NULL) { // input not in the list
3085 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
3086 return RETURN_ERR;
3087 }
3088 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
3089 break;
3090 list_channel = strtok(NULL, ",");
3091 }
developerd1824452023-05-18 12:30:04 +08003092 /*
developer72fb0bb2023-01-11 09:46:29 +08003093 list.name = "channel";
3094 list.value = str_channel;
3095 wifi_getMaxRadioNumber(&max_radio_num);
3096 for(int i=0; i<=MAX_APS/max_radio_num;i++)
3097 {
3098 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
3099 wifi_hostapdWrite(config_file, &list, 1);
3100 }
developerd1824452023-05-18 12:30:04 +08003101 */
3102 dat.name = "Channel";
3103 dat.value = str_channel;
3104 band = wifi_index_to_band(radioIndex);
3105 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3106 wifi_datfileWrite(config_file_dat, &dat, 1);
3107 if (acs_channel == true) {
3108 acs.name = "AutoChannelSelect";
3109 acs.value = "3";
3110 } else {
3111 acs.name = "AutoChannelSelect";
3112 acs.value = "0";
3113 }
3114 wifi_datfileWrite(config_file_dat, &acs, 1);
developer72fb0bb2023-01-11 09:46:29 +08003115 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3116 return RETURN_OK;
3117}
3118
3119INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
3120{
3121 struct params list[2];
3122 char str_idx[16];
3123 char config_file[64];
3124 int max_num_radios = 0;
3125 wifi_band band = band_invalid;
3126
3127 band = wifi_index_to_band(radioIndex);
3128 if (band == band_2_4)
3129 return RETURN_OK;
3130
3131 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
3132 list[0].name = "vht_oper_centr_freq_seg0_idx";
3133 list[0].value = str_idx;
3134 list[1].name = "he_oper_centr_freq_seg0_idx";
3135 list[1].value = str_idx;
3136
3137 wifi_getMaxRadioNumber(&max_num_radios);
3138 for(int i=0; i<=MAX_APS/max_num_radios; i++)
3139 {
3140 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
3141 if (band == band_6)
3142 wifi_hostapdWrite(config_file, &list[1], 1);
3143 else
3144 wifi_hostapdWrite(config_file, list, 2);
3145 }
3146
3147 return RETURN_OK;
3148}
3149
3150//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
3151//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
3152INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
3153{
3154 //Set to wifi config only. Wait for wifi reset to apply.
3155 char buf[256] = {0};
3156 char str_channel[256] = {0};
3157 int count = 0;
3158 ULONG Value = 0;
3159 FILE *fp = NULL;
3160 if(enable == TRUE)
3161 {
3162 wifi_setRadioChannel(radioIndex,Value);
3163 }
3164 return RETURN_OK;
3165}
3166
3167INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
3168{
3169 if (output_bool == NULL)
3170 return RETURN_ERR;
3171
3172 *output_bool = TRUE;
3173
3174 return RETURN_OK;
3175}
3176
3177INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
3178{
developer69b61b02023-03-07 17:17:44 +08003179 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003180 return RETURN_ERR;
3181 *output_bool=FALSE;
3182 return RETURN_OK;
3183}
3184
3185INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
3186{
developer69b61b02023-03-07 17:17:44 +08003187 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003188 return RETURN_ERR;
3189 *output_bool=FALSE;
3190 return RETURN_OK;
3191}
3192
3193INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
3194{
3195 //Set to wifi config only. Wait for wifi reset to apply.
3196 return RETURN_OK;
3197}
3198
3199INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
3200{
3201 return RETURN_OK;
3202}
3203
3204INT wifi_factoryResetAP(int apIndex)
3205{
developer47cc27a2023-05-17 23:09:58 +08003206 char ap_config_file[MAX_CMD_SIZE] = {0};
3207 char cmd[MAX_CMD_SIZE] = {0};
3208 char ret_buf[MAX_BUF_SIZE] = {0};
3209 int radio_idx = 0;
3210 int bss_idx = 0;
3211 char ssid[32] = {0};
3212 char interface[IF_NAME_SIZE] = {0};
3213 char psk_file[MAX_CMD_SIZE] = {0};
3214 struct params params[3] = {0};
3215 char *band_str[3] = {"2G", "5G", "6G"};
developer72fb0bb2023-01-11 09:46:29 +08003216
3217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3218
developer47cc27a2023-05-17 23:09:58 +08003219 /*del old config file*/
3220 snprintf(ap_config_file, MAX_CMD_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
3221 snprintf(cmd, MAX_CMD_SIZE, "rm %s", ap_config_file);
3222 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003223
developer47cc27a2023-05-17 23:09:58 +08003224 memset(cmd, 0, sizeof(cmd));
3225 memset(ret_buf, 0, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003226
developer47cc27a2023-05-17 23:09:58 +08003227 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
3228
3229 /*prepare new config file*/
3230 snprintf(cmd, sizeof(cmd), "cp /etc/hostapd-%s.conf %s", band_str[radio_idx], ap_config_file);
3231 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3232
3233 if (radio_idx == band_2_4) {
3234 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
3235 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
3236 } else if (radio_idx == band_5) {
3237 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
3238 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
3239 } else if (radio_idx == band_6) {
3240 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
3241 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
3242 }
3243
3244 /* fix wpa_psk_file path */
3245 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", apIndex);
3246
3247 params[0].name = "ssid";
3248 params[0].value = ssid;
3249 params[1].name = "interface";
3250 params[1].value = interface;
3251 params[2].name = "wpa_psk_file";
3252 params[2].value = psk_file;
3253
3254 wifi_hostapdWrite(ap_config_file, params, 3);
3255
3256 /*clear psk file*/
3257 memset(cmd, 0, sizeof(cmd));
3258 memset(ret_buf, 0, sizeof(ret_buf));
3259
3260 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, apIndex);
3261
3262 if (access(psk_file, F_OK) != 0) {
3263 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
3264 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3265 } else {
3266 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
3267 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3268 }
3269
3270 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3271
3272 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003273}
3274
3275//To set Band Steering AP group
3276//To-do
3277INT wifi_setBandSteeringApGroup(char *ApGroup)
3278{
3279 return RETURN_OK;
3280}
3281
3282INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
3283{
3284 char config_file[128] = {'\0'};
3285 char buf[128] = {'\0'};
3286
3287 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3288 if (dtimInterval == NULL)
3289 return RETURN_ERR;
3290
3291 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
3292 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
3293
3294 if (strlen(buf) == 0) {
3295 *dtimInterval = 2;
3296 } else {
3297 *dtimInterval = strtoul(buf, NULL, 10);
3298 }
3299
3300 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3301 return RETURN_OK;
3302}
3303
3304INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
3305{
3306 struct params params={0};
3307 char config_file[MAX_BUF_SIZE] = {'\0'};
3308 char buf[MAX_BUF_SIZE] = {'\0'};
3309
3310 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3311 if (dtimInterval < 1 || dtimInterval > 255) {
3312 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
3313 return RETURN_ERR;
3314 }
developer69b61b02023-03-07 17:17:44 +08003315
developer72fb0bb2023-01-11 09:46:29 +08003316 params.name = "dtim_period";
3317 snprintf(buf, sizeof(buf), "%d", dtimInterval);
3318 params.value = buf;
3319
3320 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
3321 wifi_hostapdWrite(config_file, &params, 1);
3322 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3323
3324 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3325 return RETURN_OK;
3326}
3327
3328//Check if the driver support the Dfs
3329INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
3330{
3331 wifi_band band = band_invalid;
developer69b61b02023-03-07 17:17:44 +08003332 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003333 return RETURN_ERR;
3334 *output_bool=FALSE;
3335
3336 band = wifi_index_to_band(radioIndex);
3337 if (band == band_5)
3338 *output_bool = TRUE;
3339 return RETURN_OK;
3340}
3341
3342//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.
3343//The value of this parameter is a comma seperated list of channel number
3344INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
3345{
developer69b61b02023-03-07 17:17:44 +08003346 if (NULL == output_pool)
developer72fb0bb2023-01-11 09:46:29 +08003347 return RETURN_ERR;
3348 if (radioIndex==1)
developer69b61b02023-03-07 17:17:44 +08003349 return RETURN_OK;//TODO need to handle for 5GHz band, i think
developer72fb0bb2023-01-11 09:46:29 +08003350 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
3351
3352 return RETURN_OK;
3353}
3354
3355INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
3356{
3357 //Set to wifi config. And apply instantly.
3358 return RETURN_OK;
3359}
3360
3361INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
3362{
developer69b61b02023-03-07 17:17:44 +08003363 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
developer72fb0bb2023-01-11 09:46:29 +08003364 return RETURN_ERR;
3365 *output_interval_seconds=1800;
3366 *output_dwell_milliseconds=40;
3367
3368 return RETURN_OK;
3369}
3370
3371INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
3372{
3373 //Set to wifi config. And apply instantly.
3374 return RETURN_OK;
3375}
3376
3377INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
3378{
3379 if (output_bool == NULL)
3380 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08003381 *output_bool = true;
3382 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003383}
3384
3385INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
3386{
3387 return RETURN_OK;
3388}
3389
3390//Get the Dfs enable status
3391INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
3392{
3393 char buf[16] = {0};
3394 FILE *f = NULL;
developerd1824452023-05-18 12:30:04 +08003395 char config_file_dat[128] = {0};
3396 char dfs_key[16] = "DfsEnable";
3397 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003398
3399 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3400
3401 if (output_bool == NULL)
3402 return RETURN_ERR;
developerf6a87542023-05-16 15:47:28 +08003403 *output_bool = TRUE; // default
developerd1824452023-05-18 12:30:04 +08003404 band = wifi_index_to_band(radioIndex);
3405 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3406
3407 wifi_datfileRead(config_file_dat, dfs_key, buf, sizeof(buf));
3408
3409 if (strncmp(buf, "0", 1) == 0)
3410 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08003411 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3412 return RETURN_OK;
3413}
3414
3415//Set the Dfs enable status
3416INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
3417{
3418 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +08003419 char config_dat_file[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003420 FILE *f = NULL;
developerd1824452023-05-18 12:30:04 +08003421 struct params dat = {0};
3422 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003423
3424 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3425
3426 f = fopen(DFS_ENABLE_FILE, "w");
3427 if (f == NULL)
3428 return RETURN_ERR;
3429 fprintf(f, "%d", enable);
3430 fclose(f);
3431
developer72fb0bb2023-01-11 09:46:29 +08003432 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
3433
developerd1824452023-05-18 12:30:04 +08003434 dat.name = "DfsEnable";
3435 dat.value = enable?"0":"1";
3436 band = wifi_index_to_band(radioIndex);
3437 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3438 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08003439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3440 return RETURN_OK;
3441}
3442
3443//Check if the driver support the AutoChannelRefreshPeriod
3444INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
3445{
developer69b61b02023-03-07 17:17:44 +08003446 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003447 return RETURN_ERR;
3448 *output_bool=FALSE; //not support
3449
3450 return RETURN_OK;
3451}
3452
3453//Get the ACS refresh period in seconds
3454INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
3455{
developer69b61b02023-03-07 17:17:44 +08003456 if (NULL == output_ulong)
developer72fb0bb2023-01-11 09:46:29 +08003457 return RETURN_ERR;
3458 *output_ulong=300;
3459
3460 return RETURN_OK;
3461}
3462
3463//Set the ACS refresh period in seconds
3464INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
3465{
3466 return RETURN_ERR;
3467}
3468
3469//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
3470//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.
3471INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
3472{
developer8666b312023-03-24 14:05:31 +08003473 char cmd[MAX_CMD_SIZE] = {0}, buf[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003474 char extchannel[128] = {0};
developer8666b312023-03-24 14:05:31 +08003475 char interface_name[64] = {0};
3476 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08003477 BOOL radio_enable = FALSE;
3478 wifi_band band;
3479
3480 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3481
developerd1824452023-05-18 12:30:04 +08003482 if (NULL == output_string) {
3483 WIFI_ENTRY_EXIT_DEBUG("output_string is nuill %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003484 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003485 }
3486 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR) {
3487 WIFI_ENTRY_EXIT_DEBUG("wifi_getRadioEnable failed %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003488 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003489 }
3490 if (radio_enable != TRUE) {
3491 WIFI_ENTRY_EXIT_DEBUG("Radio %d is not enable failed %s: %d \n", radioIndex, __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003492 return RETURN_OK;
developerd1824452023-05-18 12:30:04 +08003493 }
developer8666b312023-03-24 14:05:31 +08003494 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3495 return RETURN_ERR;
3496 /*IW command get BW320 to do*/
developerd1824452023-05-18 12:30:04 +08003497
developer8666b312023-03-24 14:05:31 +08003498 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
3499 ret = _syscmd(cmd, buf, sizeof(buf));
3500 len = strlen(buf);
3501 if((ret != 0) || (len == 0))
3502 {
3503 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
3504 return RETURN_ERR;
3505 }
3506
developer72fb0bb2023-01-11 09:46:29 +08003507 band = wifi_index_to_band(radioIndex);
developer8666b312023-03-24 14:05:31 +08003508 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
developer72fb0bb2023-01-11 09:46:29 +08003509 wifi_getRadioExtChannel(radioIndex, extchannel);
developer8666b312023-03-24 14:05:31 +08003510 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
3511 snprintf(buf, sizeof(buf), "40");
developer72fb0bb2023-01-11 09:46:29 +08003512 }
developer8666b312023-03-24 14:05:31 +08003513 snprintf(output_string, 64, "%sMHz", buf);
developer72fb0bb2023-01-11 09:46:29 +08003514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3515
3516 return RETURN_OK;
3517}
developer72fb0bb2023-01-11 09:46:29 +08003518//Set the Operating Channel Bandwidth.
3519INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
3520{
3521 char config_file[128];
developerd1824452023-05-18 12:30:04 +08003522 char ht_value[16];
3523 char vht_value[16];
3524 char eht_value[16];
3525 struct params dat[3];
3526 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003527
3528 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3529
3530 if(NULL == bandwidth)
3531 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003532 band = wifi_index_to_band(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08003533
developerd1824452023-05-18 12:30:04 +08003534 if(strstr(bandwidth,"320") != NULL) {
3535 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3536 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
3537 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_320);
3538 } else if(strstr(bandwidth,"160") != NULL) {
3539 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3540 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
3541 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_160);
3542 } else if(strstr(bandwidth,"80") != NULL) {
3543 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3544 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_80);
3545 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_80);
3546 } else if(strstr(bandwidth,"40") != NULL) {
3547 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3548 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
3549 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_40);
3550 } else if(strstr(bandwidth,"20") != NULL) {
3551 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_20);
3552 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
3553 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_20);
3554 } else {
developer72fb0bb2023-01-11 09:46:29 +08003555 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
3556 return RETURN_ERR;
3557 }
3558
developerd1824452023-05-18 12:30:04 +08003559 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3560 dat[0].name = "HT_BW";
3561 dat[0].value = ht_value;
3562 dat[1].name = "VHT_BW";
3563 dat[1].value = vht_value;
3564 dat[2].name = "EHT_ApBw";
3565 dat[2].value = eht_value;
3566 wifi_datfileWrite(config_file, dat, 3);
developer72fb0bb2023-01-11 09:46:29 +08003567
3568 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3569 return RETURN_OK;
3570}
3571
developer72fb0bb2023-01-11 09:46:29 +08003572//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
3573//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.
3574INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
3575{
3576 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08003577 char config_dat_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003578 char mode_str[16] = {0};
3579 char buf[64] = {0};
developerd1824452023-05-18 12:30:04 +08003580 char cmd[MAX_CMD_SIZE] = {0};
3581 char interface_name[64] = {0};
3582 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08003583 wifi_band band;
developerd1824452023-05-18 12:30:04 +08003584 ULONG channel = 0;
3585 int centr_channel = 0;
developer72fb0bb2023-01-11 09:46:29 +08003586 UINT mode_map = 0;
developerd1824452023-05-18 12:30:04 +08003587 int freq=0;
developer72fb0bb2023-01-11 09:46:29 +08003588
3589 if (output_string == NULL)
3590 return RETURN_ERR;
3591
3592 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
3593
3594 band = wifi_index_to_band(radioIndex);
3595 if (band == band_invalid)
3596 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003597 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3598 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08003599
3600 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3601
3602 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08003603 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developerd1824452023-05-18 12:30:04 +08003604 // 2G band or ac and ax mode is disable, we will check HT_EXTCHA
3605 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3606 wifi_halgetRadioExtChannel(config_dat_file, output_string);
developer23e71282023-01-18 10:25:19 +08003607 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08003608 snprintf(output_string, 64, "Auto");
3609 } else {
3610 // 5G and 6G band with ac or ax mode.
3611 wifi_getRadioChannel(radioIndex, &channel);
developerd1824452023-05-18 12:30:04 +08003612 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'center1' | cut -d ' ' -f9 | tr -d '\\n'", interface_name);
3613
3614 ret = _syscmd(cmd, buf, sizeof(buf));
3615 len = strlen(buf);
3616 if((ret != 0) || (len == 0))
3617 {
3618 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
3619 return RETURN_ERR;
3620 }
3621 sscanf(buf, "%d", &freq);
3622 centr_channel = ieee80211_frequency_to_channel(freq);
3623 if (centr_channel > (int)channel)
developer72fb0bb2023-01-11 09:46:29 +08003624 snprintf(output_string, 64, "AboveControlChannel");
3625 else
3626 snprintf(output_string, 64, "BelowControlChannel");
3627 }
3628
3629 return RETURN_OK;
3630}
3631
3632//Set the extension channel.
3633INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer69b61b02023-03-07 17:17:44 +08003634{
developer72fb0bb2023-01-11 09:46:29 +08003635 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3636 struct params params={0};
3637 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08003638 char config_dat_file[64] = {0};
3639 char ext_channel[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003640 char buf[128] = {0};
3641 char cmd[128] = {0};
3642 int max_radio_num =0, ret = 0, bandwidth = 0;
3643 unsigned long channel = 0, centr_channel = 0;
3644 bool stbcEnable = FALSE;
3645 params.name = "ht_capab";
3646 wifi_band band;
3647
3648 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3649 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
3650 _syscmd(cmd, buf, sizeof(buf));
3651 if (strlen(buf) != 0)
3652 stbcEnable = TRUE;
3653 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
3654 return RETURN_ERR;
3655 bandwidth = strtol(buf, NULL, 10);
3656 // TDK expected to get error with 20MHz
3657 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
3658 return RETURN_ERR;
3659
3660 band = wifi_index_to_band(radioIndex);
3661 if (band == band_invalid)
3662 return RETURN_ERR;
3663
3664 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
3665 return RETURN_ERR;
3666
3667 if (band == band_5) {
3668 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
3669 centr_channel = util_unii_5g_centerfreq(buf, channel);
3670 if (centr_channel == 0)
3671 return RETURN_ERR;
3672 }
3673
3674 if(NULL!= strstr(string,"Above")) {
3675 if ((band == band_2_4 && channel > 9) || (band == band_5 && channel > centr_channel))
3676 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003677 snprintf(ext_channel, sizeof(ext_channel), "Above");
developer72fb0bb2023-01-11 09:46:29 +08003678 } else if(NULL!= strstr(string,"Below")) {
3679 if ((band == band_2_4 && channel < 5) || (band == band_5 && channel < centr_channel))
3680 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003681 snprintf(ext_channel, sizeof(ext_channel), "Above");
3682 } else
3683 printf("%s: invalid EXT_CHA:%s\n", __func__, string);
developer72fb0bb2023-01-11 09:46:29 +08003684
developerd1824452023-05-18 12:30:04 +08003685 params.name = "HT_EXTCHA";
developer72fb0bb2023-01-11 09:46:29 +08003686 params.value = ext_channel;
3687
developerd1824452023-05-18 12:30:04 +08003688 snprintf (config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3689 wifi_datfileWrite(config_dat_file, &params, 1);
3690
developer72fb0bb2023-01-11 09:46:29 +08003691 wifi_getMaxRadioNumber(&max_radio_num);
3692 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3693 {
3694 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer72fb0bb2023-01-11 09:46:29 +08003695 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
3696 }
3697
3698 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3699 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3700 return RETURN_OK;
3701}
3702
3703//Get the guard interval value. eg "400nsec" or "800nsec"
3704//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.
3705INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3706{
3707 wifi_guard_interval_t GI;
3708
3709 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3710
3711 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
3712 return RETURN_ERR;
3713
3714 if (GI == wifi_guard_interval_400)
3715 strcpy(output_string, "400nsec");
3716 else if (GI == wifi_guard_interval_800)
3717 strcpy(output_string, "800nsec");
3718 else if (GI == wifi_guard_interval_1600)
3719 strcpy(output_string, "1600nsec");
3720 else if (GI == wifi_guard_interval_3200)
3721 strcpy(output_string, "3200nsec");
3722 else
3723 strcpy(output_string, "Auto");
3724
3725 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3726 return RETURN_OK;
3727}
3728
3729//Set the guard interval value.
3730INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3731{
3732 wifi_guard_interval_t GI;
3733 int ret = 0;
3734
3735 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3736
3737 if (strcmp(string, "400nsec") == 0)
3738 GI = wifi_guard_interval_400;
3739 else if (strcmp(string , "800nsec") == 0)
3740 GI = wifi_guard_interval_800;
3741 else if (strcmp(string , "1600nsec") == 0)
3742 GI = wifi_guard_interval_1600;
3743 else if (strcmp(string , "3200nsec") == 0)
3744 GI = wifi_guard_interval_3200;
3745 else
3746 GI = wifi_guard_interval_auto;
3747
3748 ret = wifi_setGuardInterval(radioIndex, GI);
3749
3750 if (ret == RETURN_ERR) {
3751 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3752 return RETURN_ERR;
3753 }
3754
3755 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3756 return RETURN_OK;
3757}
3758
3759//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3760INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3761{
3762 char buf[32]={0};
3763 char mcs_file[64] = {0};
3764 char cmd[64] = {0};
3765 int mode_bitmap = 0;
3766
3767 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3768 if(output_int == NULL)
3769 return RETURN_ERR;
3770 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3771
3772 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3773 _syscmd(cmd, buf, sizeof(buf));
3774 if (strlen(buf) > 0)
3775 *output_int = strtol(buf, NULL, 10);
3776 else {
3777 // output the max MCS for the current radio mode
3778 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3779 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3780 return RETURN_ERR;
3781 }
3782 if (mode_bitmap & WIFI_MODE_AX) {
3783 *output_int = 11;
3784 } else if (mode_bitmap & WIFI_MODE_AC) {
3785 *output_int = 9;
3786 } else if (mode_bitmap & WIFI_MODE_N) {
3787 *output_int = 7;
3788 }
3789 }
3790 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3791
3792 return RETURN_OK;
3793}
3794
3795//Set the Modulation Coding Scheme index
3796INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3797{
developera1255e42023-05-13 17:45:02 +08003798 /*Only HE mode can specify MCS capability. We don't support MCS in HT mode,
3799 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 +08003800 char config_file[64] = {0};
3801 char set_value[16] = {0};
3802 char mcs_file[32] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003803 struct params set_config = {0};
3804 FILE *f = NULL;
developera1255e42023-05-13 17:45:02 +08003805 INT nss = 0;
3806 int ant_bitmap = 0;
3807 unsigned short cal_value = 0;
3808 UCHAR tval = 0, i = 0;
developer72fb0bb2023-01-11 09:46:29 +08003809
3810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3811
3812 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3813
3814 // -1 means auto
3815 if (MCS > 15 || MCS < -1) {
3816 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3817 return RETURN_ERR;
3818 }
developera1255e42023-05-13 17:45:02 +08003819 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);/*nss is a bit map value,1111*/
3820 for(; ant_bitmap > 0; ant_bitmap >>= 1)
3821 nss += 1;
3822 //printf("%s:nss = %d\n", __func__, nss);
3823 /*16-bit combination of 2-bit values of Max HE-MCS For 1..8 SS;each 2-bit value have following meaning:
3824 0 = HE-MCS 0-7, 1 = HE-MCS 0-9, 2 = HE-MCS 0-11, 3 = not supported*/
developer72fb0bb2023-01-11 09:46:29 +08003825 if (MCS > 9 || MCS == -1)
developera1255e42023-05-13 17:45:02 +08003826 tval = 2;/*one stream value*/
developer72fb0bb2023-01-11 09:46:29 +08003827 else if (MCS > 7)
developera1255e42023-05-13 17:45:02 +08003828 tval = 1;
developer72fb0bb2023-01-11 09:46:29 +08003829 else
developera1255e42023-05-13 17:45:02 +08003830 tval = 0;
3831 for (i = 0; i < nss; i++)
3832 cal_value |= (tval << (2*i));
3833 snprintf(set_value, sizeof(set_value), "%x", cal_value);
3834 WIFI_ENTRY_EXIT_DEBUG("%s:set=%s, cal=%x\n", __func__, set_value, cal_value);
3835 set_config.name = "he_basic_mcs_nss_set";/*He capability in beacon or response*/
developer72fb0bb2023-01-11 09:46:29 +08003836 set_config.value = set_value;
3837
3838 wifi_hostapdWrite(config_file, &set_config, 1);
3839 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3840
3841 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3842 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3843 f = fopen(mcs_file, "w");
3844 if (f == NULL) {
3845 fprintf(stderr, "%s: fopen failed\n", __func__);
3846 return RETURN_ERR;
3847 }
3848 fprintf(f, "%d", MCS);
3849 fclose(f);
3850
3851 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3852 return RETURN_OK;
3853}
3854
3855//Get supported Transmit Power list, eg : "0,25,50,75,100"
3856//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.
3857INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3858{
3859 if (NULL == output_list)
3860 return RETURN_ERR;
3861 snprintf(output_list, 64,"0,25,50,75,100");
3862 return RETURN_OK;
3863}
3864
3865//Get current Transmit Power in dBm units.
3866//The transmite power level is in units of full power for this radio.
3867INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3868{
3869 char interface_name[16] = {0};
3870 char cmd[128]={0};
3871 char buf[16]={0};
developera1255e42023-05-13 17:45:02 +08003872 char pwr_file[128]={0};
3873
developer72fb0bb2023-01-11 09:46:29 +08003874 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3875
3876 if(output_ulong == NULL)
3877 return RETURN_ERR;
3878
3879 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3880 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08003881/*
developer72fb0bb2023-01-11 09:46:29 +08003882 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
3883 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08003884 *output_ulong = strtol(buf, NULL, 10);
developera1255e42023-05-13 17:45:02 +08003885*/
3886 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
3887 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", pwr_file);
3888 _syscmd(cmd, buf, sizeof(buf));
3889 if (strlen(buf) > 0)
3890 *output_ulong = strtol(buf, NULL, 10);
3891 else
3892 *output_ulong = 100;
developer72fb0bb2023-01-11 09:46:29 +08003893 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3894 return RETURN_OK;
3895}
3896
3897//Set Transmit Power
3898//The transmite power level is in units of full power for this radio.
3899INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3900{
3901 char interface_name[16] = {0};
3902 char *support;
3903 char cmd[128]={0};
3904 char buf[128]={0};
3905 char txpower_str[64] = {0};
developera1255e42023-05-13 17:45:02 +08003906 char pwr_file[128]={0};
3907 FILE *f = NULL;
developer72fb0bb2023-01-11 09:46:29 +08003908
3909 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3910
3911 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3912 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08003913 // Get the Tx power supported list and check that is the input in the list
3914 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3915 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3916 support = strtok(buf, ",");
3917 while(true)
3918 {
3919 if(support == NULL) { // input not in the list
3920 wifi_dbg_printf("Input value is invalid.\n");
3921 return RETURN_ERR;
3922 }
3923 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3924 break;
3925 }
3926 support = strtok(NULL, ",");
3927 }
3928 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr PercentageCtrl=1\n", interface_name);
3929 _syscmd(cmd, buf, sizeof(buf));
3930 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr PowerDropCtrl=%lu\n", interface_name, TransmitPower);
3931 _syscmd(cmd, buf, sizeof(buf));
3932 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
3933 f = fopen(pwr_file, "w");
3934 if (f == NULL) {
3935 fprintf(stderr, "%s: fopen failed\n", __func__);
3936 return RETURN_ERR;
3937 }
3938 fprintf(f, "%d", TransmitPower);
3939 fclose(f);
3940/* 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 +08003941 _syscmd(cmd, buf, sizeof(buf));
3942 maximum_tx = strtol(buf, NULL, 10);
3943
3944 // Get the Tx power supported list and check that is the input in the list
3945 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3946 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3947 support = strtok(buf, ",");
3948 while(true)
3949 {
3950 if(support == NULL) { // input not in the list
3951 wifi_dbg_printf("Input value is invalid.\n");
3952 return RETURN_ERR;
3953 }
3954 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3955 break;
3956 }
3957 support = strtok(NULL, ",");
3958 }
3959 txpower = TransmitPower*maximum_tx/100;
3960 phyId = radio_index_to_phy(radioIndex);
3961 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
3962 _syscmd(cmd, buf, sizeof(buf));
3963 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera1255e42023-05-13 17:45:02 +08003964*/
3965 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003966}
3967
3968//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3969INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3970{
developer69b61b02023-03-07 17:17:44 +08003971 if (NULL == Supported)
developer72fb0bb2023-01-11 09:46:29 +08003972 return RETURN_ERR;
3973 *Supported = TRUE;
3974
3975 return RETURN_OK;
3976}
3977
3978//Get 80211h feature enable
3979INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3980{
3981 char buf[64]={'\0'};
3982 char config_file[64] = {'\0'};
3983
3984 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3985 if(enable == NULL)
3986 return RETURN_ERR;
3987
3988 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerd1824452023-05-18 12:30:04 +08003989 /* wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf)); */
3990 wifi_datfileRead(config_file, "IEEE80211H", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08003991
3992 if (strncmp(buf, "1", 1) == 0)
3993 *enable = TRUE;
3994 else
3995 *enable = FALSE;
3996
3997 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3998 return RETURN_OK;
3999}
4000
4001//Set 80211h feature enable
4002INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
4003{
4004 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4005 struct params params={'\0'};
developerd1824452023-05-18 12:30:04 +08004006 struct params dat={0};
developer72fb0bb2023-01-11 09:46:29 +08004007 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08004008 char config_dat_file[MAX_BUF_SIZE] = {0};
4009 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004010
4011 params.name = "ieee80211h";
4012
4013 if (enable) {
4014 params.value = "1";
4015 } else {
4016 params.value = "0";
4017 }
4018
developerd1824452023-05-18 12:30:04 +08004019 dat.name = "IEEE80211H";
4020 dat.value = params.value;
4021
4022 band = wifi_index_to_band(radioIndex);
4023 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4024 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer69b61b02023-03-07 17:17:44 +08004025
developerd1824452023-05-18 12:30:04 +08004026 wifi_hostapdWrite(config_file, &params, 1);
4027 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08004028 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4029 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4030 return RETURN_OK;
4031}
4032
4033//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.
4034INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
4035{
4036 if (NULL == output)
4037 return RETURN_ERR;
4038 *output=100;
4039
4040 return RETURN_OK;
4041}
4042
4043//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.
4044INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
4045{
4046 if (NULL == output)
4047 return RETURN_ERR;
4048 *output = -99;
4049
4050 return RETURN_OK;
4051}
4052
4053INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
4054{
4055 return RETURN_ERR;
4056}
4057
4058
4059//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
4060INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
4061{
4062 char interface_name[16] = {0};
4063 char cmd[MAX_BUF_SIZE]={'\0'};
4064 char buf[MAX_CMD_SIZE]={'\0'};
4065
4066 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4067 if(output == NULL)
4068 return RETURN_ERR;
4069
4070 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4071 return RETURN_ERR;
4072 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
4073 _syscmd(cmd, buf, sizeof(buf));
4074 *output = atoi(buf);
4075
4076 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4077 return RETURN_OK;
4078}
developer69b61b02023-03-07 17:17:44 +08004079
developer72fb0bb2023-01-11 09:46:29 +08004080INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
4081{
4082 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4083 struct params params={'\0'};
4084 char buf[MAX_BUF_SIZE] = {'\0'};
4085 char config_file[MAX_BUF_SIZE] = {'\0'};
4086
4087 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
4088 return RETURN_ERR;
4089
4090 params.name = "beacon_int";
4091 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
4092 params.value = buf;
4093
4094 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
4095 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08004096
developer72fb0bb2023-01-11 09:46:29 +08004097 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4098 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4099 return RETURN_OK;
4100}
4101
4102//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.
4103INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
4104{
4105 //TODO: need to revisit below implementation
4106 char *temp;
4107 char temp_output[128] = {0};
4108 char temp_TransmitRates[64] = {0};
4109 char config_file[64] = {0};
4110
4111 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4112 if (NULL == output)
4113 return RETURN_ERR;
4114 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4115 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
developer69b61b02023-03-07 17:17:44 +08004116
developer72fb0bb2023-01-11 09:46:29 +08004117 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
4118 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
4119 } else {
4120 temp = strtok(temp_TransmitRates," ");
4121 while(temp!=NULL)
4122 {
4123 // Convert 100 kbps to Mbps
4124 temp[strlen(temp)-1]=0;
4125 if((temp[0]=='5') && (temp[1]=='\0'))
4126 {
4127 temp="5.5";
4128 }
4129 strcat(temp_output,temp);
4130 temp = strtok(NULL," ");
4131 if(temp!=NULL)
4132 {
4133 strcat(temp_output,",");
4134 }
4135 }
4136 strcpy(output,temp_output);
4137 }
4138 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4139 return RETURN_OK;
4140}
4141
4142INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
4143{
4144 char *temp;
4145 char temp1[128];
4146 char temp_output[128];
4147 char temp_TransmitRates[128];
4148 char set[128];
4149 char sub_set[128];
4150 int set_count=0,subset_count=0;
4151 int set_index=0,subset_index=0;
4152 char *token;
4153 int flag=0, i=0;
4154 struct params params={'\0'};
4155 char config_file[MAX_BUF_SIZE] = {0};
4156 wifi_band band = wifi_index_to_band(radioIndex);
4157
4158 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4159 if(NULL == TransmitRates)
4160 return RETURN_ERR;
4161 strcpy(sub_set,TransmitRates);
4162
4163 //Allow only supported Data transmit rate to be set
4164 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
4165 token = strtok(sub_set,",");
4166 while( token != NULL ) /* split the basic rate to be set, by comma */
4167 {
4168 sub_set[subset_count]=atoi(token);
4169 subset_count++;
4170 token=strtok(NULL,",");
4171 }
4172 token=strtok(set,",");
4173 while(token!=NULL) /* split the supported rate by comma */
4174 {
4175 set[set_count]=atoi(token);
4176 set_count++;
4177 token=strtok(NULL,",");
4178 }
4179 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
4180 {
4181 for(set_index=0;set_index < set_count;set_index++)
4182 {
4183 flag=0;
4184 if(sub_set[subset_index]==set[set_index])
4185 break;
4186 else
4187 flag=1; /* No match found */
4188 }
4189 if(flag==1)
4190 return RETURN_ERR; //If value not found return Error
4191 }
4192 strcpy(temp_TransmitRates,TransmitRates);
4193
4194 for(i=0;i<strlen(temp_TransmitRates);i++)
4195 {
4196 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
4197 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
4198 {
4199 continue;
4200 }
4201 else
4202 {
4203 return RETURN_ERR;
4204 }
4205 }
4206 strcpy(temp_output,"");
4207 temp = strtok(temp_TransmitRates,",");
4208 while(temp!=NULL)
4209 {
4210 strcpy(temp1,temp);
4211 if(band == band_5)
4212 {
4213 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
4214 {
4215 return RETURN_ERR;
4216 }
4217 }
4218
4219 if(strcmp(temp,"5.5")==0)
4220 {
4221 strcpy(temp1,"55");
4222 }
4223 else
4224 {
4225 strcat(temp1,"0");
4226 }
4227 strcat(temp_output,temp1);
4228 temp = strtok(NULL,",");
4229 if(temp!=NULL)
4230 {
4231 strcat(temp_output," ");
4232 }
4233 }
4234 strcpy(TransmitRates,temp_output);
4235
4236 params.name= "basic_rates";
4237 params.value =TransmitRates;
4238
4239 wifi_dbg_printf("\n%s:",__func__);
4240 wifi_dbg_printf("\nparams.value=%s\n",params.value);
4241 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
4242 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4243 wifi_hostapdWrite(config_file,&params,1);
4244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4245 return RETURN_OK;
4246}
4247
4248//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
4249INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
4250{
4251 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4252 FILE *fp = NULL;
4253 char path[256] = {0}, output_string[256] = {0};
4254 int count = 0;
4255 char *interface = NULL;
4256
4257 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
4258 if (fp == NULL)
4259 {
4260 printf("Failed to run command in Function %s\n", __FUNCTION__);
4261 return RETURN_ERR;
4262 }
4263 if (fgets(path, sizeof(path) - 1, fp) != NULL)
4264 {
4265 interface = strchr(path, '=');
4266
4267 if (interface != NULL)
4268 {
4269 strcpy(output_string, interface + 1);
4270 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
4271 interface_name[count] = output_string[count];
4272
4273 interface_name[count] = '\0';
4274 }
4275 }
4276 pclose(fp);
4277 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4278 return RETURN_OK;
4279}
4280
4281INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
4282{
4283 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4284 output_struct->radio_BytesSent = 0;
4285 output_struct->radio_BytesReceived = 0;
4286 output_struct->radio_PacketsSent = 0;
4287 output_struct->radio_PacketsReceived = 0;
4288 output_struct->radio_ErrorsSent = 0;
4289 output_struct->radio_ErrorsReceived = 0;
4290 output_struct->radio_DiscardPacketsSent = 0;
4291 output_struct->radio_DiscardPacketsReceived = 0;
4292 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4293 return RETURN_OK;
4294}
4295
4296
4297INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
4298{
4299 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4300 CHAR buf[MAX_CMD_SIZE] = {0};
4301 CHAR Value[MAX_BUF_SIZE] = {0};
4302 FILE *fp = NULL;
4303
4304 if (ifname == NULL || strlen(ifname) <= 1)
4305 return RETURN_OK;
4306
4307 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
4308 system(buf);
4309
4310 fp = fopen("/tmp/Radio_Stats.txt", "r");
4311 if(fp == NULL)
4312 {
4313 printf("/tmp/Radio_Stats.txt not exists \n");
4314 return RETURN_ERR;
4315 }
4316 fclose(fp);
4317
4318 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4319 File_Reading(buf, Value);
4320 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
4321
4322 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4323 File_Reading(buf, Value);
4324 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
4325
4326 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4327 File_Reading(buf, Value);
4328 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
4329
4330 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4331 File_Reading(buf, Value);
4332 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
4333
4334 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4335 File_Reading(buf, Value);
4336 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
4337
4338 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4339 File_Reading(buf, Value);
4340 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
4341
4342 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4343 File_Reading(buf, Value);
4344 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
4345
4346 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4347 File_Reading(buf, Value);
4348 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
4349
4350 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4351 return RETURN_OK;
4352}
4353
4354INT GetIfacestatus(CHAR *interface_name, CHAR *status)
4355{
developer7e4a2a62023-04-06 19:56:03 +08004356 CHAR buf[MAX_CMD_SIZE] = {0};
4357 INT count = 0;
developer72fb0bb2023-01-11 09:46:29 +08004358
developer7e4a2a62023-04-06 19:56:03 +08004359 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4360
4361 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL) {
4362 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
4363 File_Reading(buf, status);
4364 }
4365
4366 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4367 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004368}
4369
4370//Get detail radio traffic static info
4371INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
4372{
4373
developer69b61b02023-03-07 17:17:44 +08004374#if 0
4375 //ifconfig radio_x
developer72fb0bb2023-01-11 09:46:29 +08004376 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
4377 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
4378 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
4379 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
4380
4381 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
4382 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
4383 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.
4384 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.
4385
developer69b61b02023-03-07 17:17:44 +08004386 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 +08004387 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].
4388 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
4389 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.
4390 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
4391 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
4392 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
4393 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
4394 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
4395
4396 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
4397 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
4398 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
4399 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.
4400
4401 return RETURN_OK;
4402#endif
4403
4404 CHAR interface_name[64] = {0};
4405 BOOL iface_status = FALSE;
4406 wifi_radioTrafficStats2_t radioTrafficStats = {0};
4407
4408 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4409 if (NULL == output_struct)
4410 return RETURN_ERR;
4411
4412 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4413 return RETURN_ERR;
4414
4415 wifi_getApEnable(radioIndex, &iface_status);
4416
4417 if (iface_status == TRUE)
4418 wifi_halGetIfStats(interface_name, &radioTrafficStats);
4419 else
4420 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
4421
4422 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
4423 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
4424 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
4425 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
4426 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
4427 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
4428 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
4429 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
4430
4431 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
4432 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].
4433 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
4434 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.
4435 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
4436 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
4437 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
4438 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
4439 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
4440
4441 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
4442 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
4443 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
4444 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.
4445
4446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4447
4448 return RETURN_OK;
4449}
4450
4451//Set radio traffic static Measureing rules
4452INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
4453{
4454 //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
4455 // Else, save the MeasuringRate and MeasuringInterval for future usage
4456
4457 return RETURN_OK;
4458}
4459
4460//To start or stop RadioTrafficStats
4461INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
4462{
4463 //zqiu: If the RadioTrafficStats process running
4464 // if(enable)
4465 // return RETURN_OK.
4466 // else
4467 // Stop RadioTrafficStats process
developer69b61b02023-03-07 17:17:44 +08004468 // Else
developer72fb0bb2023-01-11 09:46:29 +08004469 // if(enable)
4470 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
4471 // else
4472 // return RETURN_OK.
4473
4474 return RETURN_OK;
4475}
4476
4477//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
4478INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
4479{
4480 //zqiu: Please ignor signalIndex.
developer69b61b02023-03-07 17:17:44 +08004481 if (NULL == SignalLevel)
developer72fb0bb2023-01-11 09:46:29 +08004482 return RETURN_ERR;
developer47cc27a2023-05-17 23:09:58 +08004483
developer72fb0bb2023-01-11 09:46:29 +08004484 *SignalLevel=(radioIndex==0)?-19:-19;
4485
4486 return RETURN_OK;
4487}
4488
4489//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4490INT wifi_applyRadioSettings(INT radioIndex)
4491{
4492 return RETURN_OK;
4493}
4494
4495//Get the radio index assocated with this SSID entry
4496INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
4497{
4498 if(NULL == radioIndex)
4499 return RETURN_ERR;
4500 int max_radio_num = 0;
4501 wifi_getMaxRadioNumber(&max_radio_num);
4502 *radioIndex = ssidIndex%max_radio_num;
4503 return RETURN_OK;
4504}
4505
4506//Device.WiFi.SSID.{i}.Enable
4507//Get SSID enable configuration parameters (not the SSID enable status)
4508INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
4509{
developer69b61b02023-03-07 17:17:44 +08004510 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08004511 return RETURN_ERR;
4512
4513 return wifi_getApEnable(ssidIndex, output_bool);
4514}
4515
4516//Device.WiFi.SSID.{i}.Enable
4517//Set SSID enable configuration parameters
4518INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
4519{
4520 return wifi_setApEnable(ssidIndex, enable);
4521}
4522
4523//Device.WiFi.SSID.{i}.Status
4524//Get the SSID enable status
4525INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
4526{
4527 char cmd[MAX_CMD_SIZE]={0};
4528 char buf[MAX_BUF_SIZE]={0};
4529 BOOL output_bool;
4530
4531 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4532 if (NULL == output_string)
4533 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08004534
developer72fb0bb2023-01-11 09:46:29 +08004535 wifi_getApEnable(ssidIndex,&output_bool);
4536 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
4537
4538 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4539 return RETURN_OK;
4540}
4541
4542// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
4543INT wifi_getSSIDName(INT apIndex, CHAR *output)
4544{
4545 char config_file[MAX_BUF_SIZE] = {0};
4546
developer69b61b02023-03-07 17:17:44 +08004547 if (NULL == output)
developer72fb0bb2023-01-11 09:46:29 +08004548 return RETURN_ERR;
4549
4550 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4551 wifi_hostapdRead(config_file,"ssid",output,32);
4552
4553 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
4554 return RETURN_OK;
4555}
4556
developer69b61b02023-03-07 17:17:44 +08004557// Set a max 32 byte string and sets an internal variable to the SSID name
developer72fb0bb2023-01-11 09:46:29 +08004558INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
4559{
4560 char str[MAX_BUF_SIZE]={'\0'};
4561 char cmd[MAX_CMD_SIZE]={'\0'};
4562 struct params params;
4563 char config_file[MAX_BUF_SIZE] = {0};
4564
4565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4566 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
4567 return RETURN_ERR;
4568
4569 params.name = "ssid";
4570 params.value = ssid_string;
4571 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4572 wifi_hostapdWrite(config_file, &params, 1);
4573 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4575
4576 return RETURN_OK;
4577}
4578
4579//Get the BSSID
4580INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
4581{
developer7e4a2a62023-04-06 19:56:03 +08004582 char cmd[MAX_CMD_SIZE] = {0};
4583 char inf_name[IF_NAME_SIZE] = {0};
4584 char conf_file[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004585
developer7e4a2a62023-04-06 19:56:03 +08004586 if (!output_string)
developer72fb0bb2023-01-11 09:46:29 +08004587 return RETURN_ERR;
4588
developer47cc27a2023-05-17 23:09:58 +08004589 if (wifi_GetInterfaceName(ssidIndex, inf_name) != RETURN_OK)
4590 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08004591
4592 if(ssidIndex >= 0 && ssidIndex < MAX_APS) {
4593 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 +08004594 _syscmd(cmd, output_string, 64);
developer7e4a2a62023-04-06 19:56:03 +08004595 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004596 }
developer7e4a2a62023-04-06 19:56:03 +08004597
developer72fb0bb2023-01-11 09:46:29 +08004598 strncpy(output_string, "\0", 1);
4599
4600 return RETURN_ERR;
4601}
4602
4603//Get the MAC address associated with this Wifi SSID
4604INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
4605{
4606 wifi_getBaseBSSID(ssidIndex,output_string);
4607 return RETURN_OK;
4608}
4609
4610//Get the basic SSID traffic static info
4611//Apply SSID and AP (in the case of Acess Point devices) to the hardware
4612//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4613INT wifi_applySSIDSettings(INT ssidIndex)
4614{
4615 char interface_name[16] = {0};
4616 BOOL status = false;
4617 char cmd[MAX_CMD_SIZE] = {0};
4618 char buf[MAX_CMD_SIZE] = {0};
4619 int apIndex, ret;
4620 int max_radio_num = 0;
4621 int radioIndex = 0;
4622
4623 wifi_getMaxRadioNumber(&max_radio_num);
4624
4625 radioIndex = ssidIndex % max_radio_num;
4626
4627 wifi_getApEnable(ssidIndex,&status);
4628 // Do not apply when ssid index is disabled
4629 if (status == false)
4630 return RETURN_OK;
4631
4632 /* Doing full remove and add for ssid Index
4633 * Not all hostapd options are supported with reload
4634 * for example macaddr_acl
4635 */
4636 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
4637 return RETURN_ERR;
4638
4639 ret = wifi_setApEnable(ssidIndex,true);
4640
4641 /* Workaround for hostapd issue with multiple bss definitions
4642 * when first created interface will be removed
4643 * then all vaps other vaps on same phy are removed
4644 * after calling setApEnable to false readd all enabled vaps */
4645 for(int i=0; i < MAX_APS/max_radio_num; i++) {
4646 apIndex = max_radio_num*i+radioIndex;
4647 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4648 return RETURN_ERR;
4649 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
4650 _syscmd(cmd, buf, sizeof(buf));
4651 if(*buf == '1')
4652 wifi_setApEnable(apIndex, true);
4653 }
4654
4655 return ret;
4656}
4657
4658struct channels_noise {
4659 int channel;
4660 int noise;
4661};
4662
4663// Return noise array for each channel
4664int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
4665{
4666 char interface_name[16] = {0};
4667 FILE *f = NULL;
4668 char cmd[128] = {0};
4669 char line[256] = {0};
4670 size_t len = 0;
4671 ssize_t read = 0;
4672 int tmp = 0, arr_index = -1;
4673
4674 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4675 return RETURN_ERR;
4676 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
4677
4678 if ((f = popen(cmd, "r")) == NULL) {
4679 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4680 return RETURN_ERR;
4681 }
developer69b61b02023-03-07 17:17:44 +08004682
developer72fb0bb2023-01-11 09:46:29 +08004683 while(fgets(line, sizeof(line), f) != NULL) {
4684 if(arr_index < channels_num){
4685 sscanf(line, "%d", &tmp);
4686 if (tmp > 0) { // channel frequency, the first line must be frequency
4687 arr_index++;
4688 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
4689 } else { // noise
4690 channels_noise_arr[arr_index].noise = tmp;
4691 }
4692 }else{
4693 break;
4694 }
4695 }
4696 pclose(f);
4697 return RETURN_OK;
4698}
4699
4700//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
4701//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
developer69b61b02023-03-07 17:17:44 +08004702INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
developer72fb0bb2023-01-11 09:46:29 +08004703{
4704 int index = -1;
4705 wifi_neighbor_ap2_t *scan_array = NULL;
4706 char cmd[256]={0};
4707 char buf[128]={0};
4708 char file_name[32] = {0};
4709 char filter_SSID[32] = {0};
4710 char line[256] = {0};
4711 char interface_name[16] = {0};
4712 char *ret = NULL;
4713 int freq=0;
4714 FILE *f = NULL;
4715 size_t len=0;
4716 int channels_num = 0;
4717 int vht_channel_width = 0;
4718 int get_noise_ret = RETURN_ERR;
4719 bool filter_enable = false;
4720 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
4721 int phyId = 0;
4722
4723 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
4724
4725 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4726 return RETURN_ERR;
4727
4728 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4729 f = fopen(file_name, "r");
4730 if (f != NULL) {
4731 fgets(filter_SSID, sizeof(file_name), f);
4732 if (strlen(filter_SSID) != 0)
4733 filter_enable = true;
4734 fclose(f);
4735 }
4736
4737 phyId = radio_index_to_phy(radioIndex);
4738 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
4739 _syscmd(cmd, buf, sizeof(buf));
4740 channels_num = strtol(buf, NULL, 10);
4741
4742
4743
4744 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4745 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
4746 fprintf(stderr, "cmd: %s\n", cmd);
4747 if ((f = popen(cmd, "r")) == NULL) {
4748 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4749 return RETURN_ERR;
4750 }
developer69b61b02023-03-07 17:17:44 +08004751
developer72fb0bb2023-01-11 09:46:29 +08004752 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4753 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08004754
developer72fb0bb2023-01-11 09:46:29 +08004755 ret = fgets(line, sizeof(line), f);
4756 while (ret != NULL) {
4757 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08004758 // 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 +08004759 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4760 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
4761
4762 if (!filter_BSS) {
4763 index++;
4764 wifi_neighbor_ap2_t *tmp;
4765 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4766 if (tmp == NULL) { // no more memory to use
4767 index--;
4768 wifi_dbg_printf("%s: realloc failed\n", __func__);
4769 break;
4770 }
4771 scan_array = tmp;
4772 }
4773 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4774
4775 filter_BSS = false;
4776 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4777 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4778 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4779 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4780 } else if (strstr(line, "freq") != NULL) {
4781 sscanf(line," freq: %d", &freq);
4782 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4783
4784 if (freq >= 2412 && freq <= 2484) {
4785 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4786 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4787 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4788 }
4789 else if (freq >= 5160 && freq <= 5805) {
4790 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4791 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4792 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4793 }
4794
4795 scan_array[index].ap_Noise = 0;
4796 if (get_noise_ret == RETURN_OK) {
4797 for (int i = 0; i < channels_num; i++) {
4798 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4799 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4800 break;
4801 }
4802 }
4803 }
4804 } else if (strstr(line, "beacon interval") != NULL) {
4805 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4806 } else if (strstr(line, "signal") != NULL) {
4807 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4808 } else if (strstr(line,"SSID") != NULL) {
4809 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4810 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4811 filter_BSS = true;
4812 }
4813 } else if (strstr(line, "Supported rates") != NULL) {
4814 char SRate[80] = {0}, *tmp = NULL;
4815 memset(buf, 0, sizeof(buf));
4816 strcpy(SRate, line);
4817 tmp = strtok(SRate, ":");
4818 tmp = strtok(NULL, ":");
4819 strcpy(buf, tmp);
4820 memset(SRate, 0, sizeof(SRate));
4821
4822 tmp = strtok(buf, " \n");
4823 while (tmp != NULL) {
4824 strcat(SRate, tmp);
4825 if (SRate[strlen(SRate) - 1] == '*') {
4826 SRate[strlen(SRate) - 1] = '\0';
4827 }
4828 strcat(SRate, ",");
4829
4830 tmp = strtok(NULL, " \n");
4831 }
4832 SRate[strlen(SRate) - 1] = '\0';
4833 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4834 } else if (strstr(line, "DTIM") != NULL) {
4835 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4836 } else if (strstr(line, "VHT capabilities") != NULL) {
4837 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4838 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4839 } else if (strstr(line, "HT capabilities") != NULL) {
4840 strcat(scan_array[index].ap_SupportedStandards, ",n");
4841 strcpy(scan_array[index].ap_OperatingStandards, "n");
4842 } else if (strstr(line, "VHT operation") != NULL) {
4843 ret = fgets(line, sizeof(line), f);
4844 sscanf(line," * channel width: %d", &vht_channel_width);
4845 if(vht_channel_width == 1) {
4846 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4847 } else {
4848 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4849 }
4850 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4851 continue;
4852 } else if (strstr(line, "HT operation") != NULL) {
4853 ret = fgets(line, sizeof(line), f);
4854 sscanf(line," * secondary channel offset: %s", &buf);
4855 if (!strcmp(buf, "above")) {
4856 //40Mhz +
4857 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4858 }
4859 else if (!strcmp(buf, "below")) {
4860 //40Mhz -
4861 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4862 } else {
4863 //20Mhz
4864 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4865 }
4866 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4867 continue;
4868 } else if (strstr(line, "HE capabilities") != NULL) {
4869 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4870 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4871 ret = fgets(line, sizeof(line), f);
4872 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4873 if (strstr(line, "HE40/2.4GHz") != NULL)
4874 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
4875 else
4876 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
4877 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
4878 if (strstr(line, "HE80/5GHz") != NULL) {
4879 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4880 ret = fgets(line, sizeof(line), f);
4881 } else
4882 continue;
4883 if (strstr(line, "HE160/5GHz") != NULL)
4884 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
4885 }
4886 continue;
4887 } else if (strstr(line, "WPA") != NULL) {
4888 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4889 } else if (strstr(line, "RSN") != NULL) {
4890 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4891 } else if (strstr(line, "Group cipher") != NULL) {
4892 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4893 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4894 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4895 }
4896 }
4897 ret = fgets(line, sizeof(line), f);
4898 }
4899
4900 if (!filter_BSS) {
4901 *output_array_size = index + 1;
4902 } else {
4903 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4904 *output_array_size = index;
4905 }
4906 *neighbor_ap_array = scan_array;
4907 pclose(f);
4908 free(channels_noise_arr);
4909 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4910 return RETURN_OK;
4911}
4912
4913//>> Deprecated: used for old RDKB code.
4914INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4915{
4916 INT status = RETURN_ERR;
4917
4918 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4919 output_struct->wifi_PLCPErrorCount = 0;
4920 output_struct->wifi_FCSErrorCount = 0;
4921 output_struct->wifi_InvalidMACCount = 0;
4922 output_struct->wifi_PacketsOtherReceived = 0;
4923 output_struct->wifi_Noise = 0;
4924 status = RETURN_OK;
4925 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4926 return status;
4927}
4928
4929INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4930{
4931 char interface_name[16] = {0};
4932 char cmd[128] = {0};
4933 char buf[1280] = {0};
4934 char *pos = NULL;
4935
4936 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4937 if (NULL == output_struct)
4938 return RETURN_ERR;
4939
4940 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4941 return RETURN_ERR;
4942
4943 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4944
4945 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
4946 _syscmd(cmd, buf, sizeof(buf));
4947
4948 pos = buf;
4949 if ((pos = strstr(pos, "RX packets:")) == NULL)
4950 return RETURN_ERR;
4951 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4952
4953 if ((pos = strstr(pos, "TX packets:")) == NULL)
4954 return RETURN_ERR;
4955 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4956
4957 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4958 return RETURN_ERR;
4959 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4960
4961 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4962 return RETURN_ERR;
4963 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4964
4965 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
4966 _syscmd(cmd, buf, sizeof(buf));
4967 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4968
4969#if 0
4970 //TODO: need to revisit below implementation
4971 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4972 char interface_name[MAX_BUF_SIZE] = {0};
4973 char interface_status[MAX_BUF_SIZE] = {0};
4974 char Value[MAX_BUF_SIZE] = {0};
4975 char buf[MAX_CMD_SIZE] = {0};
4976 char cmd[MAX_CMD_SIZE] = {0};
4977 FILE *fp = NULL;
4978
4979 if (NULL == output_struct) {
4980 return RETURN_ERR;
4981 }
4982
4983 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4984
4985 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4986 {
4987 if(apIndex == 0) //private_wifi for 2.4G
4988 {
4989 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4990 }
4991 else if(apIndex == 1) //private_wifi for 5G
4992 {
4993 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4994 }
4995 else if(apIndex == 4) //public_wifi for 2.4G
4996 {
4997 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4998 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4999 {
5000 return RETURN_ERR;
5001 }
5002 if(buf[0] == '#')//tp-link
5003 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5004 else//tenda
5005 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
5006 }
5007 else if(apIndex == 5) //public_wifi for 5G
5008 {
5009 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5010 }
5011
5012 GetIfacestatus(interface_name, interface_status);
5013
5014 if(0 != strcmp(interface_status, "1"))
5015 return RETURN_ERR;
5016
5017 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5018 system(cmd);
5019
5020 fp = fopen("/tmp/SSID_Stats.txt", "r");
5021 if(fp == NULL)
5022 {
5023 printf("/tmp/SSID_Stats.txt not exists \n");
5024 return RETURN_ERR;
5025 }
5026 fclose(fp);
5027
5028 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5029 File_Reading(buf, Value);
5030 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
5031
5032 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5033 File_Reading(buf, Value);
5034 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
5035
5036 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5037 File_Reading(buf, Value);
5038 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
5039
5040 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5041 File_Reading(buf, Value);
5042 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
5043
5044 /* There is no specific parameter from caller to associate the value wifi_Associations */
5045 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
5046 //_syscmd(cmd, buf, sizeof(buf));
5047 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
5048 }
5049#endif
5050 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5051 return RETURN_OK;
5052}
5053
5054INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
5055{
5056 char interface_name[MAX_BUF_SIZE] = {0};
5057 char interface_status[MAX_BUF_SIZE] = {0};
5058 char Value[MAX_BUF_SIZE] = {0};
5059 char buf[MAX_CMD_SIZE] = {0};
5060 char cmd[MAX_CMD_SIZE] = {0};
5061 FILE *fp = NULL;
5062
5063 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5064 if (NULL == output_struct)
5065 return RETURN_ERR;
5066
5067 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
5068
5069 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
5070 return RETURN_ERR;
5071 GetIfacestatus(interface_name, interface_status);
5072
5073 if(0 != strcmp(interface_status, "1"))
5074 return RETURN_ERR;
5075
5076 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5077 system(cmd);
5078
5079 fp = fopen("/tmp/SSID_Stats.txt", "r");
5080 if(fp == NULL)
5081 {
5082 printf("/tmp/SSID_Stats.txt not exists \n");
5083 return RETURN_ERR;
5084 }
5085 fclose(fp);
5086
5087 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5088 File_Reading(buf, Value);
5089 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
5090
5091 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5092 File_Reading(buf, Value);
5093 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
5094
5095 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5096 File_Reading(buf, Value);
5097 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
5098
5099 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5100 File_Reading(buf, Value);
5101 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
5102
5103 output_struct->wifi_UnicastPacketsSent = 0;
5104 output_struct->wifi_UnicastPacketsReceived = 0;
5105 output_struct->wifi_MulticastPacketsSent = 0;
5106 output_struct->wifi_MulticastPacketsReceived = 0;
5107 output_struct->wifi_BroadcastPacketsSent = 0;
5108 output_struct->wifi_BroadcastPacketsRecevied = 0;
5109 output_struct->wifi_UnknownPacketsReceived = 0;
5110
5111 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5112 return RETURN_OK;
5113}
5114
5115INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
5116{
5117 INT status = RETURN_ERR;
5118
5119 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5120 //Below values should get updated from hal
5121 output_struct->wifi_RetransCount=0;
5122 output_struct->wifi_FailedRetransCount=0;
5123 output_struct->wifi_RetryCount=0;
5124 output_struct->wifi_MultipleRetryCount=0;
5125 output_struct->wifi_ACKFailureCount=0;
5126 output_struct->wifi_AggregatedPacketCount=0;
5127
5128 status = RETURN_OK;
5129 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5130
5131 return status;
5132}
5133
5134INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
5135{
5136 INT status = RETURN_ERR;
5137 UINT index;
5138 wifi_neighbor_ap_t *pt=NULL;
5139
5140 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5141 *output_array_size=2;
5142 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
5143 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
5144 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
5145 strcpy(pt->ap_Radio,"");
5146 strcpy(pt->ap_SSID,"");
5147 strcpy(pt->ap_BSSID,"");
5148 strcpy(pt->ap_Mode,"");
5149 pt->ap_Channel=1;
5150 pt->ap_SignalStrength=0;
5151 strcpy(pt->ap_SecurityModeEnabled,"");
5152 strcpy(pt->ap_EncryptionMode,"");
5153 strcpy(pt->ap_OperatingFrequencyBand,"");
5154 strcpy(pt->ap_SupportedStandards,"");
5155 strcpy(pt->ap_OperatingStandards,"");
5156 strcpy(pt->ap_OperatingChannelBandwidth,"");
5157 pt->ap_BeaconPeriod=1;
5158 pt->ap_Noise=0;
5159 strcpy(pt->ap_BasicDataTransferRates,"");
5160 strcpy(pt->ap_SupportedDataTransferRates,"");
5161 pt->ap_DTIMPeriod=1;
5162 pt->ap_ChannelUtilization = 1;
5163 }
5164
5165 status = RETURN_OK;
5166 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5167
5168 return status;
5169}
5170
5171//----------------- AP HAL -------------------------------
5172
5173//>> Deprecated: used for old RDKB code.
5174INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
5175{
5176 if (NULL == output_ulong || NULL == output_struct)
5177 return RETURN_ERR;
5178 *output_ulong = 0;
5179 *output_struct = NULL;
5180 return RETURN_OK;
5181}
5182
5183#ifdef HAL_NETLINK_IMPL
5184static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
5185 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5186 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5187 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
5188 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
5189 char mac_addr[20];
5190 static int count=0;
5191 int rate=0;
5192
5193 wifi_device_info_t *out = (wifi_device_info_t*)arg;
5194
5195 nla_parse(tb,
5196 NL80211_ATTR_MAX,
5197 genlmsg_attrdata(gnlh, 0),
5198 genlmsg_attrlen(gnlh, 0),
5199 NULL);
5200
5201 if(!tb[NL80211_ATTR_STA_INFO]) {
5202 fprintf(stderr, "sta stats missing!\n");
5203 return NL_SKIP;
5204 }
5205
5206
5207 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
5208 fprintf(stderr, "failed to parse nested attributes!\n");
5209 return NL_SKIP;
5210 }
5211
5212 //devIndex starts from 1
5213 if( ++count == out->wifi_devIndex )
5214 {
5215 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
5216 //Getting the mac addrress
5217 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
5218
5219 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
5220 fprintf(stderr, "failed to parse nested rate attributes!");
5221 return NL_SKIP;
5222 }
5223
5224 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
5225 if(rinfo[NL80211_RATE_INFO_BITRATE])
5226 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
5227 out->wifi_devTxRate = rate/10;
5228 }
5229
5230 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
5231 fprintf(stderr, "failed to parse nested rate attributes!");
5232 return NL_SKIP;
5233 }
5234
5235 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
5236 if(rinfo[NL80211_RATE_INFO_BITRATE])
5237 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
5238 out->wifi_devRxRate = rate/10;
5239 }
5240 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
5241 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
5242
5243 out->wifi_devAssociatedDeviceAuthentiationState = 1;
5244 count = 0; //starts the count for next cycle
5245 return NL_STOP;
5246 }
5247
5248 return NL_SKIP;
5249
5250}
5251#endif
5252
5253INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
5254{
5255#ifdef HAL_NETLINK_IMPL
5256 Netlink nl = {0};
5257 char if_name[10] = {0};
5258 char interface_name[16] = {0};
5259
5260 wifi_device_info_t info = {0};
5261 info.wifi_devIndex = devIndex;
5262
5263 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5264 return RETURN_ERR;
5265
5266 snprintf(if_name,sizeof(if_name),"%s", interface_name);
5267
5268 nl.id = initSock80211(&nl);
5269
5270 if (nl.id < 0) {
5271 fprintf(stderr, "Error initializing netlink \n");
5272 return -1;
5273 }
5274
5275 struct nl_msg* msg = nlmsg_alloc();
5276
5277 if (!msg) {
5278 fprintf(stderr, "Failed to allocate netlink message.\n");
5279 nlfree(&nl);
5280 return -2;
5281 }
5282
5283 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +08005284 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +08005285 NL_AUTO_SEQ,
5286 nl.id,
5287 0,
5288 NLM_F_DUMP,
5289 NL80211_CMD_GET_STATION,
5290 0);
5291
5292 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +08005293 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +08005294 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
5295 nl_recvmsgs(nl.socket, nl.cb);
5296 nlmsg_free(msg);
5297 nlfree(&nl);
5298
5299 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
5300 output_struct->wifi_devRxRate = info.wifi_devRxRate;
5301 output_struct->wifi_devTxRate = info.wifi_devTxRate;
5302 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
5303 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
5304 return RETURN_OK;
5305#else
5306 //iw utility to retrieve station information
5307#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
5308#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
5309#define MACFILE "/tmp/wifi_AssoMac.txt"
5310#define TXRATEFILE "/tmp/wifi_txrate.txt"
5311#define RXRATEFILE "/tmp/wifi_rxrate.txt"
5312 FILE *file = NULL;
5313 char if_name[10] = {'\0'};
5314 char pipeCmd[256] = {'\0'};
5315 char line[256] = {0};
5316 char interface_name[16] = {0};
5317 int count = 0, device = 0;
5318
5319 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5320 return RETURN_ERR;
5321
5322 snprintf(if_name,sizeof(if_name),"%s", interface_name);
5323
5324 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
5325 file = popen(pipeCmd, "r");
5326
5327 if(file == NULL)
5328 return RETURN_ERR; //popen failed
5329
5330 fgets(line, sizeof line, file);
5331 device = atoi(line);
5332 pclose(file);
5333
5334 if(device == 0)
5335 return RETURN_ERR; //No devices are connected
5336
5337 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
5338 system(pipeCmd);
5339
5340 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
5341
5342 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
5343
5344 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
5345
5346 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
5347
5348 //devIndex starts from 1, ++count
5349 if((file = fopen(SIGNALFILE, "r")) != NULL )
5350 {
5351 for(count =0;fgets(line, sizeof line, file) != NULL;)
5352 {
5353 if (++count == devIndex)
5354 {
5355 output_struct->wifi_devSignalStrength = atoi(line);
5356 break;
5357 }
5358 }
5359 fclose(file);
5360 }
5361 else
5362 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
5363
5364 if((file = fopen(MACFILE, "r")) != NULL )
5365 {
5366 for(count =0;fgets(line, sizeof line, file) != NULL;)
5367 {
5368 if (++count == devIndex)
5369 {
5370 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]);
5371 break;
5372 }
5373 }
5374 fclose(file);
5375 }
5376 else
5377 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
5378
5379 if((file = fopen(TXRATEFILE, "r")) != NULL )
5380 {
5381 for(count =0;fgets(line, sizeof line, file) != NULL;)
5382 {
5383 if (++count == devIndex)
5384 {
5385 output_struct->wifi_devTxRate = atoi(line);
5386 break;
5387 }
5388 }
5389 fclose(file);
5390 }
5391 else
5392 fprintf(stderr,"fopen wifi_txrate.txt failed");
5393
5394 if((file = fopen(RXRATEFILE, "r")) != NULL)
5395 {
5396 for(count =0;fgets(line, sizeof line, file) != NULL;)
5397 {
5398 if (++count == devIndex)
5399 {
5400 output_struct->wifi_devRxRate = atoi(line);
5401 break;
5402 }
5403 }
5404 fclose(file);
5405 }
5406 else
5407 fprintf(stderr,"fopen wifi_rxrate.txt failed");
5408
5409 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
5410
5411 return RETURN_OK;
5412#endif
5413}
5414
5415INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
5416{
5417 if (NULL == device)
5418 return RETURN_ERR;
5419 return RETURN_OK;
5420}
5421//<<
5422
5423
5424//--------------wifi_ap_hal-----------------------------
5425//enables CTS protection for the radio used by this AP
5426INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
5427{
5428 //save config and Apply instantly
5429 return RETURN_ERR;
5430}
5431
5432// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
5433INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
5434{
5435 char config_file[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08005436 char config_dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08005437 char buf[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08005438 struct params list = {0};
5439 struct params dat = {0};
5440 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08005441
5442 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5443 list.name = "ht_coex";
5444 snprintf(buf, sizeof(buf), "%d", enable);
5445 list.value = buf;
5446
developerd1824452023-05-18 12:30:04 +08005447 dat.name = "HT_BSSCoexistence";
5448 dat.value = buf;
5449
5450 band = wifi_index_to_band(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005451 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerd1824452023-05-18 12:30:04 +08005452 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08005453 wifi_hostapdWrite(config_file, &list, 1);
developerd1824452023-05-18 12:30:04 +08005454 wifi_datfileWrite(config_dat_file, &list, 1);
developer72fb0bb2023-01-11 09:46:29 +08005455 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developerd1824452023-05-18 12:30:04 +08005456 wifi_reloadAp(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005457
5458 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5459
5460 return RETURN_OK;
5461}
5462
5463//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
5464INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
5465{
5466 char config_file[MAX_BUF_SIZE] = {'\0'};
5467 char buf[MAX_BUF_SIZE] = {'\0'};
5468 struct params list;
5469
5470 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5471 if (threshold < 256 || threshold > 2346 )
5472 return RETURN_ERR;
5473 list.name = "fragm_threshold";
5474 snprintf(buf, sizeof(buf), "%d", threshold);
5475 list.value = buf;
5476
5477 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5478 wifi_hostapdWrite(config_file, &list, 1);
5479 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5480
5481 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5482
5483 return RETURN_OK;
5484}
5485
5486// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
5487INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
5488{
5489 char config_file[64] = {'\0'};
5490 char cmd[512] = {'\0'};
5491 char buf[512] = {'\0'};
5492 char stbc_config[16] = {'\0'};
5493 wifi_band band;
5494 int iterator = 0;
5495 BOOL current_stbc = FALSE;
5496 int ant_count = 0;
5497 int ant_bitmap = 0;
5498 struct params list;
developera1255e42023-05-13 17:45:02 +08005499 char dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08005500
5501 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5502
5503 band = wifi_index_to_band(radioIndex);
5504 if (band == band_invalid)
5505 return RETURN_ERR;
5506
5507 if (band == band_2_4)
5508 iterator = 1;
developera1255e42023-05-13 17:45:02 +08005509 else if ((band == band_5) || (band == band_6))
developer72fb0bb2023-01-11 09:46:29 +08005510 iterator = 2;
5511 else
5512 return RETURN_OK;
5513
5514 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
5515 for (; ant_bitmap > 0; ant_bitmap >>= 1)
5516 ant_count += ant_bitmap & 1;
5517
5518 if (ant_count == 1 && STBC_Enable == TRUE) {
5519 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
5520 return RETURN_OK;
5521 }
5522
5523 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5524
5525 // set ht and vht config
5526 for (int i = 0; i < iterator; i++) {
5527 memset(stbc_config, 0, sizeof(stbc_config));
5528 memset(cmd, 0, sizeof(cmd));
5529 memset(buf, 0, sizeof(buf));
5530 list.name = (i == 0)?"ht_capab":"vht_capab";
5531 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
5532 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
5533 _syscmd(cmd, buf, sizeof(buf));
5534 if (strlen(buf) != 0)
5535 current_stbc = TRUE;
5536 if (current_stbc == STBC_Enable)
5537 continue;
5538
5539 if (STBC_Enable == TRUE) {
5540 // Append the STBC flags in capab config
5541 memset(cmd, 0, sizeof(cmd));
5542 if (i == 0)
5543 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
5544 else
5545 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
5546 _syscmd(cmd, buf, sizeof(buf));
5547 } else if (STBC_Enable == FALSE) {
5548 // Remove the STBC flags and remain other flags in capab
5549 memset(cmd, 0, sizeof(cmd));
5550 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5551 _syscmd(cmd, buf, sizeof(buf));
5552 memset(cmd, 0, sizeof(cmd));
5553 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
5554 _syscmd(cmd, buf, sizeof(buf));
5555 }
5556 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
5557 list.value = buf;
5558 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
5559 }
developera1255e42023-05-13 17:45:02 +08005560 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5561 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_STBC=.*/HT_STBC=%d/g' %s", STBC_Enable, dat_file);
5562 _syscmd(cmd, buf, sizeof(buf));
5563 if ((band == band_5) || (band == band_6)) {
5564 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^VHT_STBC=.*/VHT_STBC=%d/g' %s", STBC_Enable, dat_file);
5565 _syscmd(cmd, buf, sizeof(buf));
5566 }
5567 /*wifi_reloadAp(radioIndex);
5568 the caller do this.*/
developer72fb0bb2023-01-11 09:46:29 +08005569
5570 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5571 return RETURN_OK;
5572}
5573
5574// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
5575INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
5576{
5577 char cmd[128] = {0};
5578 char buf[128] = {0};
5579 char interface_name[16] = {0};
5580
5581 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5582
5583 if(output_bool == NULL)
5584 return RETURN_ERR;
5585
5586 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5587 return RETURN_ERR;
5588
5589 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
5590 _syscmd(cmd, buf, sizeof(buf));
5591
5592 if (strncmp(buf, "1", 1) == 0)
5593 *output_bool = TRUE;
5594 else
5595 *output_bool = FALSE;
5596
5597 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5598 return RETURN_OK;
5599}
5600
5601// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
5602INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
5603{
5604 char config_file[128] = {0};
5605 struct params list = {0};
5606 BOOL enable;
5607
5608 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5609
5610 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
5611 return RETURN_ERR;
5612
5613 if (amsduEnable == enable)
5614 return RETURN_OK;
5615
5616 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5617 list.name = "amsdu";
5618 list.value = amsduEnable? "1":"0";
5619 wifi_hostapdWrite(config_file, &list, 1);
5620 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
5621 wifi_reloadAp(radioIndex);
5622
5623 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5624 return RETURN_OK;
5625}
5626
5627//P2 // outputs the number of Tx streams
5628INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
5629{
5630 char buf[8] = {0};
5631 char cmd[128] = {0};
5632 int phyId = 0;
5633
5634 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5635
5636 phyId = radio_index_to_phy(radioIndex);
5637 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
5638 _syscmd(cmd, buf, sizeof(buf));
5639
5640 *output_int = (INT)strtol(buf, NULL, 16);
5641
5642 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5643
5644 return RETURN_OK;
5645}
5646
5647INT fitChainMask(INT radioIndex, int antcount)
5648{
5649 char buf[128] = {0};
5650 char cmd[128] = {0};
5651 char config_file[64] = {0};
5652 wifi_band band;
5653 struct params list[2] = {0};
5654
5655 band = wifi_index_to_band(radioIndex);
5656 if (band == band_invalid)
5657 return RETURN_ERR;
5658
5659 list[0].name = "he_mu_beamformer";
5660 list[1].name = "he_su_beamformer";
5661
5662 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5663 if (antcount == 1) {
5664 // remove config about multiple antennas
5665 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5666 _syscmd(cmd, buf, sizeof(buf));
5667
5668 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
5669 _syscmd(cmd, buf, sizeof(buf));
5670
5671 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
5672 _syscmd(cmd, buf, sizeof(buf));
5673
5674 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
5675 _syscmd(cmd, buf, sizeof(buf));
5676
5677 list[0].value = "0";
5678 list[1].value = "0";
5679 } else {
5680 // 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.
5681 if (band == band_2_4 || band == band_5) {
5682 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5683 _syscmd(cmd, buf, sizeof(buf));
5684 if (strlen(buf) > 0) {
5685 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
5686 _syscmd(cmd, buf, sizeof(buf));
5687 }
5688 }
5689 if (band == band_5) {
5690 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5691 _syscmd(cmd, buf, sizeof(buf));
5692 if (strlen(buf) > 0) {
5693 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
5694 _syscmd(cmd, buf, sizeof(buf));
5695 }
5696 }
5697
5698 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
5699 _syscmd(cmd, buf, sizeof(buf));
5700 if (strlen(buf) == 0) {
5701 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
5702 _syscmd(cmd, buf, sizeof(buf));
5703 }
5704
5705 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
5706 _syscmd(cmd, buf, sizeof(buf));
5707 if (strlen(buf) == 0) {
5708 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
5709 _syscmd(cmd, buf, sizeof(buf));
5710 }
5711
5712 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
5713 _syscmd(cmd, buf, sizeof(buf));
5714 if (strlen(buf) == 0) {
5715 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
5716 } else {
5717 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
5718 }
5719 _syscmd(cmd, buf, sizeof(buf));
5720
5721 list[0].value = "1";
5722 list[1].value = "1";
5723 }
5724 wifi_hostapdWrite(config_file, list, 2);
5725}
5726
5727//P2 // sets the number of Tx streams to an enviornment variable
5728INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5729{
5730 char cmd[128] = {0};
5731 char buf[128] = {0};
5732 int phyId = 0;
5733 int cur_mask = 0;
developera1255e42023-05-13 17:45:02 +08005734 int antcountmsk = 0;
5735 INT cur_nss = 0;
5736 UCHAR dat_file[64] = {0};
5737 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08005738
5739 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5740
5741 if (numStreams <= 0) {
5742 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
5743 return RETURN_ERR;
5744 }
5745
developera1255e42023-05-13 17:45:02 +08005746 wifi_getRadioTxChainMask(radioIndex, &cur_mask);//this is mask value
5747 for(; cur_mask > 0; cur_mask >>= 1)//convert to number of streams.
5748 cur_nss += 1;
5749 WIFI_ENTRY_EXIT_DEBUG("%s:cur_nss=%d, new_nss=%d\n", __func__, cur_nss, numStreams);
5750 if (cur_nss == numStreams)
developer72fb0bb2023-01-11 09:46:29 +08005751 return RETURN_OK;
5752
5753 wifi_setRadioEnable(radioIndex, FALSE);
5754
5755 phyId = radio_index_to_phy(radioIndex);
developera1255e42023-05-13 17:45:02 +08005756 //iw need mask value.
5757 for (;numStreams > 0; numStreams--)
5758 antcountmsk |= 0x1 << (numStreams - 1);
5759 snprintf(cmd, sizeof(cmd), "iw phy%d set antenna 0x%x 2>&1", phyId, antcountmsk);
developer72fb0bb2023-01-11 09:46:29 +08005760 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005761 if (strlen(buf) > 0) {
5762 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5763 return RETURN_ERR;
5764 }
developera1255e42023-05-13 17:45:02 +08005765 band = wifi_index_to_band(radioIndex);
5766 if (band == band_invalid) {
5767 printf("%s:Band Error\n", __func__);
5768 return RETURN_ERR;
5769 }
5770 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5771 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_TxStream=.*/HT_TxStream=%d/g' %s", numStreams, dat_file);
5772 _syscmd(cmd, buf, sizeof(buf));
5773 if (strlen(buf) > 0) {
5774 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5775 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08005776 }
developera1255e42023-05-13 17:45:02 +08005777 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_RxStream=.*/HT_RxStream=%d/g' %s", numStreams, dat_file);
5778 _syscmd(cmd, buf, sizeof(buf));
5779 if (strlen(buf) > 0) {
5780 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5781 return RETURN_ERR;
5782 }
5783 fitChainMask(radioIndex, numStreams);
developer72fb0bb2023-01-11 09:46:29 +08005784 wifi_setRadioEnable(radioIndex, TRUE);
5785
5786 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5787 return RETURN_OK;
5788}
5789
5790//P2 // outputs the number of Rx streams
5791INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5792{
5793 char buf[8] = {0};
5794 char cmd[128] = {0};
5795 int phyId = 0;
5796
5797 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5798
5799 phyId = radio_index_to_phy(radioIndex);
5800 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5801 _syscmd(cmd, buf, sizeof(buf));
5802
5803 *output_int = (INT)strtol(buf, NULL, 16);
5804
5805 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5806
5807 return RETURN_OK;
5808}
5809
5810//P2 // sets the number of Rx streams to an enviornment variable
5811INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5812{
5813 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5814 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5815 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5816 return RETURN_ERR;
5817 }
5818 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5819 return RETURN_ERR;
5820}
5821
5822//Get radio RDG enable setting
5823INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5824{
developer47cc27a2023-05-17 23:09:58 +08005825 if (NULL == output_bool)
5826 return RETURN_ERR;
5827
5828 *output_bool = TRUE;
5829 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005830}
5831
5832//Get radio RDG enable setting
5833INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5834{
developer47cc27a2023-05-17 23:09:58 +08005835 char cmd[MAX_CMD_SIZE] = {0};
5836 char buf[MAX_BUF_SIZE] = {0};
5837 char rdg_status[2] = {0};
5838 char dat_file[MAX_CMD_SIZE] = {0};
5839 struct params params = {0};
5840
5841 if (NULL == output_bool)
5842 return RETURN_ERR;
5843
5844 /*prepare dat file path*/
5845 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
5846
5847 wifi_datfileRead(dat_file, "HT_RDG", rdg_status, sizeof(rdg_status));
5848 if (!strncmp(rdg_status, "1", sizeof(rdg_status)))
5849 *output_bool = TRUE;
5850 else
5851 *output_bool = FALSE;
5852
5853 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005854}
5855
5856//Set radio RDG enable setting
5857INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5858{
developer47cc27a2023-05-17 23:09:58 +08005859 char cmd[MAX_CMD_SIZE] = {0};
5860 char buf[MAX_BUF_SIZE] = {0};
5861 char dat_file[MAX_CMD_SIZE] = {0};
5862 struct params params = {0};
5863
5864 /*prepare dat file path*/
5865 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
5866
5867 params.name = "HT_RDG";
5868
5869 if (enable) {
5870 params.value = "1";
5871 } else {
5872 params.value = "0";
5873 }
5874
5875 wifi_datfileWrite(dat_file, &params, 1);
5876
5877 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005878}
5879
5880//Get radio ADDBA enable setting
5881INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5882{
5883 if (NULL == output_bool)
5884 return RETURN_ERR;
5885 *output_bool = TRUE;
5886 return RETURN_OK;
5887}
5888
5889//Set radio ADDBA enable setting
5890INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5891{
5892 return RETURN_ERR;
5893}
5894
5895//Get radio auto block ack enable setting
5896INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5897{
5898 if (NULL == output_bool)
5899 return RETURN_ERR;
5900 *output_bool = TRUE;
5901 return RETURN_OK;
5902}
5903
5904//Set radio auto block ack enable setting
5905INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5906{
5907 return RETURN_ERR;
5908}
5909
5910//Get radio 11n pure mode enable support
5911INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5912{
5913 if (NULL == output_bool)
5914 return RETURN_ERR;
5915 *output_bool = TRUE;
5916 return RETURN_OK;
5917}
5918
5919//Get radio 11n pure mode enable setting
5920INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5921{
5922 if (NULL == output_bool)
5923 return RETURN_ERR;
5924 *output_bool = TRUE;
5925 return RETURN_OK;
5926}
5927
5928//Set radio 11n pure mode enable setting
5929INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5930{
5931 return RETURN_ERR;
5932}
5933
5934//Get radio IGMP snooping enable setting
5935INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5936{
5937 char interface_name[16] = {0};
5938 char cmd[128]={0};
5939 char buf[4]={0};
5940 bool bridge = FALSE, mac80211 = FALSE;
5941 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5942
5943 if(output_bool == NULL)
5944 return RETURN_ERR;
5945
5946 *output_bool = FALSE;
5947
5948 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5949 _syscmd(cmd, buf, sizeof(buf));
5950 if (strncmp(buf, "1", 1) == 0)
5951 bridge = TRUE;
5952
5953 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5954 return RETURN_ERR;
5955 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
5956 _syscmd(cmd, buf, sizeof(buf));
5957 if (strncmp(buf, "1", 1) == 0)
5958 mac80211 = TRUE;
5959
5960 if (bridge && mac80211)
5961 *output_bool = TRUE;
5962
5963 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5964 return RETURN_OK;
5965}
5966
5967//Set radio IGMP snooping enable setting
5968INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5969{
5970 char interface_name[16] = {0};
5971 char cmd[128]={0};
5972 char buf[4]={0};
5973 int max_num_radios =0;
5974 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5975
5976 // bridge
5977 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
5978 _syscmd(cmd, buf, sizeof(buf));
5979
5980 wifi_getMaxRadioNumber(&max_num_radios);
5981 // mac80211
5982 for (int i = 0; i < max_num_radios; i++) {
5983 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
5984 return RETURN_ERR;
5985 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
5986 _syscmd(cmd, buf, sizeof(buf));
5987 }
5988 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5989 return RETURN_OK;
5990}
5991
5992//Get the Reset count of radio
developer69b61b02023-03-07 17:17:44 +08005993INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
developer72fb0bb2023-01-11 09:46:29 +08005994{
developer69b61b02023-03-07 17:17:44 +08005995 if (NULL == output_int)
developer72fb0bb2023-01-11 09:46:29 +08005996 return RETURN_ERR;
5997 *output_int = (radioIndex==0)? 1: 3;
5998
5999 return RETURN_OK;
6000}
6001
6002
6003//---------------------------------------------------------------------------------------------------
6004//
6005// Additional Wifi AP level APIs used for Access Point devices
6006//
6007//---------------------------------------------------------------------------------------------------
6008
6009// creates a new ap and pushes these parameters to the hardware
6010INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
6011{
6012 // Deprecated when use hal version 3, use wifi_createVap() instead.
6013 return RETURN_OK;
6014}
6015
6016// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
6017INT wifi_deleteAp(INT apIndex)
6018{
developer7e4a2a62023-04-06 19:56:03 +08006019 char interface_name[16] = {0};
6020 char buf[MAX_BUF_SIZE];
6021 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08006022
developer7e4a2a62023-04-06 19:56:03 +08006023 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6024 return RETURN_ERR;
developer8a3bbbf2023-03-15 17:47:23 +08006025
developer7e4a2a62023-04-06 19:56:03 +08006026 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
6027 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006028
developer7e4a2a62023-04-06 19:56:03 +08006029 wifi_removeApSecVaribles(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006030
developer7e4a2a62023-04-06 19:56:03 +08006031 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006032}
6033
6034// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
6035INT wifi_getApName(INT apIndex, CHAR *output_string)
6036{
developer7e4a2a62023-04-06 19:56:03 +08006037 char interface_name[IF_NAME_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08006038 int radio_idx = 0;
6039 int bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08006040
developer7e4a2a62023-04-06 19:56:03 +08006041 if(!output_string)
6042 return RETURN_ERR;
6043
6044 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
6045 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
6046
6047 snprintf(output_string, IF_NAME_SIZE, "%s%d", ext_prefix[radio_idx], bss_idx); // For wifiagent generating data model.
6048 } else
6049 snprintf(output_string, IF_NAME_SIZE, "%s", interface_name);
6050
6051 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006052}
6053
6054// Outputs the index number in that corresponds to the SSID string
6055INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
6056{
developer7e4a2a62023-04-06 19:56:03 +08006057 char cmd [128] = {0};
6058 char buf[32] = {0};
6059 char ap_idx = 0;
6060 char *apIndex_str = NULL;
6061 char radio_idx = 0;
6062 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08006063
developer7e4a2a62023-04-06 19:56:03 +08006064 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'",
6065 inputSsidString);
6066 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006067
developer7e4a2a62023-04-06 19:56:03 +08006068 if (strlen(buf)) {
6069 apIndex_str = strtok(buf, "\n");
6070 *output_int = strtoul(apIndex_str, NULL, 10);
6071 return RETURN_OK;
6072 }
developer72fb0bb2023-01-11 09:46:29 +08006073
developer7e4a2a62023-04-06 19:56:03 +08006074 /* If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.*/
6075 if (strstr(inputSsidString, PREFIX_WIFI6G)) {
6076 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI6G));
6077 radio_idx = 2;
6078 } else if (strstr(inputSsidString, PREFIX_WIFI5G)) {
6079 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI5G));
6080 radio_idx = 1;
6081 } else if (strstr(inputSsidString, PREFIX_WIFI2G)) {
6082 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI2G));
6083 radio_idx = 0;
6084 } else {
6085 printf("%s: hostapd conf not find, unknow inf(%s), return ERROR!!!(%d).\n",
6086 __func__, inputSsidString, ap_idx);
6087 *output_int = -1;
6088 return RETURN_ERR;
6089 }
6090
6091 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
6092
6093 if (ap_idx >= 0 && ap_idx < MAX_VAP) {
6094 printf("%s: hostapd conf not find, inf(%s), use inf idx(%d).\n",
6095 __func__, inputSsidString, ap_idx);
6096 *output_int = ap_idx;
6097 return RETURN_OK;
6098 }
6099
6100 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006101}
6102
6103INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
6104{
6105 return wifi_getIndexFromName(inputSsidString, output_int);
6106}
6107
6108// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
6109INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
6110{
6111 char buf[MAX_BUF_SIZE] = {0};
6112 char cmd[MAX_CMD_SIZE] = {0};
6113 char config_file[MAX_BUF_SIZE] = {0};
6114
6115 if(NULL == output_string)
6116 return RETURN_ERR;
6117
6118 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6119 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
6120 if((strcmp(buf,"3")==0))
6121 snprintf(output_string, 32, "WPAand11i");
6122 else if((strcmp(buf,"2")==0))
6123 snprintf(output_string, 32, "11i");
6124 else if((strcmp(buf,"1")==0))
6125 snprintf(output_string, 32, "WPA");
6126 else
6127 snprintf(output_string, 32, "None");
6128
6129 return RETURN_OK;
6130}
6131
6132// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
6133INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
6134{
6135 char config_file[MAX_BUF_SIZE] = {0};
6136 struct params list;
6137
6138 if (NULL == beaconTypeString)
6139 return RETURN_ERR;
6140 list.name = "wpa";
6141 list.value = "0";
6142
6143 if((strcmp(beaconTypeString,"WPAand11i")==0))
6144 list.value="3";
6145 else if((strcmp(beaconTypeString,"11i")==0))
6146 list.value="2";
6147 else if((strcmp(beaconTypeString,"WPA")==0))
6148 list.value="1";
6149
6150 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6151 wifi_hostapdWrite(config_file, &list, 1);
6152 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6153 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6154 return RETURN_OK;
6155}
6156
6157// sets the beacon interval on the hardware for this AP
6158INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
6159{
6160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6161 struct params params={'\0'};
6162 char buf[MAX_BUF_SIZE] = {'\0'};
6163 char config_file[MAX_BUF_SIZE] = {'\0'};
6164
6165 params.name = "beacon_int";
6166 snprintf(buf, sizeof(buf), "%u", beaconInterval);
6167 params.value = buf;
6168
6169 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6170 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08006171
developer72fb0bb2023-01-11 09:46:29 +08006172 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6173 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6174 return RETURN_OK;
6175}
6176
6177INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
6178{
6179 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
6180 return RETURN_ERR;
6181 return RETURN_OK;
6182}
6183
6184// Get the packet size threshold supported.
6185INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
6186{
6187 //save config and apply instantly
6188 if (NULL == output_bool)
6189 return RETURN_ERR;
6190 *output_bool = TRUE;
6191 return RETURN_OK;
6192}
6193
6194// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
6195INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
6196{
developer72fb0bb2023-01-11 09:46:29 +08006197 char buf[16] = {0};
6198 char config_file[128] = {0};
6199 struct params param = {0};
6200
6201 if (threshold > 65535) {
6202 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
6203 return RETURN_ERR;
6204 }
6205
developer23e71282023-01-18 10:25:19 +08006206 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006207 snprintf(buf, sizeof(buf), "%u", threshold);
6208 param.name = "rts_threshold";
6209 param.value = buf;
6210 wifi_hostapdWrite(config_file, &param, 1);
6211 wifi_hostapdProcessUpdate(apIndex, &param, 1);
6212 wifi_reloadAp(apIndex);
6213
6214 return RETURN_OK;
6215}
6216
6217// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
6218INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
6219{
6220 if (NULL == output_string)
6221 return RETURN_ERR;
6222 snprintf(output_string, 32, "TKIPandAESEncryption");
6223 return RETURN_OK;
6224
6225}
6226
6227// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
6228INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
6229{
6230 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6231 char *param_name = NULL;
6232 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
6233
6234 if(NULL == output_string)
6235 return RETURN_ERR;
6236
6237 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6238 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6239
6240 if(strcmp(buf,"0")==0)
6241 {
6242 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
6243 snprintf(output_string, 32, "None");
6244 return RETURN_OK;
6245 }
6246 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
6247 param_name = "rsn_pairwise";
6248 else if((strcmp(buf,"1")==0))
6249 param_name = "wpa_pairwise";
6250 else
6251 return RETURN_ERR;
6252 memset(output_string,'\0',32);
6253 wifi_hostapdRead(config_file,param_name,output_string,32);
6254 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
6255 param_name = "wpa_pairwise";
6256 memset(output_string, '\0', 32);
6257 wifi_hostapdRead(config_file, param_name, output_string, 32);
6258 }
6259 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
6260
developere5750452023-05-15 16:46:42 +08006261 if(strcmp(output_string,"TKIP CCMP") == 0)
6262 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
6263 else if(strcmp(output_string,"TKIP") == 0)
developer72fb0bb2023-01-11 09:46:29 +08006264 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
6265 else if(strcmp(output_string,"CCMP") == 0)
6266 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer72fb0bb2023-01-11 09:46:29 +08006267
6268 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6269 return RETURN_OK;
6270}
6271
6272// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
6273INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
6274{
6275 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6276 struct params params={'\0'};
6277 char output_string[32];
6278 char config_file[MAX_BUF_SIZE] = {0};
6279
6280 memset(output_string,'\0',32);
developere5750452023-05-15 16:46:42 +08006281 wifi_getApBeaconType(apIndex,output_string);
developer72fb0bb2023-01-11 09:46:29 +08006282
6283 if(strcmp(encMode, "TKIPEncryption") == 0)
6284 params.value = "TKIP";
6285 else if(strcmp(encMode,"AESEncryption") == 0)
6286 params.value = "CCMP";
6287 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
6288 params.value = "TKIP CCMP";
6289
6290 if((strcmp(output_string,"WPAand11i")==0))
6291 {
6292 params.name = "wpa_pairwise";
6293 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6294 wifi_hostapdWrite(config_file, &params, 1);
6295 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6296
6297 params.name = "rsn_pairwise";
6298 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6299 wifi_hostapdWrite(config_file, &params, 1);
6300 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6301
6302 return RETURN_OK;
6303 }
6304 else if((strcmp(output_string,"11i")==0))
6305 {
6306 params.name = "rsn_pairwise";
6307 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6308 wifi_hostapdWrite(config_file, &params, 1);
6309 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6310 return RETURN_OK;
6311 }
6312 else if((strcmp(output_string,"WPA")==0))
6313 {
6314 params.name = "wpa_pairwise";
6315 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6316 wifi_hostapdWrite(config_file, &params, 1);
6317 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6318 return RETURN_OK;
6319 }
6320
6321 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6322 return RETURN_OK;
6323}
6324
6325// deletes internal security varable settings for this ap
6326INT wifi_removeApSecVaribles(INT apIndex)
6327{
6328 //TODO: remove the entry in hostapd config file
6329 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
6330 //_syscmd(cmd, buf, sizeof(buf));
6331
6332 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
6333 //_syscmd(cmd, buf, sizeof(buf));
6334 return RETURN_ERR;
6335}
6336
6337// changes the hardware settings to disable encryption on this ap
6338INT wifi_disableApEncryption(INT apIndex)
6339{
6340 //Apply instantly
6341 return RETURN_ERR;
6342}
6343
6344// set the authorization mode on this ap
6345// mode mapping as: 1: open, 2: shared, 4:auto
6346INT wifi_setApAuthMode(INT apIndex, INT mode)
6347{
6348 struct params params={0};
6349 char config_file[64] = {0};
6350 int ret;
6351
6352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6353
6354 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
6355 params.name = "auth_algs";
6356
developere5750452023-05-15 16:46:42 +08006357 if ((mode & 1 && mode & 2) || mode & 4)
developer72fb0bb2023-01-11 09:46:29 +08006358 params.value = "3";
6359 else if (mode & 2)
6360 params.value = "2";
6361 else if (mode & 1)
6362 params.value = "1";
6363 else
6364 params.value = "0";
6365
6366 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6367 wifi_hostapdWrite(config_file, &params, 1);
6368 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08006369 wifi_reloadAp(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006370 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6371
6372 return RETURN_OK;
6373}
6374
6375// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
6376INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
6377{
6378 //save to wifi config, and wait for wifi restart to apply
6379 struct params params={'\0'};
6380 char config_file[MAX_BUF_SIZE] = {0};
6381 int ret;
6382
6383 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6384 if(authMode == NULL)
6385 return RETURN_ERR;
6386
6387 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
6388 params.name = "wpa_key_mgmt";
6389
6390 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
6391 params.value = "WPA-PSK";
6392 else if(strcmp(authMode,"EAPAuthentication") == 0)
6393 params.value = "WPA-EAP";
6394 else if (strcmp(authMode, "SAEAuthentication") == 0)
6395 params.value = "SAE";
6396 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
6397 params.value = "WPA-EAP-SUITE-B-192";
6398 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
6399 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08006400 else if (strcmp(authMode, "Enhanced_Open") == 0)
6401 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08006402 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
6403 return RETURN_OK; //This is taken careof in beaconType
6404
6405 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6406 ret=wifi_hostapdWrite(config_file,&params,1);
6407 if(!ret)
6408 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
6409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6410
6411 return ret;
6412}
6413
6414// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
6415INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
6416{
6417 //save to wifi config, and wait for wifi restart to apply
6418 char BeaconType[50] = {0};
6419 char config_file[MAX_BUF_SIZE] = {0};
6420
6421 *authMode = 0;
6422 wifi_getApBeaconType(apIndex,BeaconType);
6423 printf("%s____%s \n",__FUNCTION__,BeaconType);
6424
6425 if(strcmp(BeaconType,"None") == 0)
6426 strcpy(authMode,"None");
6427 else
6428 {
6429 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6430 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
6431 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
6432 if(strcmp(authMode,"WPA-PSK") == 0)
6433 strcpy(authMode,"SharedAuthentication");
6434 else if(strcmp(authMode,"WPA-EAP") == 0)
6435 strcpy(authMode,"EAPAuthentication");
6436 }
6437
6438 return RETURN_OK;
6439}
6440
6441// Outputs the number of stations associated per AP
6442INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
6443{
6444 char interface_name[16] = {0};
6445 char cmd[128]={0};
6446 char buf[128]={0};
6447 BOOL status = false;
6448
6449 if(apIndex > MAX_APS)
6450 return RETURN_ERR;
6451
6452 wifi_getApEnable(apIndex,&status);
6453 if (!status)
6454 return RETURN_OK;
6455
6456 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
6457 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6458 return RETURN_ERR;
6459 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
6460 _syscmd(cmd, buf, sizeof(buf));
6461 sscanf(buf,"%lu", output_ulong);
6462
6463 return RETURN_OK;
6464}
6465
6466// manually removes any active wi-fi association with the device specified on this ap
6467INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
6468{
developer7e4a2a62023-04-06 19:56:03 +08006469 char inf_name[16] = {0};
6470 char cmd[MAX_CMD_SIZE] = {0};
6471 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006472
developer7e4a2a62023-04-06 19:56:03 +08006473 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08006474 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08006475
6476 snprintf(cmd, sizeof(cmd),"hostapd_cli -i %s disassociate %s", inf_name, client_mac);
6477 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006478
6479 return RETURN_OK;
6480}
6481
6482// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
6483INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
6484{
developer7e4a2a62023-04-06 19:56:03 +08006485 int max_radio_num = 0;
6486
6487 if(NULL == output_int)
6488 return RETURN_ERR;
6489
6490 wifi_getMaxRadioNumber(&max_radio_num);
6491 *output_int = apIndex % max_radio_num;
6492
6493 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006494}
6495
6496// sets the radio index for the specific ap
6497INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
6498{
6499 //set to config only and wait for wifi reset to apply settings
6500 return RETURN_ERR;
6501}
6502
6503// Get the ACL MAC list per AP
6504INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
6505{
developer7e4a2a62023-04-06 19:56:03 +08006506 char cmd[MAX_CMD_SIZE] = {0};
6507 char buf[MAX_BUF_SIZE] = {0};
6508 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006509
developer7e4a2a62023-04-06 19:56:03 +08006510 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6511 return RETURN_ERR;
6512
6513 /* mwctl acl del sta */
6514 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | grep ':'", inf_name);
6515 _syscmd(cmd, buf, sizeof(buf));
6516
6517 memcpy(macArray, buf, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08006518
6519 return RETURN_OK;
6520}
6521
6522INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
6523{
developer72fb0bb2023-01-11 09:46:29 +08006524
developer7e4a2a62023-04-06 19:56:03 +08006525 wifi_getApAclDevices(apIndex, macArray, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08006526
6527 return RETURN_OK;
6528}
6529
6530
6531// Get the list of stations associated per AP
6532INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
6533{
developer7e4a2a62023-04-06 19:56:03 +08006534 char interface_name[IF_NAME_SIZE] = {0};
6535 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08006536
developer7e4a2a62023-04-06 19:56:03 +08006537 if(apIndex > 3) //Currently supporting apIndex upto 3
6538 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006539
developer7e4a2a62023-04-06 19:56:03 +08006540 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6541 return RETURN_ERR;
6542
6543 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s list_sta", interface_name);
6544 _syscmd(cmd, macArray, buf_size);
6545 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006546}
6547
developer8dd72532023-05-17 19:58:35 +08006548int hex2num(char c)
6549{
6550 if (c >= '0' && c <= '9')
6551 return c - '0';
6552 if (c >= 'a' && c <= 'f')
6553 return c - 'a' + 10;
6554 if (c >= 'A' && c <= 'F')
6555 return c - 'A' + 10;
6556 return -1;
6557}
6558
6559/**
6560 * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
6561 * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
6562 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
6563 * Returns: Characters used (> 0) on success, -1 on failure
6564 */
6565int hwaddr_aton2(const char *txt, unsigned char *addr)
6566{
6567 int i;
6568 const char *pos = txt;
6569
6570 for (i = 0; i < 6; i++) {
6571 int a, b;
6572
6573 while (*pos == ':' || *pos == '.' || *pos == '-')
6574 pos++;
6575
6576 a = hex2num(*pos++);
6577 if (a < 0)
6578 return -1;
6579 b = hex2num(*pos++);
6580 if (b < 0)
6581 return -1;
6582 *addr++ = (a << 4) | b;
6583 }
6584
6585 return pos - txt;
6586}
6587
developer72fb0bb2023-01-11 09:46:29 +08006588// adds the mac address to the filter list
6589//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
6590INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
6591{
developer7e4a2a62023-04-06 19:56:03 +08006592 char cmd[MAX_CMD_SIZE] = {0};
6593 char buf[MAX_BUF_SIZE] = {0};
6594 char inf_name[IF_NAME_SIZE] = {0};
developer8dd72532023-05-17 19:58:35 +08006595 int if_idx, ret = 0;
6596 struct nl_msg *msg;
6597 void *data;
6598 unsigned char mac[ETH_ALEN] = {0x00, 0x0c, 0x43, 0x11, 0x22, 0x33};
6599 struct unl unl_ins;
developer72fb0bb2023-01-11 09:46:29 +08006600
developer7e4a2a62023-04-06 19:56:03 +08006601 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6602 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08006603 if (!DeviceMacAddress)
6604 return RETURN_ERR;
6605
developer8dd72532023-05-17 19:58:35 +08006606 if (hwaddr_aton2(DeviceMacAddress, mac) < 0) {
6607 printf("error device mac address=%s\n", DeviceMacAddress);
6608 return RETURN_ERR;
6609 }
developer72fb0bb2023-01-11 09:46:29 +08006610
developer8dd72532023-05-17 19:58:35 +08006611 if_idx = if_nametoindex(inf_name);
6612 if (unl_genl_init(&unl_ins, "nl80211") < 0) {
6613 (void)fprintf(stderr, "Failed to connect to nl80211\n");
6614 return RETURN_ERR;
6615 }
6616
6617 msg = unl_genl_msg(&unl_ins, NL80211_CMD_VENDOR, false);
6618
6619 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_idx) ||
6620 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, MTK_NL80211_VENDOR_ID) ||
6621 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_SET_ACL)) {
6622 nlmsg_free(msg);
6623 goto err;
6624 }
6625
6626 data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
6627 if (!data)
6628 goto err;
6629
6630 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_ACL_ADD_MAC, ETH_ALEN, mac)) {
6631 printf("Nla put attribute error\n");
6632 goto err;
6633 }
6634
6635 nla_nest_end(msg, data);
6636
6637 ret = unl_genl_request(&unl_ins, msg, NULL, NULL);
6638 unl_free(&unl_ins);
6639 return RETURN_OK;
6640err:
6641 nlmsg_free(msg);
6642 unl_free(&unl_ins);
6643 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006644}
6645
6646// deletes the mac address from the filter list
6647//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
6648INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
6649{
developer7e4a2a62023-04-06 19:56:03 +08006650 char cmd[MAX_CMD_SIZE] = {0};
6651 char buf[MAX_BUF_SIZE] = {0};
6652 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006653
developer7e4a2a62023-04-06 19:56:03 +08006654 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6655 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006656
developer7e4a2a62023-04-06 19:56:03 +08006657 if (!DeviceMacAddress)
6658 return RETURN_ERR;
6659
6660 /* mwctl acl del sta */
6661 snprintf(cmd, sizeof(cmd), "mwctl %s acl del=%s", inf_name, DeviceMacAddress);
6662 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006663
6664 return RETURN_OK;
6665}
6666
6667// outputs the number of devices in the filter list
6668INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
6669{
developer7e4a2a62023-04-06 19:56:03 +08006670 char cmd[MAX_CMD_SIZE] = {0};
6671 char buf[MAX_BUF_SIZE] = {0};
6672 char inf_name[IF_NAME_SIZE] = {0};
6673 char sta_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08006674
developer72fb0bb2023-01-11 09:46:29 +08006675 if(output_uint == NULL)
6676 return RETURN_ERR;
6677
developer7e4a2a62023-04-06 19:56:03 +08006678 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6679 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006680
developer7e4a2a62023-04-06 19:56:03 +08006681 /* mwctl acl get sta num */
6682 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | wc -l | tr -d '\\n'", inf_name);
6683 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006684
developer7e4a2a62023-04-06 19:56:03 +08006685 if (atoi(buf) > 1)
6686 *output_uint = atoi(buf) - 1; /*except the line of acl_policy*/
6687 else {
6688 *output_uint = 0;
6689 printf("%s: acl get wrong return content!!!\n", __func__);
6690 }
6691
6692 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006693}
6694
6695INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
6696{
6697 char cmd[128]={'\0'};
6698 char buf[128]={'\0'};
6699
6700 if(strcmp(action,"DENY")==0)
6701 {
6702 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
6703 system(buf);
6704 return RETURN_OK;
6705 }
6706
6707 if(strcmp(action,"ALLOW")==0)
6708 {
6709 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
6710 system(buf);
6711 return RETURN_OK;
6712 }
6713
6714 return RETURN_ERR;
6715
6716}
6717
6718// enable kick for devices on acl black list
6719INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
6720{
developer47cc27a2023-05-17 23:09:58 +08006721 char aclArray[MAX_BUF_SIZE] = {0}, *acl = NULL;
6722 char assocArray[MAX_BUF_SIZE] = {0}, *asso = NULL;
developer72fb0bb2023-01-11 09:46:29 +08006723
6724 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
6725 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
6726
developer7e4a2a62023-04-06 19:56:03 +08006727 /* if there are no devices connected there is nothing to do */
developer72fb0bb2023-01-11 09:46:29 +08006728 if (strlen(assocArray) < 17)
6729 return RETURN_OK;
6730
developer7e4a2a62023-04-06 19:56:03 +08006731 if (enable == TRUE) {
6732 /* kick off the MAC which is in ACL array (deny list) */
6733 acl = strtok(aclArray, "\n");
developer72fb0bb2023-01-11 09:46:29 +08006734 while (acl != NULL) {
6735 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
6736 wifi_kickApAssociatedDevice(apIndex, acl);
6737
developer7e4a2a62023-04-06 19:56:03 +08006738 acl = strtok(NULL, "\n");
developer72fb0bb2023-01-11 09:46:29 +08006739 }
6740 wifi_setApMacAddressControlMode(apIndex, 2);
developer7e4a2a62023-04-06 19:56:03 +08006741 } else
developer72fb0bb2023-01-11 09:46:29 +08006742 wifi_setApMacAddressControlMode(apIndex, 0);
developer72fb0bb2023-01-11 09:46:29 +08006743
developer72fb0bb2023-01-11 09:46:29 +08006744 return RETURN_OK;
6745}
6746
6747INT wifi_setPreferPrivateConnection(BOOL enable)
6748{
6749 return RETURN_OK;
6750}
6751
6752// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
6753INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
6754{
developer7e4a2a62023-04-06 19:56:03 +08006755 char inf_name[IF_NAME_SIZE] = {0};
6756 char cmd[MAX_CMD_SIZE] = {0};
6757 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006758
developer7e4a2a62023-04-06 19:56:03 +08006759 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6760 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006761
developer7e4a2a62023-04-06 19:56:03 +08006762 /*mwctl set acl policy*/
6763 snprintf(cmd, sizeof(cmd), "mwctl %s acl policy=%d", inf_name, filterMode);
6764 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006765
developer7e4a2a62023-04-06 19:56:03 +08006766 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006767}
6768
6769// 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.
6770INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6771{
6772 return RETURN_ERR;
6773}
6774
6775// gets the vlan ID for this ap from an internal enviornment variable
6776INT wifi_getApVlanID(INT apIndex, INT *output_int)
6777{
6778 if(apIndex==0)
6779 {
6780 *output_int=100;
6781 return RETURN_OK;
6782 }
6783
6784 return RETURN_ERR;
6785}
6786
6787// sets the vlan ID for this ap to an internal enviornment variable
6788INT wifi_setApVlanID(INT apIndex, INT vlanId)
6789{
6790 //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)
6791 return RETURN_ERR;
6792}
6793
6794// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6795INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6796{
6797 snprintf(bridgeName, 32, "brlan0");
6798 snprintf(IP, 32, "10.0.0.1");
6799 snprintf(subnet, 32, "255.255.255.0");
6800
6801 return RETURN_OK;
6802}
6803
6804//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6805INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6806{
6807 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6808 return RETURN_ERR;
6809}
6810
6811// reset the vlan configuration for this ap
6812INT wifi_resetApVlanCfg(INT apIndex)
6813{
6814 char original_config_file[64] = {0};
6815 char current_config_file[64] = {0};
6816 char buf[64] = {0};
6817 char cmd[64] = {0};
6818 char vlan_file[64] = {0};
6819 char vlan_tagged_interface[16] = {0};
6820 char vlan_bridge[16] = {0};
6821 char vlan_naming[16] = {0};
6822 struct params list[4] = {0};
6823 wifi_band band;
developera1255e42023-05-13 17:45:02 +08006824 char interface_name[16] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006825
6826 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08006827 band = wifi_index_to_band(apIndex);
6828 if (band == band_2_4)
developera1255e42023-05-13 17:45:02 +08006829 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-2G.conf");
developer72fb0bb2023-01-11 09:46:29 +08006830 else if (band == band_5)
developera1255e42023-05-13 17:45:02 +08006831 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-5G.conf");
developer72fb0bb2023-01-11 09:46:29 +08006832 else if (band == band_6)
developera1255e42023-05-13 17:45:02 +08006833 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-6G.conf");
developer72fb0bb2023-01-11 09:46:29 +08006834
6835 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6836
6837 if (strlen(vlan_file) == 0)
6838 strcpy(vlan_file, VLAN_FILE);
6839
6840 // The file should exist or this vap would not work.
6841 if (access(vlan_file, F_OK) != 0) {
developera1255e42023-05-13 17:45:02 +08006842 snprintf(cmd, sizeof(cmd), "touch %s", vlan_file);
developer72fb0bb2023-01-11 09:46:29 +08006843 _syscmd(cmd, buf, sizeof(buf));
6844 }
6845 list[0].name = "vlan_file";
6846 list[0].value = vlan_file;
6847
6848 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6849 list[1].name = "vlan_tagged_interface";
6850 list[1].value = vlan_tagged_interface;
6851
6852 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6853 list[2].name = "vlan_bridge";
6854 list[2].value = vlan_bridge;
6855
6856 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6857 list[3].name = "vlan_naming";
6858 list[3].value = vlan_naming;
6859
developera1255e42023-05-13 17:45:02 +08006860 snprintf(current_config_file, sizeof(current_config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006861 wifi_hostapdWrite(current_config_file, list, 4);
6862 //Reapply vlan settings
6863 // wifi_pushBridgeInfo(apIndex);
6864
6865 // restart this ap
6866 wifi_setApEnable(apIndex, FALSE);
6867 wifi_setApEnable(apIndex, TRUE);
developera1255e42023-05-13 17:45:02 +08006868 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6869 return RETURN_ERR;
6870 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_tag 0\n", interface_name);
6871 _syscmd(cmd, buf, sizeof(buf));
6872 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_priority 0\n", interface_name);
6873 _syscmd(cmd, buf, sizeof(buf));
6874 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_id 0\n", interface_name);
6875 _syscmd(cmd, buf, sizeof(buf));
6876 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_en 0\n", interface_name);
6877 _syscmd(cmd, buf, sizeof(buf));
6878 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_policy 0:4\n", interface_name);
6879 _syscmd(cmd, buf, sizeof(buf));
6880 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_policy 1:0\n", interface_name);
6881 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006882 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6883
6884 return RETURN_OK;
6885}
6886
6887// 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.
6888INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6889{
6890 return RETURN_ERR;
6891}
6892
6893// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6894INT wifi_startHostApd()
6895{
6896 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6897 system("systemctl start hostapd.service");
6898 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6899 return RETURN_OK;
6900 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6901}
6902
6903// stops hostapd
developer69b61b02023-03-07 17:17:44 +08006904INT wifi_stopHostApd()
developer72fb0bb2023-01-11 09:46:29 +08006905{
6906 char cmd[128] = {0};
6907 char buf[128] = {0};
6908
6909 sprintf(cmd,"systemctl stop hostapd");
6910 _syscmd(cmd, buf, sizeof(buf));
6911
6912 return RETURN_OK;
6913}
6914
6915// restart hostapd dummy function
6916INT wifi_restartHostApd()
6917{
6918 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6919 system("systemctl restart hostapd-global");
6920 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6921
6922 return RETURN_OK;
6923}
6924
6925static int align_hostapd_config(int index)
6926{
6927 ULONG lval;
6928 wifi_getRadioChannel(index%2, &lval);
6929 wifi_setRadioChannel(index%2, lval);
6930 return RETURN_OK;
6931}
6932
6933// sets the AP enable status variable for the specified ap.
6934INT wifi_setApEnable(INT apIndex, BOOL enable)
6935{
developer7e4a2a62023-04-06 19:56:03 +08006936 char interface_name[16] = {0};
6937 char config_file[MAX_BUF_SIZE] = {0};
6938 char cmd[MAX_CMD_SIZE] = {0};
6939 char buf[MAX_BUF_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08006940 BOOL status = FALSE;
developer7e4a2a62023-04-06 19:56:03 +08006941 int max_radio_num = 0;
6942 int phyId = 0;
developer72fb0bb2023-01-11 09:46:29 +08006943
developer7e4a2a62023-04-06 19:56:03 +08006944 wifi_getApEnable(apIndex, &status);
developer72fb0bb2023-01-11 09:46:29 +08006945
developer7e4a2a62023-04-06 19:56:03 +08006946 wifi_getMaxRadioNumber(&max_radio_num);
6947 if (enable == status)
6948 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006949
developer7e4a2a62023-04-06 19:56:03 +08006950 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6951 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006952
developer7e4a2a62023-04-06 19:56:03 +08006953 if (enable == TRUE) {
6954 int radioIndex = apIndex % max_radio_num;
6955 phyId = radio_index_to_phy(radioIndex);
developer8a3bbbf2023-03-15 17:47:23 +08006956
developer7e4a2a62023-04-06 19:56:03 +08006957 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
6958 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
6959 _syscmd(cmd, buf, sizeof(buf));
6960 } else {
6961 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
6962 _syscmd(cmd, buf, sizeof(buf));
6963 }
6964 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
6965 interface_name, interface_name, enable, VAP_STATUS_FILE);
6966 _syscmd(cmd, buf, sizeof(buf));
6967 //Wait for wifi up/down to apply
6968 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006969}
6970
6971// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6972INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6973{
developer7e4a2a62023-04-06 19:56:03 +08006974 char interface_name[IF_NAME_SIZE] = {0};
6975 char cmd[MAX_CMD_SIZE] = {0};
6976 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006977
developer7e4a2a62023-04-06 19:56:03 +08006978 if ((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6979 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006980
developer7e4a2a62023-04-06 19:56:03 +08006981 *output_bool = 0;
developer72fb0bb2023-01-11 09:46:29 +08006982
developer7e4a2a62023-04-06 19:56:03 +08006983 if ((apIndex >= 0) && (apIndex < MAX_APS)) {
6984 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
6985 *output_bool = FALSE;
6986 return RETURN_OK;
6987 }
6988 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s 2> /dev/null | grep UP", interface_name);
6989 *output_bool = _syscmd(cmd, buf, sizeof(buf)) ? 0 : 1;
6990 }
developer72fb0bb2023-01-11 09:46:29 +08006991
developer7e4a2a62023-04-06 19:56:03 +08006992 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006993}
6994
developer69b61b02023-03-07 17:17:44 +08006995// Outputs the AP "Enabled" "Disabled" status from driver
6996INT wifi_getApStatus(INT apIndex, CHAR *output_string)
developer72fb0bb2023-01-11 09:46:29 +08006997{
developer7e4a2a62023-04-06 19:56:03 +08006998 char cmd[128] = {0};
6999 char buf[128] = {0};
7000 BOOL output_bool;
developer72fb0bb2023-01-11 09:46:29 +08007001
developer7e4a2a62023-04-06 19:56:03 +08007002 if (!output_string) {
7003 printf("%s: null pointer!", __func__);
7004 return RETURN_ERR;
7005 }
developer72fb0bb2023-01-11 09:46:29 +08007006
developer7e4a2a62023-04-06 19:56:03 +08007007 wifi_getApEnable(apIndex, &output_bool);
developer72fb0bb2023-01-11 09:46:29 +08007008
developer7e4a2a62023-04-06 19:56:03 +08007009 if(output_bool == 1)
7010 snprintf(output_string, 32, "Up");
7011 else
7012 snprintf(output_string, 32, "Disable");
7013
7014 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007015}
7016
7017//Indicates whether or not beacons include the SSID name.
7018// outputs a 1 if SSID on the AP is enabled, else outputs 0
7019INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
7020{
7021 //get the running status
7022 char config_file[MAX_BUF_SIZE] = {0};
7023 char buf[16] = {0};
7024
7025 if (!output)
7026 return RETURN_ERR;
7027
7028 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7029 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
7030 // default is enable
7031 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
7032 *output = TRUE;
7033
7034 return RETURN_OK;
7035}
7036
7037// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
7038INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
7039{
7040 //store the config, apply instantly
7041 char config_file[MAX_BUF_SIZE] = {0};
7042 struct params list;
7043
7044 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7045 list.name = "ignore_broadcast_ssid";
7046 list.value = enable?"0":"1";
7047
7048 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7049 wifi_hostapdWrite(config_file, &list, 1);
7050 wifi_hostapdProcessUpdate(apIndex, &list, 1);
7051 //TODO: call hostapd_cli for dynamic_config_control
7052 wifi_reloadAp(apIndex);
7053 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7054
7055 return RETURN_OK;
7056}
7057
7058//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
7059INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
7060{
developer47cc27a2023-05-17 23:09:58 +08007061 /* get the running status */
7062 if(!output_uint)
7063 return RETURN_ERR;
7064
7065 *output_uint = 15;
7066 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007067}
7068
developer47cc27a2023-05-17 23:09:58 +08007069/*Do not support AP retry limit fix*/
developer72fb0bb2023-01-11 09:46:29 +08007070INT wifi_setApRetryLimit(INT apIndex, UINT number)
7071{
developer47cc27a2023-05-17 23:09:58 +08007072 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007073}
7074
7075//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
7076INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
7077{
7078 if(!output)
7079 return RETURN_ERR;
7080 *output=TRUE;
7081 return RETURN_OK;
7082}
7083
7084//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
7085INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
7086{
7087 //get the running status from driver
7088 char cmd[128] = {0};
7089 char buf[128] = {0};
7090 int max_radio_num = 0, radioIndex = 0;
7091 int phyId = 0;
7092
7093 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7094
7095 wifi_getMaxRadioNumber(&max_radio_num);
7096 radioIndex = apIndex % max_radio_num;
7097 phyId = radio_index_to_phy(radioIndex);
7098 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
7099 _syscmd(cmd,buf, sizeof(buf));
7100
7101 if (strlen(buf) > 0)
7102 *output = true;
7103
7104 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7105
7106 return RETURN_OK;
7107}
7108
7109//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
7110INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
7111{
7112 //get the running status from driver
7113 if(!output)
7114 return RETURN_ERR;
7115
7116 char config_file[MAX_BUF_SIZE] = {0};
7117 char buf[16] = {0};
7118
7119 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7120 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
7121 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
7122 *output = TRUE;
7123 else
7124 *output = FALSE;
7125
7126 return RETURN_OK;
7127}
7128
7129// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
7130INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
7131{
7132 //Save config and apply instantly.
7133 char config_file[MAX_BUF_SIZE] = {0};
7134 struct params list;
7135
7136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7137 list.name = "wmm_enabled";
7138 list.value = enable?"1":"0";
7139
7140 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7141 wifi_hostapdWrite(config_file, &list, 1);
7142 wifi_hostapdProcessUpdate(apIndex, &list, 1);
7143 wifi_reloadAp(apIndex);
7144 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7145
7146 return RETURN_OK;
7147}
7148
7149//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.
7150INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
7151{
7152 //get the running status from driver
7153 if(!output)
7154 return RETURN_ERR;
7155
7156 char config_file[128] = {0};
7157 char buf[16] = {0};
7158
7159 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7160 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
7161 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
7162 *output = TRUE;
7163 else
7164 *output = FALSE;
7165
7166 return RETURN_OK;
7167}
7168
7169// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
7170INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
7171{
7172 //save config and apply instantly.
7173 char config_file[MAX_BUF_SIZE] = {0};
7174 struct params list;
7175
7176 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7177 list.name = "uapsd_advertisement_enabled";
7178 list.value = enable?"1":"0";
7179
7180 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7181 wifi_hostapdWrite(config_file, &list, 1);
7182 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developere82c0ca2023-05-10 16:25:35 +08007183 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007184 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7185
7186 return RETURN_OK;
7187}
7188
7189// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
7190INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
7191{
7192 char interface_name[16] = {0};
7193 // assume class 0->BE, 1->BK, 2->VI, 3->VO
7194 char cmd[128] = {0};
7195 char buf[128] = {0};
7196 char ack_filepath[128] = {0};
7197 uint16_t bitmap = 0;
7198 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
7199 FILE *f = NULL;
7200
7201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
7202
7203 // Get current setting
7204 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
7205 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
7206 _syscmd(cmd, buf, sizeof(buf));
7207 if (strlen(buf) > 0)
7208 bitmap = strtoul(buf, NULL, 10);
7209
7210 bitmap = strtoul(buf, NULL, 10);
7211
7212 if (ackPolicy == TRUE) { // True, unset this class
7213 bitmap &= ~class_map[class];
7214 } else { // False, set this class
7215 bitmap |= class_map[class];
7216 }
7217
7218 f = fopen(ack_filepath, "w");
7219 if (f == NULL) {
7220 fprintf(stderr, "%s: fopen failed\n", __func__);
7221 return RETURN_ERR;
7222 }
7223 fprintf(f, "%hu", bitmap);
7224 fclose(f);
7225
7226 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7227 return RETURN_ERR;
7228 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
7229 _syscmd(cmd, buf, sizeof(buf));
7230
7231 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
7232 return RETURN_OK;
7233}
7234
7235//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.
7236INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
7237{
7238 //get the running status from driver
7239 if(!output_uint)
7240 return RETURN_ERR;
7241
7242 char output[16]={'\0'};
7243 char config_file[MAX_BUF_SIZE] = {0};
7244
7245 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7246 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
7247 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
7248 else {
7249 int device_num = atoi(output);
7250 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
7251 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
7252 return RETURN_ERR;
7253 }
7254 else {
7255 *output_uint = device_num;
7256 }
7257 }
7258
7259 return RETURN_OK;
7260}
7261
7262INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
7263{
7264 //store to wifi config, apply instantly
7265 char str[MAX_BUF_SIZE]={'\0'};
7266 char cmd[MAX_CMD_SIZE]={'\0'};
7267 struct params params;
7268 char config_file[MAX_BUF_SIZE] = {0};
7269
7270 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7271 if (number > MAX_ASSOCIATED_STA_NUM) {
7272 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
7273 return RETURN_ERR;
7274 }
7275 sprintf(str, "%d", number);
7276 params.name = "max_num_sta";
7277 params.value = str;
7278
7279 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
7280 int ret = wifi_hostapdWrite(config_file, &params, 1);
7281 if (ret) {
7282 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
7283 ,__func__, ret);
7284 }
7285
7286 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
7287 if (ret) {
7288 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
7289 ,__func__, ret);
7290 }
7291 wifi_reloadAp(apIndex);
7292 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7293
7294 return RETURN_OK;
7295}
7296
7297//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.
7298INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
7299{
7300 //get the current threshold
7301 if(!output_uint)
7302 return RETURN_ERR;
7303 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
7304 if (*output_uint == 0)
7305 *output_uint = 50;
7306 return RETURN_OK;
7307}
7308
7309INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
7310{
7311 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
7312 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
7313 return RETURN_OK;
7314 return RETURN_ERR;
7315}
7316
7317//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.
7318INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
7319{
7320 if(!output_uint)
7321 return RETURN_ERR;
7322 *output_uint = 3;
7323 return RETURN_OK;
7324}
7325
7326//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
7327INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
7328{
7329 if(!output_uint)
7330 return RETURN_ERR;
7331 *output_uint = 3;
7332 return RETURN_OK;
7333}
7334
7335//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.
7336INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
7337{
7338 if(!output_in_seconds)
7339 return RETURN_ERR;
7340 *output_in_seconds = 0;
7341 return RETURN_OK;
7342}
7343
7344//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
7345INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
7346{
7347 if(!output || apIndex>=MAX_APS)
7348 return RETURN_ERR;
7349 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
7350 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
7351 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007352}
developer72fb0bb2023-01-11 09:46:29 +08007353
7354//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
7355INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
7356{
7357 char config_file[128] = {0};
7358 char wpa[16] = {0};
7359 char key_mgmt[64] = {0};
7360 char buf[16] = {0};
7361 if (!output)
7362 return RETURN_ERR;
7363
7364 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7365 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
7366
7367 strcpy(output, "None");//Copying "None" to output string for default case
7368 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
7369 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
7370 if (!strcmp(wpa, "1"))
7371 snprintf(output, 32, "WPA-Personal");
7372 else if (!strcmp(wpa, "2"))
7373 snprintf(output, 32, "WPA2-Personal");
7374 else if (!strcmp(wpa, "3"))
7375 snprintf(output, 32, "WPA-WPA2-Personal");
7376
developere5750452023-05-15 16:46:42 +08007377 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
7378 snprintf(output, 32, "WPA3-Enterprise");
developer72fb0bb2023-01-11 09:46:29 +08007379 } else if (strstr(key_mgmt, "WPA-EAP")) {
7380 if (!strcmp(wpa, "1"))
7381 snprintf(output, 32, "WPA-Enterprise");
7382 else if (!strcmp(wpa, "2"))
7383 snprintf(output, 32, "WPA2-Enterprise");
7384 else if (!strcmp(wpa, "3"))
7385 snprintf(output, 32, "WPA-WPA2-Enterprise");
7386 } else if (strstr(key_mgmt, "SAE")) {
7387 if (strstr(key_mgmt, "WPA-PSK") == NULL)
7388 snprintf(output, 32, "WPA3-Personal");
7389 else
7390 snprintf(output, 32, "WPA3-Personal-Transition");
developer72fb0bb2023-01-11 09:46:29 +08007391 }
7392
7393 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
7394 return RETURN_OK;
7395#if 0
7396 //TODO: need to revisit below implementation
7397 char securityType[32], authMode[32];
7398 int enterpriseMode=0;
7399
7400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7401 if(!output)
7402 return RETURN_ERR;
7403
7404 wifi_getApBeaconType(apIndex, securityType);
7405 strcpy(output,"None");//By default, copying "None" to output string
7406 if (strncmp(securityType,"None", strlen("None")) == 0)
7407 return RETURN_OK;
7408
7409 wifi_getApBasicAuthenticationMode(apIndex, authMode);
7410 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
7411
7412 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
7413 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
7414 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
7415 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
7416 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
7417 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
7418 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7419
7420 return RETURN_OK;
7421#endif
7422}
developer69b61b02023-03-07 17:17:44 +08007423
developer72fb0bb2023-01-11 09:46:29 +08007424INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
7425{
7426 char securityType[32];
7427 char authMode[32];
7428
7429 //store settings and wait for wifi up to apply
7430 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7431 if(!encMode)
7432 return RETURN_ERR;
7433
7434 if (strcmp(encMode, "None")==0)
7435 {
7436 strcpy(securityType,"None");
7437 strcpy(authMode,"None");
7438 }
7439 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
7440 {
7441 strcpy(securityType,"WPAand11i");
7442 strcpy(authMode,"PSKAuthentication");
7443 }
7444 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
7445 {
7446 strcpy(securityType,"WPAand11i");
7447 strcpy(authMode,"EAPAuthentication");
7448 }
7449 else if (strcmp(encMode, "WPA-Personal")==0)
7450 {
7451 strcpy(securityType,"WPA");
7452 strcpy(authMode,"PSKAuthentication");
7453 }
7454 else if (strcmp(encMode, "WPA-Enterprise")==0)
7455 {
7456 strcpy(securityType,"WPA");
7457 strcpy(authMode,"EAPAuthentication");
7458 }
7459 else if (strcmp(encMode, "WPA2-Personal")==0)
7460 {
7461 strcpy(securityType,"11i");
7462 strcpy(authMode,"PSKAuthentication");
7463 }
7464 else if (strcmp(encMode, "WPA2-Enterprise")==0)
7465 {
7466 strcpy(securityType,"11i");
7467 strcpy(authMode,"EAPAuthentication");
7468 }
7469 else if (strcmp(encMode, "WPA3-Personal") == 0)
7470 {
7471 strcpy(securityType,"11i");
7472 strcpy(authMode,"SAEAuthentication");
7473 }
7474 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
7475 {
7476 strcpy(securityType, "11i");
7477 strcpy(authMode, "PSK-SAEAuthentication");
7478 }
7479 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
7480 {
7481 strcpy(securityType,"11i");
7482 strcpy(authMode,"EAP_192-bit_Authentication");
7483 }
developer3086e2f2023-01-17 09:40:01 +08007484 else if (strcmp(encMode, "OWE") == 0)
7485 {
7486 strcpy(securityType,"11i");
7487 strcpy(authMode,"Enhanced_Open");
7488 }
developer72fb0bb2023-01-11 09:46:29 +08007489 else
7490 {
7491 strcpy(securityType,"None");
7492 strcpy(authMode,"None");
7493 }
7494 wifi_setApBeaconType(apIndex, securityType);
7495 wifi_setApBasicAuthenticationMode(apIndex, authMode);
7496 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7497
7498 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007499}
developer72fb0bb2023-01-11 09:46:29 +08007500
7501
7502//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
7503// output_string must be pre-allocated as 64 character string by caller
7504// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
7505INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
7506{
7507 char buf[16] = {0};
7508 char config_file[MAX_BUF_SIZE] = {0};
7509
7510 if(output_string==NULL)
7511 return RETURN_ERR;
7512
7513 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7514 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7515
7516 if(strcmp(buf,"0")==0)
7517 {
7518 printf("wpa_mode is %s ......... \n",buf);
7519 return RETURN_ERR;
7520 }
7521
7522 wifi_dbg_printf("\nFunc=%s\n",__func__);
7523 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developere5750452023-05-15 16:46:42 +08007524 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer72fb0bb2023-01-11 09:46:29 +08007525 wifi_dbg_printf("\noutput_string=%s\n",output_string);
7526
7527 return RETURN_OK;
7528}
7529
7530// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
7531// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
7532INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
7533{
7534 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
7535 struct params params={'\0'};
7536 int ret;
7537 char config_file[MAX_BUF_SIZE] = {0};
7538
7539 if(NULL == preSharedKey)
7540 return RETURN_ERR;
7541
developere5750452023-05-15 16:46:42 +08007542 params.name = "wpa_psk";
developer72fb0bb2023-01-11 09:46:29 +08007543
developere5750452023-05-15 16:46:42 +08007544 if(strlen(preSharedKey) != 64)
developer72fb0bb2023-01-11 09:46:29 +08007545 {
developere5750452023-05-15 16:46:42 +08007546 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer72fb0bb2023-01-11 09:46:29 +08007547 return RETURN_ERR;
7548 }
7549 params.value = preSharedKey;
7550 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7551 ret = wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +08007552 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08007553 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08007554 wifi_reloadAp(apIndex);
7555 }
developer72fb0bb2023-01-11 09:46:29 +08007556 return ret;
7557 //TODO: call hostapd_cli for dynamic_config_control
7558}
7559
7560//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
7561// outputs the passphrase, maximum 63 characters
7562INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
7563{
7564 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
7565
7566 wifi_dbg_printf("\nFunc=%s\n",__func__);
7567 if (NULL == output_string)
7568 return RETURN_ERR;
7569
7570 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7571 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7572 if(strcmp(buf,"0")==0)
7573 {
7574 printf("wpa_mode is %s ......... \n",buf);
7575 return RETURN_ERR;
7576 }
7577
7578 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
7579 wifi_dbg_printf("\noutput_string=%s\n",output_string);
7580
7581 return RETURN_OK;
7582}
7583
7584// sets the passphrase enviornment variable, max 63 characters
7585INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
7586{
7587 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
7588 struct params params={'\0'};
7589 char config_file[MAX_BUF_SIZE] = {0};
7590 int ret;
7591
7592 if(NULL == passPhrase)
7593 return RETURN_ERR;
7594
7595 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
7596 {
7597 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
7598 return RETURN_ERR;
7599 }
7600 params.name = "wpa_passphrase";
7601 params.value = passPhrase;
7602 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7603 ret=wifi_hostapdWrite(config_file,&params,1);
developere5750452023-05-15 16:46:42 +08007604 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08007605 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08007606 wifi_reloadAp(apIndex);
7607 }
developer72fb0bb2023-01-11 09:46:29 +08007608
7609 return ret;
7610}
7611
7612//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.
7613INT wifi_setApSecurityReset(INT apIndex)
7614{
7615 char original_config_file[64] = {0};
7616 char current_config_file[64] = {0};
7617 char buf[64] = {0};
7618 char cmd[64] = {0};
7619 char wpa[4] = {0};
7620 char wpa_psk[64] = {0};
7621 char wpa_passphrase[64] = {0};
7622 char wpa_psk_file[128] = {0};
7623 char wpa_key_mgmt[64] = {0};
7624 char wpa_pairwise[32] = {0};
7625 wifi_band band;
7626 struct params list[6];
7627
7628 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7629
7630 band = wifi_index_to_band(apIndex);
7631 if (band == band_2_4)
7632 sprintf(original_config_file, "/etc/hostapd-2G.conf");
7633 else if (band == band_5)
7634 sprintf(original_config_file, "/etc/hostapd-5G.conf");
7635 else if (band == band_6)
7636 sprintf(original_config_file, "/etc/hostapd-6G.conf");
7637 else
7638 return RETURN_ERR;
7639
7640 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
7641 list[0].name = "wpa";
7642 list[0].value = wpa;
developer69b61b02023-03-07 17:17:44 +08007643
developer72fb0bb2023-01-11 09:46:29 +08007644 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
7645 list[1].name = "wpa_psk";
7646 list[1].value = wpa_psk;
7647
7648 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
7649 list[2].name = "wpa_passphrase";
7650 list[2].value = wpa_passphrase;
7651
7652 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
7653
7654 if (strlen(wpa_psk_file) == 0)
7655 strcpy(wpa_psk_file, PSK_FILE);
7656
7657 if (access(wpa_psk_file, F_OK) != 0) {
7658 sprintf(cmd, "touch %s", wpa_psk_file);
7659 _syscmd(cmd, buf, sizeof(buf));
7660 }
7661 list[3].name = "wpa_psk_file";
7662 list[3].value = wpa_psk_file;
7663
7664 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
7665 list[4].name = "wpa_key_mgmt";
7666 list[4].value = wpa_key_mgmt;
7667
7668 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
7669 list[5].name = "wpa_pairwise";
7670 list[5].value = wpa_pairwise;
7671
7672 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7673 wifi_hostapdWrite(current_config_file, list, 6);
7674
7675 wifi_setApEnable(apIndex, FALSE);
7676 wifi_setApEnable(apIndex, TRUE);
7677
7678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7679 return RETURN_OK;
7680}
7681
7682//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).
7683INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7684{
7685 char config_file[64] = {0};
7686 char buf[64] = {0};
7687 char cmd[256] = {0};
7688
7689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7690
7691 if(!IP_output || !Port_output || !RadiusSecret_output)
7692 return RETURN_ERR;
7693
7694 // Read the first matched config
7695 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7696 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7697 _syscmd(cmd, buf, sizeof(buf));
7698 strncpy(IP_output, buf, 64);
7699
7700 memset(buf, 0, sizeof(buf));
7701 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7702 _syscmd(cmd, buf, sizeof(buf));
7703 *Port_output = atoi(buf);
7704
7705 memset(buf, 0, sizeof(buf));
7706 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7707 _syscmd(cmd, buf, sizeof(buf));
7708 strncpy(RadiusSecret_output, buf, 64);
7709
7710 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7711 return RETURN_OK;
7712}
7713
7714INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7715{
7716 char config_file[64] = {0};
7717 char port_str[8] = {0};
7718 char cmd[256] = {0};
7719 char buf[128] = {0};
7720
7721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7722
developere5750452023-05-15 16:46:42 +08007723 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7724 return RETURN_ERR;
7725
7726 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7727 return RETURN_ERR;
7728
developer72fb0bb2023-01-11 09:46:29 +08007729 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7730
7731 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7732 _syscmd(cmd, buf, sizeof(buf));
7733 memset(cmd, 0, sizeof(cmd));
7734
7735 snprintf(port_str, sizeof(port_str), "%d", port);
7736 if (strlen(buf) == 0)
7737 // Append
7738 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7739 "auth_server_addr=%s\\n"
7740 "auth_server_port=%s\\n"
7741 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7742 else {
7743 // Delete the three lines setting after the "# radius 1" comment
7744 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7745 _syscmd(cmd, buf, sizeof(buf));
7746 memset(cmd, 0, sizeof(cmd));
7747 // Use "# radius 1" comment to find the location to insert the radius setting
7748 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7749 "# radius 1\\n"
7750 "auth_server_addr=%s\\n"
7751 "auth_server_port=%s\\n"
7752 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7753 }
7754 if(_syscmd(cmd, buf, sizeof(buf))) {
7755 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7756 return RETURN_ERR;
7757 }
7758
7759 wifi_reloadAp(apIndex);
7760 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7761 return RETURN_OK;
7762}
7763
7764INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7765{
7766 char config_file[64] = {0};
7767 char buf[64] = {0};
7768 char cmd[256] = {0};
7769
7770 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7771
7772 if(!IP_output || !Port_output || !RadiusSecret_output)
7773 return RETURN_ERR;
7774
7775 // Read the second matched config
7776 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7777 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7778 _syscmd(cmd, buf, sizeof(buf));
7779 strncpy(IP_output, buf, 64);
7780
7781 memset(buf, 0, sizeof(buf));
7782 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7783 _syscmd(cmd, buf, sizeof(buf));
7784 *Port_output = atoi(buf);
7785
7786 memset(buf, 0, sizeof(buf));
7787 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7788 _syscmd(cmd, buf, sizeof(buf));
7789 strncpy(RadiusSecret_output, buf, 64);
7790
7791 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7792 return RETURN_OK;
7793}
7794
7795INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7796{
7797 char config_file[64] = {0};
7798 char port_str[8] = {0};
7799 char cmd[256] = {0};
7800 char buf[128] = {0};
7801
7802 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7803
developere5750452023-05-15 16:46:42 +08007804 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7805 return RETURN_ERR;
7806
7807 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7808 return RETURN_ERR;
7809
developer72fb0bb2023-01-11 09:46:29 +08007810 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7811
7812 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7813 _syscmd(cmd, buf, sizeof(buf));
7814 memset(cmd, 0, sizeof(cmd));
7815
7816 snprintf(port_str, sizeof(port_str), "%d", port);
7817 if (strlen(buf) == 0)
7818 // Append
7819 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7820 "auth_server_addr=%s\\n"
7821 "auth_server_port=%s\\n"
7822 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7823 else {
7824 // Delete the three lines setting after the "# radius 2" comment
7825 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7826 _syscmd(cmd, buf, sizeof(buf));
7827 memset(cmd, 0, sizeof(cmd));
7828 // Use "# radius 2" comment to find the location to insert the radius setting
7829 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7830 "# radius 2\\n"
7831 "auth_server_addr=%s\\n"
7832 "auth_server_port=%s\\n"
7833 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7834 }
7835 if(_syscmd(cmd, buf, sizeof(buf))) {
7836 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7837 return RETURN_ERR;
7838 }
7839
7840 wifi_reloadAp(apIndex);
7841 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7842 return RETURN_OK;
7843}
7844
7845//RadiusSettings
7846INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7847{
7848 if(!output)
7849 return RETURN_ERR;
7850
7851 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
developer69b61b02023-03-07 17:17:44 +08007852 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7853 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7854 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7855 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 +08007856 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 +08007857 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7858 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7859 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 +08007860 //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.
7861
7862 return RETURN_OK;
7863}
7864
7865INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7866{
7867 //store the paramters, and apply instantly
7868 return RETURN_ERR;
7869}
7870
7871//Device.WiFi.AccessPoint.{i}.WPS.Enable
7872//Enables or disables WPS functionality for this access point.
7873// outputs the WPS enable state of this ap in output_bool
7874INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7875{
7876 char interface_name[16] = {0};
7877 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
7878 if(!output_bool)
7879 return RETURN_ERR;
7880 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7881 return RETURN_ERR;
7882 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
7883 _syscmd(cmd, buf, sizeof(buf));
7884 if(strstr(buf, "configured"))
7885 *output_bool=TRUE;
7886 else
7887 *output_bool=FALSE;
7888
7889 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007890}
developer72fb0bb2023-01-11 09:46:29 +08007891
7892//Device.WiFi.AccessPoint.{i}.WPS.Enable
7893// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7894INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7895{
7896 char config_file[MAX_BUF_SIZE] = {0};
developere5750452023-05-15 16:46:42 +08007897 char buf[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007898 struct params params;
7899
7900 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7901 //store the paramters, and wait for wifi up to apply
7902 params.name = "wps_state";
developere5750452023-05-15 16:46:42 +08007903 if (enable == TRUE) {
7904 wifi_getApBeaconType(apIndex, buf);
7905 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
7906 params.value = "1";
7907 else // If ap set encryption
7908 params.value = "2";
7909 } else {
7910 params.value = "0";
7911 }
developer72fb0bb2023-01-11 09:46:29 +08007912
7913 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7914 wifi_hostapdWrite(config_file, &params, 1);
7915 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7916 wifi_reloadAp(apIndex);
7917
7918 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7919 return RETURN_OK;
7920}
7921
7922//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
7923INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7924{
7925 if(!output)
7926 return RETURN_ERR;
7927 snprintf(output, 128, "PushButton,PIN");
7928 return RETURN_OK;
7929}
7930
7931//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7932//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.
7933// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7934INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7935{
7936 if(!output)
7937 return RETURN_ERR;
7938 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7939
7940 return RETURN_OK;
7941}
7942
7943//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7944// 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
7945INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7946{
7947 //apply instantly. No setting need to be stored.
7948 char methods[MAX_BUF_SIZE], *token, *next_token;
7949 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7950 struct params params;
7951
7952 if(!methodString)
7953 return RETURN_ERR;
7954 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7955 //store the paramters, and wait for wifi up to apply
7956
7957 snprintf(methods, sizeof(methods), "%s", methodString);
7958 for(token=methods; *token; token=next_token)
7959 {
7960 strtok_r(token, ",", &next_token);
7961 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7962 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7963 else if(*token=='E')
7964 {
7965 if(!strcmp(methods, "Ethernet"))
7966 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7967 else if(!strcmp(methods, "ExternalNFCToken"))
7968 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7969 else
7970 printf("%s: Unknown WpsConfigMethod\n", __func__);
7971 }
7972 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7973 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7974 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7975 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7976 else if(*token=='P' )
7977 {
7978 if(!strcmp(token, "PushButton"))
developere5750452023-05-15 16:46:42 +08007979 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer72fb0bb2023-01-11 09:46:29 +08007980 else if(!strcmp(token, "PIN"))
7981 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7982 else
7983 printf("%s: Unknown WpsConfigMethod\n", __func__);
7984 }
7985 else
7986 printf("%s: Unknown WpsConfigMethod\n", __func__);
7987 }
7988 params.name = "config_methods";
7989 params.value = config_methods;
7990 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7991 wifi_hostapdWrite(config_file, &params, 1);
7992 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7993 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7994
7995 return RETURN_OK;
7996}
7997
7998// outputs the pin value, ulong_pin must be allocated by the caller
7999INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
8000{
8001 char buf[MAX_BUF_SIZE] = {0};
8002 char cmd[MAX_CMD_SIZE] = {0};
8003
8004 if(!output_ulong)
8005 return RETURN_ERR;
8006 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
8007 _syscmd(cmd, buf, sizeof(buf));
8008 if(strlen(buf) > 0)
8009 *output_ulong=strtoul(buf, NULL, 10);
8010
8011 return RETURN_OK;
8012}
8013
8014// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
8015INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
8016{
8017 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
8018 char ap_pin[16] = {0};
8019 char buf[MAX_BUF_SIZE] = {0};
8020 char config_file[MAX_BUF_SIZE] = {0};
8021 ULONG prev_pin = 0;
8022 struct params params;
8023
8024 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8025 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
8026 params.name = "ap_pin";
8027 params.value = ap_pin;
8028 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8029 wifi_hostapdWrite(config_file, &params, 1);
8030 wifi_hostapdProcessUpdate(apIndex, &params, 1);
8031 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8032
8033 return RETURN_OK;
8034}
8035
8036// Output string is either Not configured or Configured, max 32 characters
8037INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
8038{
8039 char interface_name[16] = {0};
8040 char cmd[MAX_CMD_SIZE];
8041 char buf[MAX_BUF_SIZE]={0};
8042
8043 if(!output_string)
8044 return RETURN_ERR;
8045 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8046 snprintf(output_string, 32, "Not configured");
8047 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8048 return RETURN_ERR;
8049 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
8050 _syscmd(cmd, buf, sizeof(buf));
8051
8052 if(!strncmp(buf, "configured", 10))
8053 snprintf(output_string, 32, "Configured");
8054 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8055
8056 return RETURN_OK;
8057}
8058
8059// sets the WPS pin for this AP
8060INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
8061{
8062 char interface_name[16] = {0};
8063 char cmd[MAX_CMD_SIZE];
8064 char buf[MAX_BUF_SIZE]={0};
8065 BOOL enable;
8066
8067 wifi_getApEnable(apIndex, &enable);
8068 if (!enable)
8069 return RETURN_ERR;
8070 wifi_getApWpsEnable(apIndex, &enable);
8071 if (!enable)
8072 return RETURN_ERR;
8073
8074 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8075 return RETURN_ERR;
8076 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
8077 _syscmd(cmd, buf, sizeof(buf));
8078 if((strstr(buf, "OK"))!=NULL)
8079 return RETURN_OK;
8080
8081 return RETURN_ERR;
8082}
8083
8084// This function is called when the WPS push button has been pressed for this AP
8085INT wifi_setApWpsButtonPush(INT apIndex)
8086{
8087 char cmd[MAX_CMD_SIZE];
8088 char buf[MAX_BUF_SIZE]={0};
8089 char interface_name[16] = {0};
8090 BOOL enable=FALSE;
8091
8092 wifi_getApEnable(apIndex, &enable);
8093 if (!enable)
8094 return RETURN_ERR;
8095
8096 wifi_getApWpsEnable(apIndex, &enable);
8097 if (!enable)
8098 return RETURN_ERR;
8099
8100 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8101 return RETURN_ERR;
8102
8103 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
8104 _syscmd(cmd, buf, sizeof(buf));
8105
8106 if((strstr(buf, "OK"))!=NULL)
8107 return RETURN_OK;
8108 return RETURN_ERR;
8109}
8110
8111// cancels WPS mode for this AP
8112INT wifi_cancelApWPS(INT apIndex)
8113{
8114 char interface_name[16] = {0};
8115 char cmd[MAX_CMD_SIZE];
8116 char buf[MAX_BUF_SIZE]={0};
8117
8118 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8119 return RETURN_ERR;
8120 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
8121 _syscmd(cmd,buf, sizeof(buf));
8122
8123 if((strstr(buf, "OK"))!=NULL)
8124 return RETURN_OK;
8125 return RETURN_ERR;
8126}
8127
8128//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
8129//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
8130INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
8131{
8132 char interface_name[16] = {0};
8133 FILE *f = NULL;
8134 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8135 char cmd[256] = {0}, buf[2048] = {0};
8136 char *param = NULL, *value = NULL, *line=NULL;
8137 size_t len = 0;
8138 ssize_t nread = 0;
8139 wifi_associated_dev_t *dev=NULL;
8140
8141 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8142 *associated_dev_array = NULL;
8143 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8144 return RETURN_ERR;
8145 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
8146 _syscmd(cmd,buf,sizeof(buf));
8147 *output_array_size = atoi(buf);
8148
8149 if (*output_array_size <= 0)
8150 return RETURN_OK;
8151
8152 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
8153 *associated_dev_array = dev;
8154 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
8155 _syscmd(cmd,buf,sizeof(buf));
8156 f = fopen("/tmp/connected_devices.txt", "r");
8157 if (f==NULL)
8158 {
8159 *output_array_size=0;
8160 return RETURN_ERR;
8161 }
8162 while ((getline(&line, &len, f)) != -1)
8163 {
8164 param = strtok(line,"=");
8165 value = strtok(NULL,"=");
8166
8167 if( strcmp("flags",param) == 0 )
8168 {
8169 value[strlen(value)-1]='\0';
8170 if(strstr (value,"AUTHORIZED") != NULL )
8171 {
8172 dev[auth_temp].cli_AuthenticationState = 1;
8173 dev[auth_temp].cli_Active = 1;
8174 auth_temp++;
8175 read_flag=1;
8176 }
8177 }
8178 if(read_flag==1)
8179 {
8180 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8181 {
8182 value[strlen(value)-1]='\0';
8183 sscanf(value, "%x:%x:%x:%x:%x:%x",
8184 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8185 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8186 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8187 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8188 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8189 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8190 mac_temp++;
8191 read_flag=0;
8192 }
8193 }
8194 }
8195 *output_array_size = auth_temp;
8196 auth_temp=0;
8197 mac_temp=0;
8198 free(line);
8199 fclose(f);
8200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8201 return RETURN_OK;
8202}
8203
8204#define MACADDRESS_SIZE 6
8205
8206INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8207{
8208 FILE *fp = NULL;
8209 char str[MAX_BUF_SIZE] = {0};
8210 int wificlientindex = 0 ;
8211 int count = 0;
8212 int signalstrength = 0;
8213 int arr[MACADDRESS_SIZE] = {0};
8214 unsigned char mac[MACADDRESS_SIZE] = {0};
8215 UINT wifi_count = 0;
8216 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8217 char pipeCmd[MAX_CMD_SIZE] = {0};
8218
8219 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8220 *output_array_size = 0;
8221 *associated_dev_array = NULL;
8222
8223 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8224 fp = popen(pipeCmd, "r");
developer69b61b02023-03-07 17:17:44 +08008225 if (fp == NULL)
developer72fb0bb2023-01-11 09:46:29 +08008226 {
8227 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8228 return RETURN_ERR;
8229 }
8230
8231 /* Read the output a line at a time - output it. */
8232 fgets(str, sizeof(str)-1, fp);
8233 wifi_count = (unsigned int) atoi ( str );
8234 *output_array_size = wifi_count;
8235 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8236 pclose(fp);
8237
8238 if(wifi_count == 0)
8239 {
8240 return RETURN_OK;
8241 }
8242 else
8243 {
8244 wifi_associated_dev3_t* temp = NULL;
8245 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
8246 if(temp == NULL)
8247 {
8248 printf("Error Statement. Insufficient memory \n");
8249 return RETURN_ERR;
8250 }
8251
8252 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8253 system(pipeCmd);
8254 memset(pipeCmd,0,sizeof(pipeCmd));
8255 if(apIndex == 0)
8256 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
8257 else if(apIndex == 1)
8258 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
8259 system(pipeCmd);
8260
8261 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8262 if(fp == NULL)
8263 {
8264 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8265 free(temp);
8266 return RETURN_ERR;
8267 }
8268 fclose(fp);
8269
8270 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
8271 fp = popen(pipeCmd, "r");
8272 if(fp)
8273 {
8274 for(count =0 ; count < wifi_count; count++)
8275 {
8276 fgets(str, MAX_BUF_SIZE, fp);
8277 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8278 {
8279 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8280 {
8281 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8282
8283 }
8284 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8285 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]);
8286 }
8287 temp[count].cli_AuthenticationState = 1; //TODO
8288 temp[count].cli_Active = 1; //TODO
8289 }
8290 pclose(fp);
8291 }
8292
8293 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
8294 fp = popen(pipeCmd, "r");
8295 if(fp)
developer69b61b02023-03-07 17:17:44 +08008296 {
developer72fb0bb2023-01-11 09:46:29 +08008297 pclose(fp);
8298 }
8299 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8300 if(fp)
8301 {
8302 for(count =0 ; count < wifi_count ;count++)
8303 {
8304 fgets(str, MAX_BUF_SIZE, fp);
8305 signalstrength = atoi(str);
8306 temp[count].cli_SignalStrength = signalstrength;
8307 temp[count].cli_RSSI = signalstrength;
8308 temp[count].cli_SNR = signalstrength + 95;
8309 }
8310 pclose(fp);
8311 }
8312
8313
8314 if((apIndex == 0) || (apIndex == 4))
8315 {
8316 for(count =0 ; count < wifi_count ;count++)
developer69b61b02023-03-07 17:17:44 +08008317 {
developer72fb0bb2023-01-11 09:46:29 +08008318 strcpy(temp[count].cli_OperatingStandard,"g");
8319 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
8320 }
8321
8322 //BytesSent
8323 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
8324 fp = popen(pipeCmd, "r");
8325 if(fp)
developer69b61b02023-03-07 17:17:44 +08008326 {
developer72fb0bb2023-01-11 09:46:29 +08008327 pclose(fp);
8328 }
8329 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
8330 if(fp)
8331 {
8332 for (count = 0; count < wifi_count; count++)
8333 {
8334 fgets(str, MAX_BUF_SIZE, fp);
8335 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
8336 }
8337 pclose(fp);
8338 }
8339
8340 //BytesReceived
8341 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
8342 fp = popen(pipeCmd, "r");
8343 if (fp)
8344 {
8345 pclose(fp);
8346 }
8347 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
8348 if (fp)
8349 {
8350 for (count = 0; count < wifi_count; count++)
8351 {
8352 fgets(str, MAX_BUF_SIZE, fp);
8353 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
8354 }
8355 pclose(fp);
8356 }
8357
8358 //PacketsSent
8359 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
8360 fp = popen(pipeCmd, "r");
8361 if (fp)
8362 {
8363 pclose(fp);
8364 }
8365
8366 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
8367 if (fp)
8368 {
8369 for (count = 0; count < wifi_count; count++)
8370 {
8371 fgets(str, MAX_BUF_SIZE, fp);
8372 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
8373 }
8374 pclose(fp);
8375 }
8376
8377 //PacketsReceived
8378 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
8379 fp = popen(pipeCmd, "r");
8380 if (fp)
8381 {
8382 pclose(fp);
8383 }
8384 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
8385 if (fp)
8386 {
8387 for (count = 0; count < wifi_count; count++)
8388 {
8389 fgets(str, MAX_BUF_SIZE, fp);
8390 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
8391 }
8392 pclose(fp);
8393 }
8394
8395 //ErrorsSent
8396 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
8397 fp = popen(pipeCmd, "r");
8398 if (fp)
8399 {
8400 pclose(fp);
8401 }
8402 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
8403 if (fp)
8404 {
8405 for (count = 0; count < wifi_count; count++)
8406 {
8407 fgets(str, MAX_BUF_SIZE, fp);
8408 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
8409 }
8410 pclose(fp);
8411 }
8412
8413 //ErrorsSent
8414 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
8415 fp = popen(pipeCmd, "r");
8416 if (fp)
8417 {
8418 pclose(fp);
8419 }
8420 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
8421 if (fp)
8422 {
8423 for (count = 0; count < wifi_count; count++)
8424 {
8425 fgets(str, MAX_BUF_SIZE, fp);
8426 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
8427 }
8428 pclose(fp);
8429 }
8430
8431 //LastDataDownlinkRate
8432 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
8433 fp = popen(pipeCmd, "r");
8434 if (fp)
8435 {
8436 pclose(fp);
8437 }
8438 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8439 if (fp)
8440 {
8441 for (count = 0; count < wifi_count; count++)
8442 {
8443 fgets(str, MAX_BUF_SIZE, fp);
8444 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8445 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8446 }
8447 pclose(fp);
8448 }
8449
8450 //LastDataUplinkRate
8451 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
8452 fp = popen(pipeCmd, "r");
8453 if (fp)
8454 {
8455 pclose(fp);
8456 }
8457 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8458 if (fp)
8459 {
8460 for (count = 0; count < wifi_count; count++)
8461 {
8462 fgets(str, MAX_BUF_SIZE, fp);
8463 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8464 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8465 }
8466 pclose(fp);
8467 }
8468
8469 }
8470 else if ((apIndex == 1) || (apIndex == 5))
8471 {
8472 for (count = 0; count < wifi_count; count++)
8473 {
8474 strcpy(temp[count].cli_OperatingStandard, "a");
8475 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
8476 temp[count].cli_BytesSent = 0;
8477 temp[count].cli_BytesReceived = 0;
8478 temp[count].cli_LastDataUplinkRate = 0;
8479 temp[count].cli_LastDataDownlinkRate = 0;
8480 temp[count].cli_PacketsSent = 0;
8481 temp[count].cli_PacketsReceived = 0;
8482 temp[count].cli_ErrorsSent = 0;
8483 }
8484 }
8485
8486 for (count = 0; count < wifi_count; count++)
8487 {
8488 temp[count].cli_Retransmissions = 0;
8489 temp[count].cli_DataFramesSentAck = 0;
8490 temp[count].cli_DataFramesSentNoAck = 0;
8491 temp[count].cli_MinRSSI = 0;
8492 temp[count].cli_MaxRSSI = 0;
8493 strncpy(temp[count].cli_InterferenceSources, "", 64);
8494 memset(temp[count].cli_IPAddress, 0, 64);
8495 temp[count].cli_RetransCount = 0;
8496 temp[count].cli_FailedRetransCount = 0;
8497 temp[count].cli_RetryCount = 0;
8498 temp[count].cli_MultipleRetryCount = 0;
8499 }
8500 *associated_dev_array = temp;
8501 }
8502 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8503 return RETURN_OK;
8504}
8505
developer7e4a2a62023-04-06 19:56:03 +08008506int wifihal_interfacestatus(CHAR *wifi_status, CHAR *interface_name)
developer72fb0bb2023-01-11 09:46:29 +08008507{
developer7e4a2a62023-04-06 19:56:03 +08008508 char cmd[MAX_CMD_SIZE] = {0};
8509 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08008510
developer7e4a2a62023-04-06 19:56:03 +08008511 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
8512
8513 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4 | tr -d '\\n'",
8514 interface_name);
8515 _syscmd(cmd, buf, MAX_BUF_SIZE);
8516
8517 strcpy(wifi_status, buf); /* TBD: check wifi_status mem lenth and replace with strcpy later */
8518
8519 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008520 return RETURN_OK;
8521}
8522
8523/* #define HOSTAPD_STA_PARAM_ENTRIES 29
8524struct hostapd_sta_param {
8525 char key[50];
8526 char value[100];
8527}
8528
8529static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
8530 int i = 0;
8531
8532 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
8533 if (strncmp(params[i].key,key,50) == 0){
8534 return &params[i].value;
8535 }
8536 i++;
8537 }
8538 return NULL;
8539
8540} */
8541
8542static unsigned int count_occurences(const char *buf, const char *word)
8543{
8544 unsigned int n = 0;
8545 char *ptr = strstr(buf, word);
8546
8547 while (ptr++) {
8548 n++;
8549 ptr = strstr(ptr, word);
8550 }
8551
8552 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
8553 return n;
8554}
8555
8556static const char *get_line_from_str_buf(const char *buf, char *line)
8557{
8558 int i;
8559 int n = strlen(buf);
8560
8561 for (i = 0; i < n; i++) {
8562 line[i] = buf[i];
8563 if (buf[i] == '\n') {
8564 line[i] = '\0';
8565 return &buf[i + 1];
8566 }
8567 }
8568
8569 return NULL;
8570}
8571
8572INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8573{
8574 unsigned int assoc_cnt = 0;
8575 char interface_name[50] = {0};
8576 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
8577 char cmd[MAX_CMD_SIZE] = {'\0'};
8578 char line[256] = {'\0'};
8579 int i = 0;
8580 int ret = 0;
8581 const char *ptr = NULL;
8582 char *key = NULL;
8583 char *val = NULL;
8584 wifi_associated_dev3_t *temp = NULL;
8585 int rssi;
8586
8587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8588
8589 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8590 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8591 return RETURN_ERR;
8592 }
8593
8594 // Example filtered output of 'iw dev' command:
8595 // Station 0a:69:72:10:d2:fa (on wifi0)
8596 // signal avg:-67 [-71, -71] dBm
8597 // Station 28:c2:1f:25:5f:99 (on wifi0)
8598 // signal avg:-67 [-71, -70] dBm
8599 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
8600 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
8601 return RETURN_ERR;
8602 }
8603
8604 ret = _syscmd(cmd, buf, sizeof(buf));
8605 if (ret == RETURN_ERR) {
8606 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
8607 return RETURN_ERR;
8608 }
8609
8610 *output_array_size = count_occurences(buf, "Station");
8611 if (*output_array_size == 0) return RETURN_OK;
8612
8613 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
8614 if (temp == NULL) {
8615 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
8616 return RETURN_ERR;
8617 }
8618 *associated_dev_array = temp;
8619
8620 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
8621 ptr = get_line_from_str_buf(buf, line);
8622 i = -1;
8623 while (ptr) {
8624 if (strstr(line, "Station")) {
8625 i++;
8626 key = strtok(line, " ");
8627 val = strtok(NULL, " ");
8628 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
8629 &temp[i].cli_MACAddress[0],
8630 &temp[i].cli_MACAddress[1],
8631 &temp[i].cli_MACAddress[2],
8632 &temp[i].cli_MACAddress[3],
8633 &temp[i].cli_MACAddress[4],
8634 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
8635 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
8636 free(*associated_dev_array);
8637 return RETURN_ERR;
8638 }
8639 }
8640 else if (i < 0) {
8641 ptr = get_line_from_str_buf(ptr, line);
8642 continue; // We didn't detect 'station' entry yet
8643 }
8644 else if (strstr(line, "signal avg")) {
8645 key = strtok(line, ":");
8646 val = strtok(NULL, " ");
8647 if (sscanf(val, "%d", &rssi) <= 0 ) {
8648 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
8649 free(*associated_dev_array);
8650 return RETURN_ERR;
8651 }
8652 temp[i].cli_RSSI = rssi;
8653 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
8654 }
8655 // Here other fields can be parsed if added to filter of 'iw dev' command
8656
8657 ptr = get_line_from_str_buf(ptr, line);
8658 };
8659
8660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8661
8662 return RETURN_OK;
8663}
8664
8665#if 0
8666//To-do
8667INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8668{
8669 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8670
8671 //Using different approach to get required WiFi Parameters from system available commands
developer69b61b02023-03-07 17:17:44 +08008672#if 0
developer72fb0bb2023-01-11 09:46:29 +08008673 FILE *f;
8674 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8675 char cmd[256], buf[2048];
8676 char *param , *value, *line=NULL;
8677 size_t len = 0;
8678 ssize_t nread;
8679 wifi_associated_dev3_t *dev=NULL;
8680 *associated_dev_array = NULL;
8681 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
8682 _syscmd(cmd,buf,sizeof(buf));
8683 *output_array_size = atoi(buf);
8684
8685 if (*output_array_size <= 0)
8686 return RETURN_OK;
8687
8688 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8689 *associated_dev_array = dev;
8690 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
8691 _syscmd(cmd,buf,sizeof(buf));
8692 f = fopen("/tmp/connected_devices.txt", "r");
8693 if (f==NULL)
8694 {
8695 *output_array_size=0;
8696 return RETURN_ERR;
8697 }
8698 while ((nread = getline(&line, &len, f)) != -1)
8699 {
8700 param = strtok(line,"=");
8701 value = strtok(NULL,"=");
8702
8703 if( strcmp("flags",param) == 0 )
8704 {
8705 value[strlen(value)-1]='\0';
8706 if(strstr (value,"AUTHORIZED") != NULL )
8707 {
8708 dev[auth_temp].cli_AuthenticationState = 1;
8709 dev[auth_temp].cli_Active = 1;
8710 auth_temp++;
8711 read_flag=1;
8712 }
8713 }
8714 if(read_flag==1)
8715 {
8716 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8717 {
8718 value[strlen(value)-1]='\0';
8719 sscanf(value, "%x:%x:%x:%x:%x:%x",
8720 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8721 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8722 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8723 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8724 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8725 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8726
8727 }
8728 else if( strcmp("rx_packets",param) == 0 )
8729 {
8730 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8731 }
8732
8733 else if( strcmp("tx_packets",param) == 0 )
8734 {
developer69b61b02023-03-07 17:17:44 +08008735 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
developer72fb0bb2023-01-11 09:46:29 +08008736 }
8737
8738 else if( strcmp("rx_bytes",param) == 0 )
8739 {
8740 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8741 }
8742
8743 else if( strcmp("tx_bytes",param) == 0 )
8744 {
developer69b61b02023-03-07 17:17:44 +08008745 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
developer72fb0bb2023-01-11 09:46:29 +08008746 mac_temp++;
8747 read_flag=0;
developer69b61b02023-03-07 17:17:44 +08008748 }
developer72fb0bb2023-01-11 09:46:29 +08008749 }
8750 }
8751
8752 *output_array_size = auth_temp;
8753 auth_temp=0;
8754 mac_temp=0;
8755 free(line);
8756 fclose(f);
8757#endif
8758 char interface_name[MAX_BUF_SIZE] = {0};
8759 char wifi_status[MAX_BUF_SIZE] = {0};
8760 char hostapdconf[MAX_BUF_SIZE] = {0};
8761
8762 wifi_associated_dev3_t *dev_array = NULL;
8763 ULONG wifi_count = 0;
8764
8765 *associated_dev_array = NULL;
8766 *output_array_size = 0;
8767
8768 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8769 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8770 {
8771 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8772
8773 wifi_GetInterfaceName(interface_name, hostapdconf);
8774
8775 if(strlen(interface_name) > 1)
8776 {
8777 wifihal_interfacestatus(wifi_status,interface_name);
8778 if(strcmp(wifi_status,"RUNNING") == 0)
8779 {
8780 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8781
8782 *associated_dev_array = dev_array;
developer69b61b02023-03-07 17:17:44 +08008783 *output_array_size = wifi_count;
developer72fb0bb2023-01-11 09:46:29 +08008784 }
8785 else
8786 {
8787 *associated_dev_array = NULL;
8788 }
8789 }
8790 }
8791
8792 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8793 return RETURN_OK;
8794}
8795#endif
8796
8797/* getIPAddress function */
8798/**
8799* @description Returning IpAddress of the Matched String
8800*
developer69b61b02023-03-07 17:17:44 +08008801* @param
developer72fb0bb2023-01-11 09:46:29 +08008802* @str Having MacAddress
developer69b61b02023-03-07 17:17:44 +08008803* @ipaddr Having ipaddr
developer72fb0bb2023-01-11 09:46:29 +08008804* @return The status of the operation
8805* @retval RETURN_OK if successful
8806* @retval RETURN_ERR if any error is detected
8807*
8808*/
8809
8810INT getIPAddress(char *str,char *ipaddr)
8811{
8812 FILE *fp = NULL;
8813 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8814 int LeaseTime = 0,ret = 0;
8815 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8816 {
8817 return RETURN_ERR;
8818 }
8819
8820 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8821 {
8822 /*
8823 Sample:sss
8824 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8825 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8826 */
8827 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
8828 &(LeaseTime),
8829 phyAddr,
8830 ipAddr,
8831 hostName
8832 );
8833 if(ret != 4)
8834 continue;
8835 if(strcmp(str,phyAddr) == 0)
8836 strcpy(ipaddr,ipAddr);
8837 }
8838 fclose(fp);
8839 return RETURN_OK;
8840}
8841
8842/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8843/**
8844* @description Returning Inactive wireless connected clients informations
8845*
developer69b61b02023-03-07 17:17:44 +08008846* @param
developer72fb0bb2023-01-11 09:46:29 +08008847* @filename Holding private_wifi 2g/5g content files
8848* @associated_dev_array Having inactiv wireless clients informations
8849* @output_array_size Returning Inactive wireless counts
8850* @return The status of the operation
8851* @retval RETURN_OK if successful
8852* @retval RETURN_ERR if any error is detected
8853*
8854*/
8855
8856INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8857{
8858 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8859 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8860 FILE *fp = NULL;
8861 int arr[MACADDRESS_SIZE] = {0};
8862 unsigned char mac[MACADDRESS_SIZE] = {0};
8863 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8864 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8865 fp = popen(buf,"r");
8866 if(fp == NULL)
8867 return RETURN_ERR;
8868 else
8869 {
8870 fgets(path,sizeof(path),fp);
8871 maccount = atoi(path);
8872 }
8873 pclose(fp);
8874 *output_array_size = maccount;
8875 wifi_associated_dev3_t* temp = NULL;
8876 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8877 *associated_dev_array = temp;
8878 if(temp == NULL)
8879 {
8880 printf("Error Statement. Insufficient memory \n");
8881 return RETURN_ERR;
8882 }
8883 memset(buf,0,sizeof(buf));
8884 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8885 fp = popen(buf,"r");
8886 if (fp == NULL) {
8887 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8888 return RETURN_ERR;
8889 }
8890 for(count = 0; count < maccount ; count++)
8891 {
8892 fgets(path,sizeof(path),fp);
8893 for(i = 0; path[i]!='\n';i++)
8894 str[i]=path[i];
8895 str[i]='\0';
8896 getIPAddress(str,ipaddr);
8897 memset(buf,0,sizeof(buf));
8898 if(strlen(ipaddr) > 0)
8899 {
8900 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8901 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8902 {
8903 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8904 {
8905 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8906 {
8907 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8908
8909 }
8910 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8911 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]);
8912 }
8913 temp[count].cli_AuthenticationState = 0; //TODO
developer69b61b02023-03-07 17:17:44 +08008914 temp[count].cli_Active = 0; //TODO
developer72fb0bb2023-01-11 09:46:29 +08008915 temp[count].cli_SignalStrength = 0;
8916 }
8917 else //Active wireless clients info
8918 {
8919 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8920 {
8921 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8922 {
8923 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8924
8925 }
8926 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8927 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]);
8928 }
8929 temp[count].cli_Active = 1;
8930 }
8931 }
8932 memset(ipaddr,0,sizeof(ipaddr));
8933 }
8934 pclose(fp);
8935 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8936 return RETURN_OK;
8937}
8938//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8939//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8940//To get Band Steering Capability
8941INT wifi_getBandSteeringCapability(BOOL *support)
8942{
8943 *support = FALSE;
8944 return RETURN_OK;
8945}
8946
8947
8948//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8949//To get Band Steering enable status
8950INT wifi_getBandSteeringEnable(BOOL *enable)
8951{
8952 *enable = FALSE;
8953 return RETURN_OK;
8954}
8955
8956//To turn on/off Band steering
8957INT wifi_setBandSteeringEnable(BOOL enable)
8958{
8959 return RETURN_OK;
8960}
8961
8962//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8963//To get Band Steering AP group
8964INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8965{
8966 if (NULL == output_ApGroup)
8967 return RETURN_ERR;
8968
8969 strcpy(output_ApGroup, "1,2");
8970 return RETURN_OK;
8971}
8972
8973//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8974//to set and read the band steering BandUtilizationThreshold parameters
8975INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8976{
8977 return RETURN_ERR;
8978}
8979
8980INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8981{
8982 return RETURN_ERR;
8983}
8984
8985//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8986//to set and read the band steering RSSIThreshold parameters
8987INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8988{
8989 return RETURN_ERR;
8990}
8991
8992INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8993{
8994 return RETURN_ERR;
8995}
8996
8997
8998//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8999//to set and read the band steering physical modulation rate threshold parameters
9000INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
9001{
9002 //If chip is not support, return -1
9003 return RETURN_ERR;
9004}
9005
9006INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
9007{
9008 //If chip is not support, return -1
9009 return RETURN_ERR;
9010}
9011
9012//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
9013//to set and read the inactivity time (in seconds) for steering under overload condition
9014INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
9015{
9016 return RETURN_ERR;
9017}
9018
9019INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
9020{
9021 return RETURN_ERR;
9022}
9023
9024//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
9025//to set and read the inactivity time (in seconds) for steering under Idle condition
9026INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
9027{
9028 return RETURN_ERR;
9029}
9030
9031INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
9032{
9033 return RETURN_ERR;
9034}
9035
9036//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
9037//pClientMAC[64]
9038//pSourceSSIDIndex[64]
9039//pDestSSIDIndex[64]
9040//pSteeringReason[256]
9041INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
9042{
9043 //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
9044 *pSteeringTime=time(NULL);
9045 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
9046 return RETURN_OK;
9047}
9048
9049INT wifi_ifConfigDown(INT apIndex)
9050{
9051 INT status = RETURN_OK;
9052 char cmd[64];
9053
9054 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
9055 printf("%s: %s\n", __func__, cmd);
9056 system(cmd);
9057
9058 return status;
9059}
9060
9061INT wifi_ifConfigUp(INT apIndex)
9062{
9063 char interface_name[16] = {0};
9064 char cmd[128];
9065 char buf[1024];
9066
9067 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9068 return RETURN_ERR;
9069 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
9070 _syscmd(cmd, buf, sizeof(buf));
9071 return 0;
9072}
9073
9074//>> Deprecated. Replace with wifi_applyRadioSettings
9075INT wifi_pushBridgeInfo(INT apIndex)
9076{
9077 char interface_name[16] = {0};
9078 char ip[32] = {0};
9079 char subnet[32] = {0};
9080 char bridge[32] = {0};
9081 int vlanId = 0;
9082 char cmd[128] = {0};
9083 char buf[1024] = {0};
9084
9085 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
9086 wifi_getApVlanID(apIndex,&vlanId);
9087
9088 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9089 return RETURN_ERR;
9090 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
9091 _syscmd(cmd,buf, sizeof(buf));
9092
9093 return 0;
9094}
9095
9096INT wifi_pushChannel(INT radioIndex, UINT channel)
9097{
9098 char interface_name[16] = {0};
9099 char cmd[128];
9100 char buf[1024];
9101 int apIndex;
9102
developer69b61b02023-03-07 17:17:44 +08009103 apIndex=(radioIndex==0)?0:1;
developer72fb0bb2023-01-11 09:46:29 +08009104 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9105 return RETURN_ERR;
9106 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
9107 _syscmd(cmd,buf, sizeof(buf));
9108
9109 return 0;
9110}
9111
9112INT wifi_pushChannelMode(INT radioIndex)
9113{
9114 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
9115 return RETURN_ERR;
9116}
9117
9118INT wifi_pushDefaultValues(INT radioIndex)
9119{
9120 //Apply Comcast specified default radio settings instantly
9121 //AMPDU=1
9122 //AMPDUFrames=32
9123 //AMPDULim=50000
9124 //txqueuelen=1000
9125
9126 return RETURN_ERR;
9127}
9128
9129INT wifi_pushTxChainMask(INT radioIndex)
9130{
9131 //Apply default TxChainMask instantly
9132 return RETURN_ERR;
9133}
9134
9135INT wifi_pushRxChainMask(INT radioIndex)
9136{
9137 //Apply default RxChainMask instantly
9138 return RETURN_ERR;
9139}
9140
9141INT wifi_pushSSID(INT apIndex, CHAR *ssid)
9142{
developer7e4a2a62023-04-06 19:56:03 +08009143 INT status;
developer72fb0bb2023-01-11 09:46:29 +08009144
developer7e4a2a62023-04-06 19:56:03 +08009145 status = wifi_setSSIDName(apIndex, ssid);
9146 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08009147
developer7e4a2a62023-04-06 19:56:03 +08009148 return status;
developer72fb0bb2023-01-11 09:46:29 +08009149}
9150
9151INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
9152{
9153 //Apply default Ssid Advertisement instantly
9154 return RETURN_ERR;
9155}
9156
9157INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
9158{
developere82c0ca2023-05-10 16:25:35 +08009159 time_t now;
9160
9161 time(&now);
9162 if (now > radio_up_time[radioIndex])
9163 *output = now - radio_up_time[radioIndex];
9164 else {
9165 *output = 0;
9166 return RETURN_ERR;
9167 }
9168
9169 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08009170}
9171
9172INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
9173{
9174 return RETURN_OK;
9175}
9176
9177INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
9178{
9179 return RETURN_OK;
9180}
9181
9182//To-do
9183INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
9184{
9185 char output[16]={'\0'};
9186 char config_file[MAX_BUF_SIZE] = {0};
9187
9188 if (!output_string)
9189 return RETURN_ERR;
9190
9191 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9192 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
9193
9194 if (strlen(output) == 0)
9195 snprintf(output_string, 64, "Disabled");
9196 else if (strncmp(output, "0", 1) == 0)
9197 snprintf(output_string, 64, "Disabled");
9198 else if (strncmp(output, "1", 1) == 0)
9199 snprintf(output_string, 64, "Optional");
9200 else if (strncmp(output, "2", 1) == 0)
9201 snprintf(output_string, 64, "Required");
9202 else {
9203 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
9204 return RETURN_ERR;
9205 }
9206
9207 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
9208 return RETURN_OK;
9209}
9210INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
9211{
9212 char str[MAX_BUF_SIZE]={'\0'};
9213 char cmd[MAX_CMD_SIZE]={'\0'};
9214 struct params params;
9215 char config_file[MAX_BUF_SIZE] = {0};
9216
9217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9218 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
9219 return RETURN_ERR;
9220
9221 params.name = "ieee80211w";
9222 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
9223 params.value = "0";
9224 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
9225 params.value = "1";
9226 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
9227 params.value = "2";
9228 else{
9229 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
9230 return RETURN_ERR;
9231 }
9232 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9233 wifi_hostapdWrite(config_file, &params, 1);
9234 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
9235 return RETURN_OK;
9236}
9237INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
9238{
9239 char output[16]={'\0'};
9240 char config_file[MAX_BUF_SIZE] = {0};
9241
9242 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerd1824452023-05-18 12:30:04 +08009243 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);ss
9244 wifi_datfileRead(config_file, "Channel" , output, sizeof(output));
developer72fb0bb2023-01-11 09:46:29 +08009245
9246 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
9247 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9248
9249 return RETURN_OK;
9250}
9251
9252INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
9253{
9254 return RETURN_OK;
9255}
9256
9257INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
9258{
9259 return RETURN_OK;
9260}
9261
9262INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
9263{
9264 return RETURN_OK;
9265}
9266
9267INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
9268{
9269 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9270 char config_file[MAX_BUF_SIZE] = {0};
9271
9272 if (NULL == output)
9273 return RETURN_ERR;
9274 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
9275 wifi_hostapdRead(config_file,"hw_mode",output,64);
9276
9277 if(strcmp(output,"b")==0)
9278 sprintf(output, "%s", "1,2,5.5,11");
9279 else if (strcmp(output,"a")==0)
9280 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
9281 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
9282 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
9283
9284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9285 return RETURN_OK;
9286}
9287
9288INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
9289{
9290 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9291 char *temp;
9292 char temp_output[128];
9293 char temp_TransmitRates[128];
9294 char config_file[MAX_BUF_SIZE] = {0};
9295
9296 if (NULL == output)
9297 return RETURN_ERR;
9298
9299 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
9300 wifi_hostapdRead(config_file,"supported_rates",output,64);
9301
9302 if (strlen(output) == 0) {
9303 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
9304 return RETURN_OK;
9305 }
9306 strcpy(temp_TransmitRates,output);
9307 strcpy(temp_output,"");
9308 temp = strtok(temp_TransmitRates," ");
9309 while(temp!=NULL)
9310 {
9311 temp[strlen(temp)-1]=0;
9312 if((temp[0]=='5') && (temp[1]=='\0'))
9313 {
9314 temp="5.5";
9315 }
9316 strcat(temp_output,temp);
9317 temp = strtok(NULL," ");
9318 if(temp!=NULL)
9319 {
9320 strcat(temp_output,",");
9321 }
9322 }
9323 strcpy(output,temp_output);
9324 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9325
9326 return RETURN_OK;
9327}
9328
9329INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
9330{
9331 return RETURN_OK;
9332}
9333
9334
9335INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
9336{
9337 int i=0;
9338 char *temp;
9339 char temp1[128] = {0};
9340 char temp_output[128] = {0};
9341 char temp_TransmitRates[128] = {0};
9342 struct params params={'\0'};
9343 char config_file[MAX_BUF_SIZE] = {0};
9344 wifi_band band = wifi_index_to_band(wlanIndex);
9345
9346 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9347 if(NULL == output)
9348 return RETURN_ERR;
9349 strcpy(temp_TransmitRates,output);
9350
9351 for(i=0;i<strlen(temp_TransmitRates);i++)
9352 {
9353 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
9354 {
9355 continue;
9356 }
9357 else
9358 {
9359 return RETURN_ERR;
9360 }
9361 }
9362 strcpy(temp_output,"");
9363 temp = strtok(temp_TransmitRates,",");
9364 while(temp!=NULL)
9365 {
9366 strcpy(temp1,temp);
9367 if(band == band_5)
9368 {
9369 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
9370 {
9371 return RETURN_ERR;
9372 }
9373 }
9374
9375 if(strcmp(temp,"5.5")==0)
9376 {
9377 strcpy(temp1,"55");
9378 }
9379 else
9380 {
9381 strcat(temp1,"0");
9382 }
9383 strcat(temp_output,temp1);
9384 temp = strtok(NULL,",");
9385 if(temp!=NULL)
9386 {
9387 strcat(temp_output," ");
9388 }
9389 }
9390 strcpy(output,temp_output);
9391
9392 params.name = "supported_rates";
9393 params.value = output;
9394
9395 wifi_dbg_printf("\n%s:",__func__);
9396 wifi_dbg_printf("params.value=%s\n",params.value);
9397 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
9398 wifi_hostapdWrite(config_file,&params,1);
9399 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9400
9401 return RETURN_OK;
9402}
9403
9404
9405static char *sncopy(char *dst, int dst_sz, const char *src)
9406{
9407 if (src && dst && dst_sz > 0) {
9408 strncpy(dst, src, dst_sz);
9409 dst[dst_sz - 1] = '\0';
9410 }
9411 return dst;
9412}
9413
9414static int util_get_sec_chan_offset(int channel, const char* ht_mode)
9415{
9416 if (0 == strcmp(ht_mode, "HT40") ||
9417 0 == strcmp(ht_mode, "HT80") ||
9418 0 == strcmp(ht_mode, "HT160")) {
9419 switch (channel) {
9420 case 1 ... 7:
9421 case 36:
9422 case 44:
9423 case 52:
9424 case 60:
9425 case 100:
9426 case 108:
9427 case 116:
9428 case 124:
9429 case 132:
9430 case 140:
9431 case 149:
9432 case 157:
9433 return 1;
9434 case 8 ... 13:
9435 case 40:
9436 case 48:
9437 case 56:
9438 case 64:
9439 case 104:
9440 case 112:
9441 case 120:
9442 case 128:
9443 case 136:
9444 case 144:
9445 case 153:
9446 case 161:
9447 return -1;
9448 default:
9449 return -EINVAL;
9450 }
9451 }
9452
9453 return -EINVAL;
9454}
9455
9456static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
9457{
9458 int idx = channel%8;
9459 if (0 == strcmp(ht_mode, "HT40") ||
9460 0 == strcmp(ht_mode, "HT80") ||
9461 0 == strcmp(ht_mode, "HT160")) {
9462 switch (idx) {
9463 case 1:
9464 return 1;
9465 case 5:
9466 return -1;
9467 default:
9468 return -EINVAL;
9469 }
9470 }
9471
9472 return -EINVAL;
9473}
9474static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
9475{
9476 if (NULL == hw_mode) return;
9477
9478 if (0 == strcmp(hw_mode, "ac"))
9479 sncopy(bw_mode, bw_mode_len, "ht vht");
9480
9481 if (0 == strcmp(hw_mode, "n"))
9482 sncopy(bw_mode, bw_mode_len, "ht");
9483
9484 return;
9485}
9486
9487static int util_chan_to_freq(int chan)
9488{
9489 if (chan == 14)
9490 return 2484;
9491 else if (chan < 14)
9492 return 2407 + chan * 5;
9493 else if (chan >= 182 && chan <= 196)
9494 return 4000 + chan * 5;
9495 else
9496 return 5000 + chan * 5;
9497 return 0;
9498}
9499
9500static int util_6G_chan_to_freq(int chan)
9501{
9502 if (chan)
9503 return 5950 + chan * 5;
9504 else
9505 return 0;
developer69b61b02023-03-07 17:17:44 +08009506
developer72fb0bb2023-01-11 09:46:29 +08009507}
9508const int *util_unii_5g_chan2list(int chan, int width)
9509{
9510 static const int lists[] = {
9511 // <width>, <chan1>, <chan2>..., 0,
9512 20, 36, 0,
9513 20, 40, 0,
9514 20, 44, 0,
9515 20, 48, 0,
9516 20, 52, 0,
9517 20, 56, 0,
9518 20, 60, 0,
9519 20, 64, 0,
9520 20, 100, 0,
9521 20, 104, 0,
9522 20, 108, 0,
9523 20, 112, 0,
9524 20, 116, 0,
9525 20, 120, 0,
9526 20, 124, 0,
9527 20, 128, 0,
9528 20, 132, 0,
9529 20, 136, 0,
9530 20, 140, 0,
9531 20, 144, 0,
9532 20, 149, 0,
9533 20, 153, 0,
9534 20, 157, 0,
9535 20, 161, 0,
9536 20, 165, 0,
9537 40, 36, 40, 0,
9538 40, 44, 48, 0,
9539 40, 52, 56, 0,
9540 40, 60, 64, 0,
9541 40, 100, 104, 0,
9542 40, 108, 112, 0,
9543 40, 116, 120, 0,
9544 40, 124, 128, 0,
9545 40, 132, 136, 0,
9546 40, 140, 144, 0,
9547 40, 149, 153, 0,
9548 40, 157, 161, 0,
9549 80, 36, 40, 44, 48, 0,
9550 80, 52, 56, 60, 64, 0,
9551 80, 100, 104, 108, 112, 0,
9552 80, 116, 120, 124, 128, 0,
9553 80, 132, 136, 140, 144, 0,
9554 80, 149, 153, 157, 161, 0,
9555 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
9556 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
9557 -1 // final delimiter
9558 };
9559 const int *start;
9560 const int *p;
9561
9562 for (p = lists; *p != -1; p++) {
9563 if (*p == width) {
9564 for (start = ++p; *p != 0; p++) {
9565 if (*p == chan)
9566 return start;
9567 }
9568 }
9569 // move to the end of channel list of given width
9570 while (*p != 0) {
9571 p++;
9572 }
9573 }
9574
9575 return NULL;
9576}
9577
9578static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
9579{
9580 if (NULL == ht_mode)
9581 return 0;
9582
9583 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
9584 const int *chans = util_unii_5g_chan2list(channel, width);
9585 int sum = 0;
9586 int cnt = 0;
9587
9588 if (NULL == chans)
9589 return 0;
9590
9591 while (*chans) {
9592 sum += *chans;
9593 cnt++;
9594 chans++;
9595 }
9596 if (cnt == 0)
9597 return 0;
9598 return sum / cnt;
9599}
9600
9601static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
9602{
9603 if (NULL == ht_mode)
9604 return 0;
9605
9606 int width = strtol((ht_mode + 2), NULL, 10);
9607
9608 int idx = 0 ;
9609 int centerchan = 0;
9610 int chan_ofs = 1;
9611
9612 if (width == 40){
9613 idx = ((channel/4) + chan_ofs)%2;
9614 switch (idx) {
9615 case 0:
9616 centerchan = (channel - 2);
9617 break;
9618 case 1:
9619 centerchan = (channel + 2);
developer69b61b02023-03-07 17:17:44 +08009620 break;
developer72fb0bb2023-01-11 09:46:29 +08009621 default:
9622 return -EINVAL;
9623 }
9624 }else if (width == 80){
developer69b61b02023-03-07 17:17:44 +08009625 idx = ((channel/4) + chan_ofs)%4;
developer72fb0bb2023-01-11 09:46:29 +08009626 switch (idx) {
9627 case 0:
9628 centerchan = (channel - 6);
9629 break;
9630 case 1:
9631 centerchan = (channel + 6);
9632 break;
9633 case 2:
9634 centerchan = (channel + 2);
9635 break;
9636 case 3:
9637 centerchan = (channel - 2);
9638 break;
9639 default:
9640 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08009641 }
developer72fb0bb2023-01-11 09:46:29 +08009642 }else if (width == 160){
9643 switch (channel) {
9644 case 1 ... 29:
9645 centerchan = 15;
9646 break;
9647 case 33 ... 61:
9648 centerchan = 47;
9649 break;
9650 case 65 ... 93:
9651 centerchan = 79;
9652 break;
9653 case 97 ... 125:
9654 centerchan = 111;
9655 break;
9656 case 129 ... 157:
9657 centerchan = 143;
9658 break;
9659 case 161 ... 189:
9660 centerchan = 175;
9661 break;
9662 case 193 ... 221:
9663 centerchan = 207;
9664 break;
9665 default:
9666 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08009667 }
developer72fb0bb2023-01-11 09:46:29 +08009668 }
9669 return centerchan;
9670}
9671static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9672{
9673 BOOL onlyG, onlyN, onlyA;
9674 CHAR tmp[64];
9675 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9676 if (ret == RETURN_OK) {
9677 sncopy(hw_mode, hw_mode_size, tmp);
9678 }
9679 return ret;
9680}
9681
9682INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9683{
9684 // Sample commands:
9685 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9686 // hostapd_cli -i wifi0 chan_switch 30 2437
9687 char cmd[MAX_CMD_SIZE] = {0};
9688 char buf[MAX_BUF_SIZE] = {0};
9689 int freq = 0, ret = 0;
9690 char center_freq1_str[32] = ""; // center_freq1=%d
9691 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9692 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9693 char hw_mode[16] = ""; // n|ac
9694 char bw_mode[16] = ""; // ht|ht vht
9695 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
9696 char interface_name[16] = {0};
9697 int sec_chan_offset;
9698 int width;
9699 char config_file[64] = {0};
9700 BOOL stbcEnable = FALSE;
9701 char *ext_str = "None";
9702 wifi_band band = band_invalid;
9703 int center_chan = 0;
9704 int center_freq1 = 0;
developerd1824452023-05-18 12:30:04 +08009705 struct params mwctl = {0};
9706 char str_channel[8]={0};
developer72fb0bb2023-01-11 09:46:29 +08009707
9708 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
9709
9710 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9711 return RETURN_ERR;
9712
9713 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9714
9715 band = wifi_index_to_band(radioIndex);
9716
9717 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
9718
9719 // Get radio mode HT20|HT40|HT80 etc.
9720 if (channel){
9721 if (band == band_6){
9722 freq = util_6G_chan_to_freq(channel);
9723 }else{
9724 freq = util_chan_to_freq(channel);
9725 }
9726 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
9727
9728 // Provide bandwith if specified
9729 if (channel_width_MHz > 20) {
9730 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9731 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9732 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
9733
9734 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9735 }else if (channel_width_MHz == 20){
9736 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9737 }
9738
9739
9740 if (channel_width_MHz > 20) {
9741 if (band == band_6){
9742 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9743 if(center_chan){
9744 center_freq1 = util_6G_chan_to_freq(center_chan);
9745 }
9746 }else{
9747 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9748 if(center_chan){
9749 center_freq1 = util_chan_to_freq(center_chan);
9750 }
9751 }
developer69b61b02023-03-07 17:17:44 +08009752
developer72fb0bb2023-01-11 09:46:29 +08009753 if (center_freq1)
9754 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
developer69b61b02023-03-07 17:17:44 +08009755
developer72fb0bb2023-01-11 09:46:29 +08009756 }
9757
9758 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9759 if (band == band_6){
9760 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9761 }else{
9762 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
9763 }
9764 if (sec_chan_offset != -EINVAL)
9765 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
9766
9767 // Only the first AP, other are hanging on the same radio
9768 int apIndex = radioIndex;
developerd1824452023-05-18 12:30:04 +08009769 /* snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
developer72fb0bb2023-01-11 09:46:29 +08009770 interface_name, csa_beacon_count, freq,
developerd1824452023-05-18 12:30:04 +08009771 sec_chan_offset_str, center_freq1_str, opt_chan_info_str); */
9772 snprintf(str_channel, sizeof(str_channel), "%d", channel);
9773 mwctl.name = "channel num=";
9774 mwctl.value = str_channel;
9775 ret = wifi_mwctlSet(radioIndex, &mwctl, BASE_PHY_INDEX);
9776 if (ret != RETURN_OK) {
9777 fprintf(stderr, "%s: wifi_mwctlSet return error.\n", __func__);
9778 return RETURN_ERR;
9779 }
9780 /* wifi_dbg_printf("execute: '%s'\n", cmd);
developerf6a87542023-05-16 15:47:28 +08009781 ret = _syscmd(cmd, buf, sizeof(buf));
developerd1824452023-05-18 12:30:04 +08009782 wifi_reloadAp(radioIndex); */
developer72fb0bb2023-01-11 09:46:29 +08009783
9784 ret = wifi_setRadioChannel(radioIndex, channel);
9785 if (ret != RETURN_OK) {
9786 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9787 return RETURN_ERR;
9788 }
9789
9790 if (sec_chan_offset == 1) ext_str = "Above";
9791 else if (sec_chan_offset == -1) ext_str = "Below";
9792
developerd1824452023-05-18 12:30:04 +08009793 /*wifi_setRadioCenterChannel(radioIndex, center_chan); */
developer72fb0bb2023-01-11 09:46:29 +08009794
9795 } else {
9796 if (channel_width_MHz > 20)
9797 ext_str = "Above";
9798 }
9799
9800 wifi_setRadioExtChannel(radioIndex, ext_str);
9801
9802 char mhz_str[16];
9803 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
9804 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
9805
9806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9807
9808 return RETURN_OK;
9809}
9810
9811INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9812{
9813 int index = -1;
9814 wifi_neighbor_ap2_t *scan_array = NULL;
9815 char cmd[256]={0};
9816 char buf[128]={0};
9817 char file_name[32] = {0};
9818 char filter_SSID[32] = {0};
9819 char line[256] = {0};
9820 char interface_name[16] = {0};
9821 char *ret = NULL;
9822 int freq=0;
9823 FILE *f = NULL;
9824 size_t len=0;
9825 int channels_num = 0;
9826 int vht_channel_width = 0;
9827 int get_noise_ret = RETURN_ERR;
9828 bool filter_enable = false;
9829 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
9830 int phyId = 0;
9831
9832 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
9833
9834 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9835 f = fopen(file_name, "r");
9836 if (f != NULL) {
9837 fgets(filter_SSID, sizeof(file_name), f);
9838 if (strlen(filter_SSID) != 0)
9839 filter_enable = true;
9840 fclose(f);
9841 }
9842
9843 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
9844 return RETURN_ERR;
9845
9846 phyId = radio_index_to_phy(radio_index);
9847
9848 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
9849 _syscmd(cmd, buf, sizeof(buf));
9850 channels_num = strtol(buf, NULL, 10);
9851
9852 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9853 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
9854 fprintf(stderr, "cmd: %s\n", cmd);
9855 if ((f = popen(cmd, "r")) == NULL) {
9856 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9857 return RETURN_ERR;
9858 }
developer69b61b02023-03-07 17:17:44 +08009859
developer72fb0bb2023-01-11 09:46:29 +08009860 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9861 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08009862
developer72fb0bb2023-01-11 09:46:29 +08009863 ret = fgets(line, sizeof(line), f);
9864 while (ret != NULL) {
9865 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08009866 // 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 +08009867 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9868 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9869
9870 if (!filter_BSS) {
9871 index++;
9872 wifi_neighbor_ap2_t *tmp;
9873 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9874 if (tmp == NULL) { // no more memory to use
9875 index--;
9876 wifi_dbg_printf("%s: realloc failed\n", __func__);
9877 break;
9878 }
9879 scan_array = tmp;
9880 }
9881 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9882
9883 filter_BSS = false;
9884 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9885 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9886 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9887 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9888 } else if (strstr(line, "freq") != NULL) {
9889 sscanf(line," freq: %d", &freq);
9890 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
9891
9892 if (freq >= 2412 && freq <= 2484) {
9893 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9894 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9895 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9896 }
9897 else if (freq >= 5160 && freq <= 5805) {
9898 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9899 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9900 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9901 }
9902
9903 scan_array[index].ap_Noise = 0;
9904 if (get_noise_ret == RETURN_OK) {
9905 for (int i = 0; i < channels_num; i++) {
9906 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9907 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9908 break;
9909 }
9910 }
9911 }
9912 } else if (strstr(line, "beacon interval") != NULL) {
9913 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9914 } else if (strstr(line, "signal") != NULL) {
9915 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9916 } else if (strstr(line,"SSID") != NULL) {
9917 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9918 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9919 filter_BSS = true;
9920 }
9921 } else if (strstr(line, "Supported rates") != NULL) {
9922 char SRate[80] = {0}, *tmp = NULL;
9923 memset(buf, 0, sizeof(buf));
9924 strcpy(SRate, line);
9925 tmp = strtok(SRate, ":");
9926 tmp = strtok(NULL, ":");
9927 strcpy(buf, tmp);
9928 memset(SRate, 0, sizeof(SRate));
9929
9930 tmp = strtok(buf, " \n");
9931 while (tmp != NULL) {
9932 strcat(SRate, tmp);
9933 if (SRate[strlen(SRate) - 1] == '*') {
9934 SRate[strlen(SRate) - 1] = '\0';
9935 }
9936 strcat(SRate, ",");
9937
9938 tmp = strtok(NULL, " \n");
9939 }
9940 SRate[strlen(SRate) - 1] = '\0';
9941 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9942 } else if (strstr(line, "DTIM") != NULL) {
9943 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9944 } else if (strstr(line, "VHT capabilities") != NULL) {
9945 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9946 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9947 } else if (strstr(line, "HT capabilities") != NULL) {
9948 strcat(scan_array[index].ap_SupportedStandards, ",n");
9949 strcpy(scan_array[index].ap_OperatingStandards, "n");
9950 } else if (strstr(line, "VHT operation") != NULL) {
9951 ret = fgets(line, sizeof(line), f);
9952 sscanf(line," * channel width: %d", &vht_channel_width);
9953 if(vht_channel_width == 1) {
9954 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9955 } else {
9956 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9957 }
9958 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9959 continue;
9960 } else if (strstr(line, "HT operation") != NULL) {
9961 ret = fgets(line, sizeof(line), f);
9962 sscanf(line," * secondary channel offset: %s", &buf);
9963 if (!strcmp(buf, "above")) {
9964 //40Mhz +
9965 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
9966 }
9967 else if (!strcmp(buf, "below")) {
9968 //40Mhz -
9969 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9970 } else {
9971 //20Mhz
9972 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
9973 }
9974 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9975 continue;
9976 } else if (strstr(line, "HE capabilities") != NULL) {
9977 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9978 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9979 ret = fgets(line, sizeof(line), f);
9980 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9981 if (strstr(line, "HE40/2.4GHz") != NULL)
9982 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9983 else
9984 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9985 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9986 if (strstr(line, "HE80/5GHz") != NULL) {
9987 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9988 ret = fgets(line, sizeof(line), f);
9989 } else
9990 continue;
9991 if (strstr(line, "HE160/5GHz") != NULL)
9992 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
9993 }
9994 continue;
9995 } else if (strstr(line, "WPA") != NULL) {
9996 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9997 } else if (strstr(line, "RSN") != NULL) {
9998 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9999 } else if (strstr(line, "Group cipher") != NULL) {
10000 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
10001 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
10002 strcpy(scan_array[index].ap_EncryptionMode, "AES");
10003 }
10004 }
10005 ret = fgets(line, sizeof(line), f);
10006 }
10007
10008 if (!filter_BSS) {
10009 *output_array_size = index + 1;
10010 } else {
10011 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
10012 *output_array_size = index;
10013 }
10014 *neighbor_ap_array = scan_array;
10015 pclose(f);
10016 free(channels_noise_arr);
10017 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10018 return RETURN_OK;
10019}
10020
10021INT wifi_getApAssociatedDeviceStats(
10022 INT apIndex,
10023 mac_address_t *clientMacAddress,
10024 wifi_associated_dev_stats_t *associated_dev_stats,
10025 u64 *handle)
10026{
10027 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
10028 char interface_name[50] = {0};
10029 char cmd[1024] = {0};
10030 char mac_str[18] = {0};
10031 char *key = NULL;
10032 char *val = NULL;
10033 FILE *f = NULL;
10034 char *line = NULL;
10035 size_t len = 0;
10036
10037 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
10038 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
10039 return RETURN_ERR;
10040 }
10041
10042 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
10043 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
10044 if((f = popen(cmd, "r")) == NULL) {
10045 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
10046 return RETURN_ERR;
10047 }
10048
10049 while ((getline(&line, &len, f)) != -1) {
10050 key = strtok(line,":");
10051 val = strtok(NULL,":");
10052
10053 if(!strncmp(key,"rx bytes",8))
10054 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
10055 if(!strncmp(key,"tx bytes",8))
10056 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
10057 if(!strncmp(key,"rx packets",10))
10058 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
10059 if(!strncmp(key,"tx packets",10))
10060 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
10061 if(!strncmp(key,"tx retries",10))
10062 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
10063 if(!strncmp(key,"tx failed",9))
10064 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
10065 if(!strncmp(key,"rx drop misc",13))
10066 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
10067 if(!strncmp(key,"rx bitrate",10)) {
10068 val = strtok(val, " ");
10069 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
10070 }
10071 if(!strncmp(key,"tx bitrate",10)) {
10072 val = strtok(val, " ");
10073 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
10074 }
10075 }
10076 free(line);
10077 pclose(f);
10078 return RETURN_OK;
10079}
10080
10081INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
10082{
developer7e4a2a62023-04-06 19:56:03 +080010083 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080010084 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
10085
developer7e4a2a62023-04-06 19:56:03 +080010086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
10087
developer72fb0bb2023-01-11 09:46:29 +080010088 if (NULL == output_string)
10089 return RETURN_ERR;
10090
10091 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10092 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +080010093
10094 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 +080010095 _syscmd(cmd, buf, sizeof(buf));
10096
10097 //size of SSID name restricted to value less than 32 bytes
10098 snprintf(output_string, 32, "%s", buf);
developer7e4a2a62023-04-06 19:56:03 +080010099 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +080010100
10101 return RETURN_OK;
10102}
10103
10104INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
10105{
developer7e4a2a62023-04-06 19:56:03 +080010106 char cmd[MAX_CMD_SIZE] = {0};
10107 char buf[MAX_BUF_SIZE] = {0};
10108 char inf_name[IF_NAME_SIZE] = {0};
10109 char policy = 0;
developer72fb0bb2023-01-11 09:46:29 +080010110
10111 if (!output_filterMode)
10112 return RETURN_ERR;
10113
developer7e4a2a62023-04-06 19:56:03 +080010114 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
10115 return RETURN_ERR;
10116
10117 /* mwctl get acl policy */
10118 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | grep policy | cut -d '=' -f2 | tr -d '\\n'", inf_name);
10119 _syscmd(cmd, buf, sizeof(buf));
10120
10121
10122 policy = atoi(buf);
10123
10124 if (policy < 0 || policy > 2) {
10125 printf("%s:get wrong acl policy!!!\n", __func__);
10126 *output_filterMode = 0;
10127 return RETURN_ERR;
10128 } else
10129 *output_filterMode = policy;
10130
developer72fb0bb2023-01-11 09:46:29 +080010131
10132 return RETURN_OK;
10133}
10134
10135INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
10136{
10137 FILE *fp = NULL;
10138 char str[MAX_BUF_SIZE] = {0};
10139 int wificlientindex = 0 ;
10140 int count = 0;
10141 int signalstrength = 0;
10142 int arr[MACADDRESS_SIZE] = {0};
10143 unsigned char mac[MACADDRESS_SIZE] = {0};
10144 UINT wifi_count = 0;
10145 char virtual_interface_name[MAX_BUF_SIZE] = {0};
10146 char pipeCmd[MAX_CMD_SIZE] = {0};
10147
10148 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10149 *output_array_size = 0;
10150 *associated_dev_array = NULL;
10151 char interface_name[50] = {0};
10152
10153 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
10154 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
10155 return RETURN_ERR;
10156 }
10157
10158 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
10159 fp = popen(pipeCmd, "r");
10160 if (fp == NULL)
10161 {
10162 printf("Failed to run command inside function %s\n",__FUNCTION__ );
10163 return RETURN_ERR;
10164 }
10165
10166 /* Read the output a line at a time - output it. */
10167 fgets(str, sizeof(str)-1, fp);
10168 wifi_count = (unsigned int) atoi ( str );
10169 *output_array_size = wifi_count;
10170 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
10171 pclose(fp);
10172
10173 if(wifi_count == 0)
10174 {
10175 return RETURN_OK;
10176 }
10177 else
10178 {
10179 wifi_associated_dev2_t* temp = NULL;
10180 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
10181 *associated_dev_array = temp;
10182 if(temp == NULL)
10183 {
10184 printf("Error Statement. Insufficient memory \n");
10185 return RETURN_ERR;
10186 }
10187
10188 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
10189 system(pipeCmd);
10190
10191 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
10192 if(fp == NULL)
10193 {
10194 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
10195 return RETURN_ERR;
10196 }
10197 fclose(fp);
10198
10199 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
10200 fp = popen(pipeCmd, "r");
10201 if(fp)
10202 {
10203 for(count =0 ; count < wifi_count; count++)
10204 {
10205 fgets(str, MAX_BUF_SIZE, fp);
10206 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
10207 {
10208 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
10209 {
10210 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
10211
10212 }
10213 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
10214 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]);
10215 }
10216 temp[count].cli_AuthenticationState = 1; //TODO
10217 temp[count].cli_Active = 1; //TODO
10218 }
10219 pclose(fp);
10220 }
10221
10222 //Updating RSSI per client
10223 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
10224 fp = popen(pipeCmd, "r");
10225 if(fp)
10226 {
10227 pclose(fp);
10228 }
10229 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
10230 if(fp)
10231 {
10232 for(count =0 ; count < wifi_count ;count++)
10233 {
10234 fgets(str, MAX_BUF_SIZE, fp);
10235 signalstrength = atoi(str);
10236 temp[count].cli_RSSI = signalstrength;
10237 }
10238 pclose(fp);
10239 }
10240
10241
10242 //LastDataDownlinkRate
10243 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
10244 fp = popen(pipeCmd, "r");
10245 if (fp)
10246 {
10247 pclose(fp);
10248 }
10249 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
10250 if (fp)
10251 {
10252 for (count = 0; count < wifi_count; count++)
10253 {
10254 fgets(str, MAX_BUF_SIZE, fp);
10255 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
10256 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
10257 }
10258 pclose(fp);
10259 }
10260
10261 //LastDataUplinkRate
10262 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
10263 fp = popen(pipeCmd, "r");
10264 if (fp)
10265 {
10266 pclose(fp);
10267 }
10268 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
10269 if (fp)
10270 {
10271 for (count = 0; count < wifi_count; count++)
10272 {
10273 fgets(str, MAX_BUF_SIZE, fp);
10274 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
10275 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
10276 }
10277 pclose(fp);
10278 }
10279 }
10280 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10281 return RETURN_OK;
10282
10283}
10284
10285INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
10286{
10287#if 0
10288 /*char buf[1024] = {0};
10289 sprintf(cmd, "ifconfig %s ", interface_name);
10290 _syscmd(cmd, buf, sizeof(buf));*/
10291
10292 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
10293 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
10294 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
10295 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
10296
10297 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.
10298 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].
10299 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].
10300 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].
10301 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
10302 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
10303
10304 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
10305 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
10306 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
10307 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.
10308 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.
10309 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.
10310 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.
10311 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.
10312 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.
10313 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.
10314 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
10315#endif
10316
10317 FILE *fp = NULL;
10318 char interface_name[50] = {0};
10319 char pipeCmd[128] = {0};
10320 char str[256] = {0};
10321 wifi_ssidTrafficStats2_t *out = output_struct;
10322
10323 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
10324 if (!output_struct)
10325 return RETURN_ERR;
10326
10327 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
10328 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
10329 return RETURN_ERR;
10330 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
10331
10332 fp = popen(pipeCmd, "r");
10333 if (fp == NULL) {
10334 fprintf(stderr, "%s: popen failed\n", __func__);
10335 return RETURN_ERR;
10336 }
10337 fgets(str, sizeof(str), fp);
10338 pclose(fp);
10339
10340 if (strlen(str) == 0) // interface not exist
10341 return RETURN_OK;
10342
10343 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
10344 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
10345
10346 memset(str, 0, sizeof(str));
10347 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
10348 fp = popen(pipeCmd, "r");
10349 if (fp == NULL) {
10350 fprintf(stderr, "%s: popen failed\n", __func__);
10351 return RETURN_ERR;
10352 }
10353 fgets(str, sizeof(str), fp);
10354
10355 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
10356 &out->ssid_BroadcastPacketsSent);
10357 pclose(fp);
10358
10359 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
10360 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
10361
10362 // Not supported
10363 output_struct->ssid_RetransCount = 0;
10364 output_struct->ssid_FailedRetransCount = 0;
10365 output_struct->ssid_RetryCount = 0;
10366 output_struct->ssid_MultipleRetryCount = 0;
10367 output_struct->ssid_ACKFailureCount = 0;
10368 output_struct->ssid_AggregatedPacketCount = 0;
10369
10370 return RETURN_OK;
10371}
10372
10373//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).
10374INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
10375{
10376 char output_val[16]={'\0'};
10377 char config_file[MAX_BUF_SIZE] = {0};
10378
10379 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10380 if (!output)
10381 return RETURN_ERR;
10382 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10383 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
10384
10385 if( strcmp(output_val,"1") == 0 )
10386 *output = TRUE;
10387 else
10388 *output = FALSE;
10389 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10390
10391 return RETURN_OK;
10392}
10393
10394INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
10395{
10396 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10397 char str[MAX_BUF_SIZE]={'\0'};
10398 char string[MAX_BUF_SIZE]={'\0'};
10399 char cmd[MAX_CMD_SIZE]={'\0'};
10400 char *ch;
10401 char config_file[MAX_BUF_SIZE] = {0};
10402 struct params params;
10403
10404 if(enable == TRUE)
10405 strcpy(string,"1");
10406 else
10407 strcpy(string,"0");
10408
10409 params.name = "ap_isolate";
10410 params.value = string;
10411
10412 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10413 wifi_hostapdWrite(config_file,&params,1);
10414 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10415
10416 return RETURN_OK;
10417}
10418
10419INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
10420{
developera1255e42023-05-13 17:45:02 +080010421 char mgmtpwr_file[32] = {0};
10422 char cmd[64] = {0};
10423 char buf[32]={0};
10424
developer72fb0bb2023-01-11 09:46:29 +080010425 if (NULL == output_dBm)
10426 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080010427 snprintf(mgmtpwr_file, sizeof(mgmtpwr_file), "%s%d.txt", MGMT_POWER_CTRL, apIndex);
10428 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mgmtpwr_file);
10429 _syscmd(cmd, buf, sizeof(buf));
10430 if (strlen(buf) > 0)
10431 *output_dBm = strtol(buf, NULL, 10);
10432 else
10433 *output_dBm = 23;
developer72fb0bb2023-01-11 09:46:29 +080010434 return RETURN_OK;
10435}
10436
10437INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
10438{
developera1255e42023-05-13 17:45:02 +080010439 char interface_name[16] = {0};
10440 char cmd[128]={0};
10441 char buf[128]={0};
10442 char mgmt_pwr_file[128]={0};
10443 FILE *f = NULL;
10444
10445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10446
10447 if (wifi_GetInterfaceName(wlanIndex, interface_name) != RETURN_OK)
10448 return RETURN_ERR;
10449 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr mgmt_frame_pwr=%d", interface_name, dBm);
10450 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR) {
10451 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10452 return RETURN_ERR;
10453 }
10454 snprintf(mgmt_pwr_file, sizeof(mgmt_pwr_file), "%s%d.txt", MGMT_POWER_CTRL, wlanIndex);
10455 f = fopen(mgmt_pwr_file, "w");
10456 if (f == NULL) {
10457 fprintf(stderr, "%s: fopen failed\n", __func__);
10458 return RETURN_ERR;
10459 }
10460 fprintf(f, "%d", dBm);
10461 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +080010462 return RETURN_OK;
10463}
10464INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
10465{
10466 return RETURN_OK;
10467}
10468INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
10469{
10470 return RETURN_OK;
10471}
10472INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
10473{
10474 return RETURN_OK;
10475}
10476INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
10477{
10478 return RETURN_OK;
10479}
10480INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
10481{
10482 char config_file[MAX_BUF_SIZE] = {0};
10483 struct params list;
10484
10485 list.name = "bss_transition";
10486 list.value = activate?"1":"0";
10487 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
10488 wifi_hostapdWrite(config_file, &list, 1);
10489
10490 return RETURN_OK;
10491}
10492wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
10493
10494void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
10495{
10496 return;
10497}
10498
10499INT wifi_setApCsaDeauth(INT apIndex, INT mode)
10500{
10501 // TODO Implement me!
10502 return RETURN_OK;
10503}
10504
10505INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
10506{
10507 char file_name[128] = {0};
10508 char buf[128] = {0};
10509 FILE *f = NULL;
10510 int max_num_radios = 0;
10511
10512 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10513
10514 wifi_getMaxRadioNumber(&max_num_radios);
10515 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
10516 for (int index = 0; index < max_num_radios; index++) {
10517 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
10518 f = fopen(file_name, "w");
10519 if (f == NULL)
10520 return RETURN_ERR;
10521 // For mode == 0 is to disable filter, just don't write to the file.
10522 if (mode)
10523 fprintf(f, "%s", essid);
10524
10525 fclose(f);
10526 }
10527 } else { // special case, need to set AP's SSID as filter for each radio.
10528 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
10529 f = fopen(file_name, "w");
10530 if (f == NULL)
10531 return RETURN_ERR;
10532
10533 // For mode == 0 is to disable filter, just don't write to the file.
10534 if (mode)
10535 fprintf(f, "%s", essid);
10536
10537 fclose(f);
10538 }
10539
10540 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10541 return RETURN_OK;
10542}
10543
10544INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
10545{
10546 // TODO Implement me!
10547 //Apply wifi_pushRadioChannel() instantly
10548 return RETURN_ERR;
10549}
10550
10551INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
10552{
10553 // TODO Implement me!
10554 return RETURN_OK;
10555}
10556
10557#ifdef HAL_NETLINK_IMPL
10558static int tidStats_callback(struct nl_msg *msg, void *arg) {
10559 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10560 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10561 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10562 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
10563 int rem , tid_index = 0;
10564
10565 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
10566 wifi_associated_dev_tid_entry_t *stats_entry;
10567
10568 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
10569 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
10570 };
10571 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
10572 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
10573 };
10574
10575 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10576 genlmsg_attrlen(gnlh, 0), NULL);
10577
10578
10579 if (!tb[NL80211_ATTR_STA_INFO]) {
10580 fprintf(stderr, "station stats missing!\n");
10581 return NL_SKIP;
10582 }
10583
10584 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
10585 tb[NL80211_ATTR_STA_INFO],
10586 stats_policy)) {
10587 fprintf(stderr, "failed to parse nested attributes!\n");
10588 return NL_SKIP;
10589 }
10590
10591 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
10592 {
10593 stats_entry = &out->tid_array[tid_index];
10594
10595 stats_entry->tid = tid_index;
10596 stats_entry->ac = _tid_ac_index_get[tid_index];
10597
10598 if(sinfo[NL80211_STA_INFO_TID_STATS])
10599 {
10600 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
10601 printf("failed to parse nested stats attributes!");
10602 return NL_SKIP;
10603 }
10604 }
10605 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10606 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10607
10608 if(tid_index < (PS_MAX_TID - 1))
10609 tid_index++;
10610 }
10611 //ToDo: sum_time_ms, ewma_time_ms
10612 return NL_SKIP;
10613}
10614#endif
10615
10616INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
10617{
10618#ifdef HAL_NETLINK_IMPL
10619 Netlink nl;
10620 char if_name[10];
10621 char interface_name[16] = {0};
10622
10623 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10624 return RETURN_ERR;
10625
10626 snprintf(if_name, sizeof(if_name), "%s", interface_name);
10627
10628 nl.id = initSock80211(&nl);
10629
10630 if (nl.id < 0) {
10631 fprintf(stderr, "Error initializing netlink \n");
10632 return -1;
10633 }
10634
10635 struct nl_msg* msg = nlmsg_alloc();
10636
10637 if (!msg) {
10638 fprintf(stderr, "Failed to allocate netlink message.\n");
10639 nlfree(&nl);
10640 return -2;
10641 }
10642
10643 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080010644 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080010645 NL_AUTO_SEQ,
10646 nl.id,
10647 0,
10648 0,
10649 NL80211_CMD_GET_STATION,
10650 0);
10651
10652 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10653 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10654 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
developer8dd72532023-05-17 19:58:35 +080010655 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080010656 nl_recvmsgs(nl.socket, nl.cb);
10657 nlmsg_free(msg);
10658 nlfree(&nl);
10659 return RETURN_OK;
10660#else
10661//iw implementation
10662#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
10663#define TOTAL_MAX_LINES 50
10664
10665 char buf[256] = {'\0'}; /* or other suitable maximum line size */
10666 char if_name[32] = {0};
10667 FILE *fp=NULL;
10668 char pipeCmd[1024]= {'\0'};
10669 int lines,tid_index=0;
10670 char mac_addr[20] = {'\0'};
10671
10672 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10673 return RETURN_ERR;
10674
10675 wifi_associated_dev_tid_entry_t *stats_entry;
10676
10677 strcpy(mac_addr,clientMacAddress);
10678
10679 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
10680 fp= popen(pipeCmd,"r");
10681 if(fp == NULL)
10682 {
10683 perror("popen for station dump failed\n");
10684 return RETURN_ERR;
10685 }
10686 pclose(fp);
10687
10688 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
10689 fp=popen(pipeCmd,"r");
10690 if(fp == NULL)
10691 {
10692 perror("popen for grep station failed\n");
10693 return RETURN_ERR;
10694 }
10695 else if(fgets(buf,sizeof(buf),fp) != NULL)
10696 lines=atoi(buf);
10697 else
10698 {
10699 pclose(fp);
10700 fprintf(stderr,"No devices are connected \n");
10701 return RETURN_ERR;
10702 }
10703 pclose(fp);
10704
10705 if(lines == 1)
10706 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
10707
10708 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
10709 {
10710 stats_entry = &tid_stats->tid_array[tid_index];
10711 stats_entry->tid = tid_index;
10712
10713 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);
10714
10715 fp=popen(pipeCmd,"r");
10716 if(fp ==NULL)
10717 {
10718 perror("Failed to read from tid file \n");
10719 return RETURN_ERR;
10720 }
10721 else if(fgets(buf,sizeof(buf),fp) != NULL)
10722 stats_entry->num_msdus = atol(buf);
10723
10724 pclose(fp);
10725 stats_entry->ac = _tid_ac_index_get[tid_index];
10726// TODO:
10727// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
10728// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
10729 }
10730 return RETURN_OK;
10731#endif
10732}
10733
10734
10735INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
10736{
10737 char interface_name[16] = {0};
10738 char cmd[128]={0};
10739 char buf[128]={0};
10740 int freq = 0;
10741
10742 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10743
10744 // full mode is used to scan all channels.
10745 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10746 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
10747 ieee80211_channel_to_frequency(chan_list[0], &freq);
10748
10749 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10750 return RETURN_ERR;
10751
10752 if (freq)
10753 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
10754 else
10755 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
10756
10757 _syscmd(cmd, buf, sizeof(buf));
10758 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10759
10760 return RETURN_OK;
10761}
10762
10763
10764INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10765{
10766 // TODO Implement me!
10767 return RETURN_ERR;
10768}
10769
10770INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10771{
10772 // TODO Implement me!
10773 return RETURN_ERR;
10774}
10775
10776INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10777{
10778 // TODO Implement me!
10779 return RETURN_ERR;
10780}
10781
10782INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10783{
10784 // TODO Implement me!
10785 return RETURN_ERR;
10786}
10787
10788INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10789{
10790 // TODO Implement me!
10791 return RETURN_ERR;
10792}
10793
10794INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10795{
10796 // TODO Implement me!
10797 return RETURN_ERR;
10798}
10799
10800INT wifi_steering_eventUnregister(void)
10801{
10802 // TODO Implement me!
10803 return RETURN_ERR;
10804}
10805
10806INT wifi_delApAclDevices(INT apIndex)
10807{
developer7e4a2a62023-04-06 19:56:03 +080010808 char cmd[MAX_CMD_SIZE] = {0};
10809 char buf[MAX_BUF_SIZE] = {0};
10810 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080010811
developer7e4a2a62023-04-06 19:56:03 +080010812 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
10813 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080010814
developer7e4a2a62023-04-06 19:56:03 +080010815 /* mwctl acl clear all stas */
10816 snprintf(cmd, sizeof(cmd), "mwctl %s acl clear_all", inf_name);
10817 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080010818
10819 return RETURN_OK;
10820}
10821
10822#ifdef HAL_NETLINK_IMPL
10823static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10824 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10825 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10826 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10827 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10828 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10829 char mac_addr[20],dev[20];
10830
10831 nla_parse(tb,
10832 NL80211_ATTR_MAX,
10833 genlmsg_attrdata(gnlh, 0),
10834 genlmsg_attrlen(gnlh, 0),
10835 NULL);
10836
10837 if(!tb[NL80211_ATTR_STA_INFO]) {
10838 fprintf(stderr, "sta stats missing!\n");
10839 return NL_SKIP;
10840 }
10841
10842 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10843 fprintf(stderr, "failed to parse nested attributes!\n");
10844 return NL_SKIP;
10845 }
10846 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10847
10848 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10849
10850 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10851 fprintf(stderr, "failed to parse nested rate attributes!");
10852 return NL_SKIP;
10853 }
10854
10855 if(sinfo[NL80211_STA_INFO_TID_STATS])
10856 {
10857 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10858 printf("failed to parse nested stats attributes!");
10859 return NL_SKIP;
10860 }
10861 }
10862
10863 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10864 {
10865 printf("Type is VHT\n");
10866 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10867 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10868
10869 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10870 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10871 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10872 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10873 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10874 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10875 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10876 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10877 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10878 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10879 }
10880 else
10881 {
10882 printf(" OFDM or CCK \n");
10883 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10884 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10885 }
10886
10887 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10888 if(rinfo[NL80211_RATE_INFO_MCS])
10889 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10890 }
10891 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10892 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10893 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10894 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10895
10896 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10897 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10898
10899 if (sinfo[NL80211_STA_INFO_SIGNAL])
10900 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10901 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10902 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10903 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10904 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10905 //rssi_array need to be filled
10906 return NL_SKIP;
10907}
10908#endif
10909
10910INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10911{
10912#ifdef HAL_NETLINK_IMPL
10913 Netlink nl;
10914 char if_name[32];
10915 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10916 return RETURN_ERR;
10917
10918 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10919
10920 if (*output_array_size <= 0)
10921 return RETURN_OK;
10922
10923 nl.id = initSock80211(&nl);
10924
10925 if (nl.id < 0) {
10926 fprintf(stderr, "Error initializing netlink \n");
10927 return 0;
10928 }
10929
10930 struct nl_msg* msg = nlmsg_alloc();
10931
10932 if (!msg) {
10933 fprintf(stderr, "Failed to allocate netlink message.\n");
10934 nlfree(&nl);
10935 return 0;
10936 }
10937
10938 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080010939 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080010940 NL_AUTO_SEQ,
10941 nl.id,
10942 0,
10943 0,
10944 NL80211_CMD_GET_STATION,
10945 0);
10946
10947 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10948 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10949 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080010950 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080010951 nl_recvmsgs(nl.socket, nl.cb);
10952 nlmsg_free(msg);
10953 nlfree(&nl);
10954 return RETURN_OK;
10955#else
10956 //TODO Implement me
10957 return RETURN_OK;
10958#endif
10959}
10960
10961#ifdef HAL_NETLINK_IMPL
10962static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10963 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10964 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10965 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10966 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10967 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10968 char mac_addr[20],dev[20];
10969
10970 nla_parse(tb,
10971 NL80211_ATTR_MAX,
10972 genlmsg_attrdata(gnlh, 0),
10973 genlmsg_attrlen(gnlh, 0),
10974 NULL);
10975
10976 if(!tb[NL80211_ATTR_STA_INFO]) {
10977 fprintf(stderr, "sta stats missing!\n");
10978 return NL_SKIP;
10979 }
10980
10981 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10982 fprintf(stderr, "failed to parse nested attributes!\n");
10983 return NL_SKIP;
10984 }
10985
10986 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10987
10988 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10989
10990 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10991 fprintf(stderr, "failed to parse nested rate attributes!");
10992 return NL_SKIP;
10993 }
10994
10995 if(sinfo[NL80211_STA_INFO_TID_STATS])
10996 {
10997 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10998 printf("failed to parse nested stats attributes!");
10999 return NL_SKIP;
11000 }
11001 }
11002 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
11003 {
11004 printf("Type is VHT\n");
11005 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
11006 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
11007
11008 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
11009 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
11010 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
11011 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
11012 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
11013 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
11014 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
11015 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
11016 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
11017 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
11018 }
11019 else
11020 {
11021 printf(" OFDM or CCK \n");
11022 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
11023 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
11024 }
11025
11026 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
11027 if(rinfo[NL80211_RATE_INFO_MCS])
11028 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
11029 }
11030
11031 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
11032 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
11033 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
11034 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
11035
11036 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
11037 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
11038 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
11039
11040 if(stats_info[NL80211_TID_STATS_TX_MSDU])
11041 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
11042
11043 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
11044 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
11045
11046 if(sinfo[NL80211_STA_INFO_TX_FAILED])
11047 ((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]);
11048
11049 return NL_SKIP;
11050}
11051#endif
11052
11053INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
11054{
11055#ifdef HAL_NETLINK_IMPL
11056 Netlink nl;
11057 char if_name[10];
11058 char interface_name[16] = {0};
11059 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
11060 return RETURN_ERR;
11061
11062 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
11063
11064 if (*output_array_size <= 0)
11065 return RETURN_OK;
11066
11067 snprintf(if_name, sizeof(if_name), "%s", interface_name);
11068
11069 nl.id = initSock80211(&nl);
11070
11071 if(nl.id < 0) {
11072 fprintf(stderr, "Error initializing netlink \n");
11073 return 0;
11074 }
11075
11076 struct nl_msg* msg = nlmsg_alloc();
11077
11078 if(!msg) {
11079 fprintf(stderr, "Failed to allocate netlink message.\n");
11080 nlfree(&nl);
11081 return 0;
11082 }
11083
11084 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080011085 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080011086 NL_AUTO_SEQ,
11087 nl.id,
11088 0,
11089 0,
11090 NL80211_CMD_GET_STATION,
11091 0);
11092
11093 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
11094 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
11095 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080011096 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080011097 nl_recvmsgs(nl.socket, nl.cb);
11098 nlmsg_free(msg);
11099 nlfree(&nl);
11100 return RETURN_OK;
11101#else
11102 //TODO Implement me
11103 return RETURN_OK;
11104#endif
11105}
11106
11107INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
11108{
11109 // TODO Implement me!
11110 char buf[MAX_BUF_SIZE] = {0};
11111 char config_file[MAX_BUF_SIZE] = {0};
11112
11113 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
11114 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
11115 *activate = (strncmp("1",buf,1) == 0);
11116
11117 return RETURN_OK;
11118}
11119
11120INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
11121{
11122 char config_file[MAX_BUF_SIZE] = {0};
11123 struct params list;
11124
11125 list.name = "rrm_neighbor_report";
11126 list.value = activate?"1":"0";
11127 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11128 wifi_hostapdWrite(config_file, &list, 1);
11129
11130 return RETURN_OK;
11131}
11132
11133INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
11134{
11135 char buf[32] = {0};
11136 char config_file[MAX_BUF_SIZE] = {0};
11137
11138 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11139 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
11140 *activate = (strncmp("1",buf,1) == 0);
11141
11142 return RETURN_OK;
11143}
11144#undef HAL_NETLINK_IMPL
11145#ifdef HAL_NETLINK_IMPL
11146static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
11147 struct nlattr *tb[NL80211_ATTR_MAX + 1];
11148 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11149 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
11150 char dev[20];
11151 int freq =0 ;
11152 static int i=0;
11153
11154 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
11155
11156 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
11157 };
11158
11159 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
11160
11161 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
11162
11163 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
11164 fprintf(stderr, "survey data missing!\n");
11165 return NL_SKIP;
11166 }
11167
11168 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
11169 {
11170 fprintf(stderr, "failed to parse nested attributes!\n");
11171 return NL_SKIP;
11172 }
11173
11174
11175 if(out[0].array_size == 1 )
11176 {
11177 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
11178 {
11179 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
11180 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
11181 out[0].ch_number = ieee80211_frequency_to_channel(freq);
11182
11183 if (sinfo[NL80211_SURVEY_INFO_NOISE])
11184 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
11185 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
11186 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
11187 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
11188 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
11189 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
11190 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
11191 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
11192 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
11193 if (sinfo[NL80211_SURVEY_INFO_TIME])
11194 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
11195 return NL_STOP;
11196 }
11197 }
11198 else
11199 {
11200 if ( i <= out[0].array_size )
11201 {
11202 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
11203 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
11204 out[i].ch_number = ieee80211_frequency_to_channel(freq);
11205
11206 if (sinfo[NL80211_SURVEY_INFO_NOISE])
11207 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
11208 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
11209 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
11210 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
11211 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
11212 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
11213 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
11214 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
11215 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
11216 if (sinfo[NL80211_SURVEY_INFO_TIME])
11217 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
11218 }
11219 }
11220
11221 i++;
11222 return NL_SKIP;
11223}
11224#endif
11225
11226static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
11227{
11228 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
11229 FILE *fp;
11230
11231 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
11232 {
11233 printf("Creating Frequency-Channel Map\n");
11234 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
11235 }
11236 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
11237 if((fp = popen(command, "r")))
11238 {
11239 fgets(output, sizeof(output), fp);
11240 *freqMHz = atoi(output);
11241 pclose(fp);
11242 }
11243
11244 return 0;
11245}
11246
11247static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
11248{
11249 int freqMHz = -1;
11250 char cmd[MAX_CMD_SIZE] = {'\0'};
11251 char interface_name[16] = {0};
11252
11253 ieee80211_channel_to_frequency(channel, &freqMHz);
11254 if (freqMHz == -1) {
11255 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
11256 return -1;
11257 }
11258
11259 wifi_GetInterfaceName(radioIndex, interface_name);
11260 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
11261 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
11262 radioIndex, freqMHz);
11263 return -1;
11264 }
11265
11266 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
11267 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
11268 return -1;
11269 }
11270
11271 return 0;
11272}
11273
11274static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
11275{
11276 const char *ptr = buf;
11277 char *key = NULL;
11278 char *val = NULL;
11279 char line[256] = { '\0' };
11280
11281 while (ptr = get_line_from_str_buf(ptr, line)) {
11282 if (strstr(line, "Frequency")) continue;
11283
11284 key = strtok(line, ":");
11285 val = strtok(NULL, " ");
11286 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
11287
11288 if (!strcmp(key, "noise")) {
11289 sscanf(val, "%d", &stats->ch_noise);
11290 if (stats->ch_noise == 0) {
11291 // Workaround for missing noise information.
11292 // Assume -95 for 2.4G and -103 for 5G
11293 if (radioIndex == 0) stats->ch_noise = -95;
11294 if (radioIndex == 1) stats->ch_noise = -103;
11295 }
11296 }
11297 else if (!strcmp(key, "channel active time")) {
11298 sscanf(val, "%llu", &stats->ch_utilization_total);
11299 }
11300 else if (!strcmp(key, "channel busy time")) {
11301 sscanf(val, "%llu", &stats->ch_utilization_busy);
11302 }
11303 else if (!strcmp(key, "channel receive time")) {
11304 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
11305 }
11306 else if (!strcmp(key, "channel transmit time")) {
11307 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
11308 }
11309 };
11310
11311 return 0;
11312}
11313
11314INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
11315{
11316 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11317#ifdef HAL_NETLINK_IMPL
11318 Netlink nl;
11319 wifi_channelStats_t_loc local[array_size];
11320 char if_name[32];
11321
11322 local[0].array_size = array_size;
11323
11324 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
11325 return RETURN_ERR;
11326
11327 nl.id = initSock80211(&nl);
11328
11329 if (nl.id < 0) {
11330 fprintf(stderr, "Error initializing netlink \n");
11331 return -1;
11332 }
11333
11334 struct nl_msg* msg = nlmsg_alloc();
11335
11336 if (!msg) {
11337 fprintf(stderr, "Failed to allocate netlink message.\n");
11338 nlfree(&nl);
11339 return -2;
11340 }
11341
11342 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080011343 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080011344 NL_AUTO_SEQ,
11345 nl.id,
11346 0,
11347 NLM_F_DUMP,
11348 NL80211_CMD_GET_SURVEY,
11349 0);
11350
11351 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +080011352 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080011353 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
11354 nl_recvmsgs(nl.socket, nl.cb);
11355 nlmsg_free(msg);
11356 nlfree(&nl);
11357 //Copying the Values
11358 for(int i=0;i<array_size;i++)
11359 {
11360 input_output_channelStats_array[i].ch_number = local[i].ch_number;
11361 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
11362 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
11363 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
11364 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
11365 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
11366 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
11367 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
11368 }
11369#else
11370 ULONG channel = 0;
11371 int i;
11372 int number_of_channels = array_size;
11373 char buf[512];
11374 INT ret;
11375 wifi_channelStats_t tmp_stats;
11376
11377 if (number_of_channels == 0) {
11378 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
11379 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
11380 return RETURN_ERR;
11381 }
11382 number_of_channels = 1;
11383 input_output_channelStats_array[0].ch_number = channel;
11384 }
11385
11386 for (i = 0; i < number_of_channels; i++) {
11387
11388 input_output_channelStats_array[i].ch_noise = 0;
11389 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
11390 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
11391 input_output_channelStats_array[i].ch_utilization_busy = 0;
11392 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
11393 input_output_channelStats_array[i].ch_utilization_total = 0;
11394
11395 memset(buf, 0, sizeof(buf));
11396 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
11397 return RETURN_ERR;
11398 }
11399 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
11400 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
11401 return RETURN_ERR;
11402 }
11403
11404 // XXX: fake missing 'self' counter which is not available in iw survey output
11405 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
11406 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
11407
11408 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
11409 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
11410 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
11411 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
11412 input_output_channelStats_array[i].ch_utilization_total *= 1000;
11413
11414 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",
11415 __func__,
11416 input_output_channelStats_array[i].ch_number,
11417 input_output_channelStats_array[i].ch_noise,
11418 input_output_channelStats_array[i].ch_utilization_total,
11419 input_output_channelStats_array[i].ch_utilization_busy,
11420 input_output_channelStats_array[i].ch_utilization_busy_rx,
11421 input_output_channelStats_array[i].ch_utilization_busy_tx,
11422 input_output_channelStats_array[i].ch_utilization_busy_self,
11423 input_output_channelStats_array[i].ch_utilization_busy_ext);
11424 }
11425#endif
11426 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11427 return RETURN_OK;
11428}
11429#define HAL_NETLINK_IMPL
11430
11431/* Hostapd events */
11432
11433#ifndef container_of
11434#define offset_of(st, m) ((size_t)&(((st *)0)->m))
11435#define container_of(ptr, type, member) \
11436 ((type *)((char *)ptr - offset_of(type, member)))
11437#endif /* container_of */
11438
11439struct ctrl {
11440 char sockpath[128];
11441 char sockdir[128];
11442 char bss[IFNAMSIZ];
11443 char reply[4096];
11444 int ssid_index;
11445 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
11446 void (*overrun)(struct ctrl *ctrl);
11447 struct wpa_ctrl *wpa;
11448 unsigned int ovfl;
11449 size_t reply_len;
11450 int initialized;
11451 ev_timer retry;
11452 ev_timer watchdog;
11453 ev_stat stat;
11454 ev_io io;
11455};
11456static wifi_newApAssociatedDevice_callback clients_connect_cb;
11457static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
11458static struct ctrl wpa_ctrl[MAX_APS];
11459static int initialized;
11460
11461static unsigned int ctrl_get_drops(struct ctrl *ctrl)
11462{
11463 char cbuf[256] = {};
11464 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
11465 struct cmsghdr *cmsg;
11466 unsigned int ovfl = ctrl->ovfl;
11467 unsigned int drop;
11468
11469 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
11470 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
11471 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
11472 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
11473
11474 drop = ovfl - ctrl->ovfl;
11475 ctrl->ovfl = ovfl;
11476
11477 return drop;
11478}
11479
11480static void ctrl_close(struct ctrl *ctrl)
11481{
11482 if (ctrl->io.cb)
11483 ev_io_stop(EV_DEFAULT_ &ctrl->io);
11484 if (ctrl->retry.cb)
11485 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11486 if (!ctrl->wpa)
11487 return;
11488
11489 wpa_ctrl_detach(ctrl->wpa);
11490 wpa_ctrl_close(ctrl->wpa);
11491 ctrl->wpa = NULL;
11492 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
11493}
11494
11495static void ctrl_process(struct ctrl *ctrl)
11496{
11497 const char *str;
11498 int drops;
11499 int level;
11500 int err;
11501
11502 /* Example events:
11503 *
11504 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
11505 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
11506 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
11507 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
11508 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
11509 */
11510 if (!(str = index(ctrl->reply, '>')))
11511 return;
11512 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
11513 return;
11514
11515 str++;
11516
11517 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
11518 if (!(str = index(ctrl->reply, ' ')))
11519 return;
11520 wifi_associated_dev_t sta;
11521 memset(&sta, 0, sizeof(sta));
11522
11523 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11524 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
11525 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
11526
11527 sta.cli_Active=true;
11528
11529 (clients_connect_cb)(ctrl->ssid_index, &sta);
11530 goto handled;
11531 }
11532
11533 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
11534 if (!(str = index(ctrl->reply, ' ')))
11535 return;
11536
11537 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
11538 goto handled;
11539 }
11540
11541 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
11542 printf("CTRL_WPA: handle TERMINATING event\n");
11543 goto retry;
11544 }
11545
11546 if (strncmp("AP-DISABLED", str, 11) == 0) {
11547 printf("CTRL_WPA: handle AP-DISABLED\n");
11548 goto retry;
11549 }
11550
11551 printf("Event not supported!!\n");
11552
11553handled:
11554
11555 if ((drops = ctrl_get_drops(ctrl))) {
11556 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
11557 if (ctrl->overrun)
11558 ctrl->overrun(ctrl);
11559 }
11560
11561 return;
11562
11563retry:
11564 printf("WPA_CTRL: closing\n");
11565 ctrl_close(ctrl);
11566 printf("WPA_CTRL: retrying from ctrl prcoess\n");
11567 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
11568}
11569
11570static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
11571{
11572 struct ctrl *ctrl = container_of(io, struct ctrl, io);
11573 int err;
11574
11575 memset(ctrl->reply, 0, sizeof(ctrl->reply));
11576 ctrl->reply_len = sizeof(ctrl->reply) - 1;
11577 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
11578 ctrl->reply[ctrl->reply_len] = 0;
11579 if (err < 0) {
11580 if (errno == EAGAIN || errno == EWOULDBLOCK)
11581 return;
11582 ctrl_close(ctrl);
11583 ev_timer_again(EV_A_ &ctrl->retry);
11584 return;
11585 }
11586
11587 ctrl_process(ctrl);
11588}
11589
11590static int ctrl_open(struct ctrl *ctrl)
11591{
11592 int fd;
11593
11594 if (ctrl->wpa)
11595 return 0;
11596
11597 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
11598 if (!ctrl->wpa)
11599 goto err;
11600
11601 if (wpa_ctrl_attach(ctrl->wpa) < 0)
11602 goto err_close;
11603
11604 fd = wpa_ctrl_get_fd(ctrl->wpa);
11605 if (fd < 0)
11606 goto err_detach;
11607
11608 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
11609 goto err_detach;
11610
11611 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
11612 ev_io_start(EV_DEFAULT_ &ctrl->io);
11613
11614 return 0;
11615
11616err_detach:
11617 wpa_ctrl_detach(ctrl->wpa);
11618err_close:
11619 wpa_ctrl_close(ctrl->wpa);
11620err:
11621 ctrl->wpa = NULL;
11622 return -1;
11623}
11624
11625static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
11626{
11627 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
11628
11629 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
11630 ctrl_open(ctrl);
11631}
11632
11633static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
11634{
11635 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
11636
11637 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
11638 if (ctrl_open(ctrl) == 0) {
11639 printf("WPA_CTRL: retry successful\n");
11640 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11641 }
11642}
11643
11644int ctrl_enable(struct ctrl *ctrl)
11645{
11646 if (ctrl->wpa)
11647 return 0;
11648
11649 if (!ctrl->stat.cb) {
11650 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
11651 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
11652 }
11653
11654 if (!ctrl->retry.cb) {
11655 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
11656 }
11657
11658 return ctrl_open(ctrl);
11659}
11660
11661static void
11662ctrl_msg_cb(char *buf, size_t len)
11663{
11664 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
11665
11666 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
11667 ctrl_process(ctrl);
11668}
11669
11670static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
11671{
11672 int err;
11673
11674 if (!ctrl->wpa)
11675 return -1;
11676 if (*reply_len < 2)
11677 return -1;
11678
11679 (*reply_len)--;
11680 ctrl->reply_len = sizeof(ctrl->reply);
11681 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
11682 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
11683 if (err < 0)
11684 return err;
11685
11686 if (ctrl->reply_len > *reply_len)
11687 ctrl->reply_len = *reply_len;
11688
11689 *reply_len = ctrl->reply_len;
11690 memcpy(reply, ctrl->reply, *reply_len);
11691 reply[*reply_len - 1] = 0;
11692 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11693 return 0;
11694}
11695
11696static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11697{
11698 const char *pong = "PONG";
11699 const char *ping = "PING";
11700 char reply[1024];
11701 size_t len = sizeof(reply);
11702 int err;
11703 ULONG s, snum;
11704 INT ret;
11705 BOOL status;
11706
11707 printf("WPA_CTRL: watchdog cb\n");
11708
11709 ret = wifi_getSSIDNumberOfEntries(&snum);
11710 if (ret != RETURN_OK) {
11711 printf("%s: failed to get SSID count", __func__);
11712 return;
11713 }
11714
11715 if (snum > MAX_APS) {
11716 printf("more ssid than supported! %lu\n", snum);
11717 return;
11718 }
11719
11720 for (s = 0; s < snum; s++) {
11721 if (wifi_getApEnable(s, &status) != RETURN_OK) {
11722 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
11723 continue;
11724 }
11725 if (status == false) continue;
11726
11727 memset(reply, 0, sizeof(reply));
11728 len = sizeof(reply);
11729 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
11730 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
11731 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11732 continue;
11733
11734 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11735 ctrl_close(&wpa_ctrl[s]);
11736 printf("WPA_CTRL: ev_timer_again %lu\n", s);
11737 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11738 }
11739}
11740
11741static int init_wpa()
11742{
11743 int ret = 0, i = 0;
11744 ULONG s, snum;
11745
11746 ret = wifi_getSSIDNumberOfEntries(&snum);
11747 if (ret != RETURN_OK) {
11748 printf("%s: failed to get SSID count", __func__);
11749 return RETURN_ERR;
11750 }
11751
11752 if (snum > MAX_APS) {
11753 printf("more ssid than supported! %lu\n", snum);
11754 return RETURN_ERR;
11755 }
11756
11757 for (s = 0; s < snum; s++) {
11758 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11759 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11760 wpa_ctrl[s].ssid_index = s;
11761 ctrl_enable(&wpa_ctrl[s]);
11762 }
11763
11764 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11765 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11766
11767 initialized = 1;
11768 printf("WPA_CTRL: initialized\n");
11769
11770 return RETURN_OK;
11771}
11772
11773void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11774{
11775 clients_connect_cb = callback_proc;
11776 if (!initialized)
11777 init_wpa();
11778}
11779
11780void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11781{
11782 clients_disconnect_cb = callback_proc;
11783 if (!initialized)
11784 init_wpa();
11785}
11786
11787INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11788{
11789 // TODO Implement me!
11790 return RETURN_ERR;
11791}
11792
11793INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11794{
11795 // TODO Implement me!
11796 return RETURN_ERR;
11797}
11798
11799INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11800{
11801 int i;
developerd1824452023-05-18 12:30:04 +080011802 int phyId = -1;
11803 char cmd[256] = {0};
11804 char channel_numbers_buf[256] = {0};
11805 char dfs_state_buf[256] = {0};
11806 char line[256] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011807 const char *ptr;
developerd1824452023-05-18 12:30:04 +080011808 BOOL dfs_enable = false;
developer72fb0bb2023-01-11 09:46:29 +080011809
developerd1824452023-05-18 12:30:04 +080011810 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer72fb0bb2023-01-11 09:46:29 +080011811
developerd1824452023-05-18 12:30:04 +080011812 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
11813 phyId = radio_index_to_phy(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080011814
developerd1824452023-05-18 12:30:04 +080011815 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 +080011816
developerd1824452023-05-18 12:30:04 +080011817 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11818 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11819 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011820 }
11821
developerd1824452023-05-18 12:30:04 +080011822 ptr = channel_numbers_buf;
11823 i = 0;
11824 while (ptr = get_line_from_str_buf(ptr, line)) {
11825 if (i >= outputMapSize) {
11826 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11827 return RETURN_ERR;
11828 }
11829 sscanf(line, "%d", &outputMap[i].ch_number);
11830
11831 memset(cmd, 0, sizeof(cmd));
11832 // Below command should fetch string for DFS state (usable, available or unavailable)
11833 // Example line: "DFS state: usable (for 78930 sec)"
11834 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) {
11835 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer72fb0bb2023-01-11 09:46:29 +080011836 return RETURN_ERR;
11837 }
11838
developerd1824452023-05-18 12:30:04 +080011839 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11840 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer72fb0bb2023-01-11 09:46:29 +080011841 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11842 return RETURN_ERR;
11843 }
11844
developerd1824452023-05-18 12:30:04 +080011845 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer59fda4f2023-05-16 15:47:38 +080011846
developerd1824452023-05-18 12:30:04 +080011847 if (!strcmp(dfs_state_buf, "usable")) {
11848 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11849 } else if (!strcmp(dfs_state_buf, "available")) {
11850 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11851 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11852 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11853 } else {
11854 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer72fb0bb2023-01-11 09:46:29 +080011855 }
developerd1824452023-05-18 12:30:04 +080011856 i++;
developer59fda4f2023-05-16 15:47:38 +080011857 }
developer40ba1762023-05-13 11:03:49 +080011858
developerd1824452023-05-18 12:30:04 +080011859 return RETURN_OK;
11860
developer72fb0bb2023-01-11 09:46:29 +080011861 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11862 return RETURN_ERR;
11863}
11864
11865INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11866{
11867 // TODO Implement me!
11868 return RETURN_ERR;
11869}
11870
11871INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11872{
11873 return RETURN_OK;
11874}
11875
11876INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11877{
11878 // TODO Implement me!
11879 return RETURN_ERR;
11880}
11881
11882INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11883{
11884 // TODO API refrence Implementaion is present on RPI hal
11885 return RETURN_ERR;
11886}
11887
11888INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11889{
developera1255e42023-05-13 17:45:02 +080011890/*
developer72fb0bb2023-01-11 09:46:29 +080011891 char interface_name[16] = {0};
11892 char cmd[128]={'\0'};
11893 char buf[128]={'\0'};
11894 char *support;
11895 int maximum_tx = 0, current_tx = 0;
developera1255e42023-05-13 17:45:02 +080011896*/ ULONG pwr_percentage = 0;
developer72fb0bb2023-01-11 09:46:29 +080011897
11898 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11899 if(txpwr_pcntg == NULL)
11900 return RETURN_ERR;
11901
developera1255e42023-05-13 17:45:02 +080011902 wifi_getRadioTransmitPower(apIndex, &pwr_percentage);
11903 *txpwr_pcntg = pwr_percentage;
11904/* if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +080011905 return RETURN_ERR;
11906
11907 // Get the maximum tx power of the device
11908 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
11909 _syscmd(cmd, buf, sizeof(buf));
11910 maximum_tx = strtol(buf, NULL, 10);
11911
11912 // Get the current tx power
11913 memset(cmd, 0, sizeof(cmd));
11914 memset(buf, 0, sizeof(buf));
11915 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
11916 _syscmd(cmd, buf, sizeof(buf));
11917 current_tx = strtol(buf, NULL, 10);
11918
11919 // Get the power supported list and find the current power percentage in supported list
11920 memset(buf, 0, sizeof(buf));
11921 wifi_getRadioTransmitPowerSupported(apIndex, buf);
11922 support = strtok(buf, ",");
11923 while(true)
11924 {
11925 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
11926 *txpwr_pcntg = 100;
11927 wifi_dbg_printf("current power is not in supported list\n");
11928 return RETURN_OK;
11929 }
11930 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
11931 if (tmp == current_tx) {
11932 *txpwr_pcntg = strtol(support, NULL, 10);
11933 break;
11934 }
11935 support = strtok(NULL, ",");
11936 }
developera1255e42023-05-13 17:45:02 +080011937*/
developer72fb0bb2023-01-11 09:46:29 +080011938 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11939 return RETURN_OK;
11940}
11941
11942INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11943{
11944 // TODO precac feature.
developerd1824452023-05-18 12:30:04 +080011945 struct params params[2] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011946 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080011947 BOOL dfs_enable = false;
11948 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080011949
11950 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerd1824452023-05-18 12:30:04 +080011951 band = wifi_index_to_band(radioIndex);
11952 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer72fb0bb2023-01-11 09:46:29 +080011953
developerd1824452023-05-18 12:30:04 +080011954 if (dfs_enable == false) {
11955 WIFI_ENTRY_EXIT_DEBUG("Please enable DFS firstly!: %s\n", __func__);
11956 return RETURN_ERR;
11957 }
11958 params[0].name = "DfsZeroWaitDefault";
11959 params[0].value = enable?"1":"0";
11960 params[1].name = "DfsDedicatedZeroWait";
11961 params[1].value = enable?"1":"0";
11962 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
11963 wifi_datfileWrite(config_file, params, 2);
developer72fb0bb2023-01-11 09:46:29 +080011964 /* TODO precac feature */
11965
11966 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11967 return RETURN_OK;
11968}
11969
11970INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11971{
11972 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080011973 char buf1[32] = {0};
11974 char buf2[32] = {0};
11975 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080011976
11977 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11978 if (NULL == enable || NULL == precac)
11979 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +080011980 band = wifi_index_to_band(radioIndex);
11981 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
11982 wifi_datfileRead(config_file, "DfsZeroWaitDefault", buf1, sizeof(buf1));
11983 wifi_datfileRead(config_file, "DfsDedicatedZeroWait", buf2, sizeof(buf2));
11984 if ((strncmp(buf1, "1", 1) == 0) && (strncmp(buf2, "1", 1) == 0))
developer72fb0bb2023-01-11 09:46:29 +080011985 *enable = true;
11986 else
11987 *enable = false;
11988
11989 /* TODO precac feature */
11990
11991 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11992 return RETURN_OK;
11993}
11994
11995INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11996{
11997 *supported = TRUE;
11998 return RETURN_OK;
11999}
12000
12001INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
12002{
developera1255e42023-05-13 17:45:02 +080012003 UCHAR dat_file[64] = {0};
12004 wifi_band band = band_invalid;
12005 char cmd[128] = {0};
12006 char buf[256] = {0};
12007 char ofdmabuf[32] = {'\0'};
12008 char mimobuf[32] = {'\0'};
12009 char new_ofdmabuf[32] = {'\0'};
12010 char new_mimobuf[32] = {'\0'};
12011 struct params params[2];
12012 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
12013 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
12014 UCHAR bss_cnt = 0;
12015 UCHAR val_cnt = 0;
12016 char *token = NULL;
developer72fb0bb2023-01-11 09:46:29 +080012017
developera1255e42023-05-13 17:45:02 +080012018 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12019 if ((mu_type < WIFI_DL_MU_TYPE_NONE)
12020 || (mu_type > WIFI_DL_MU_TYPE_OFDMA_MIMO)) {
12021 printf("%s:mu_type input Error", __func__);
12022 return RETURN_ERR;
12023 }
12024 band = wifi_index_to_band(radio_index);
12025 if (band == band_invalid) {
12026 printf("%s:Band Error\n", __func__);
12027 return RETURN_ERR;
12028 }
12029 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12030 /*get current value in dat file*/
12031 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
12032 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
12033 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
12034 get_bssnum_byindex(radio_index, &bss_cnt);
12035 val_cnt = 2*bss_cnt - 1;
12036 WIFI_ENTRY_EXIT_DEBUG("bss number: %d\n", bss_cnt);
12037 if ((val_cnt >= sizeof(new_ofdmabuf))
12038 || (val_cnt >= sizeof(new_mimobuf))) {
12039 printf("%s:bss cnt Error", __func__, bss_cnt);
12040 return RETURN_ERR;
12041 }
12042 /*translate set value*/
12043 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
12044 strncpy(new_ofdmabuf, str_zero, val_cnt);
12045 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080012046 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
developera1255e42023-05-13 17:45:02 +080012047 strncpy(new_ofdmabuf, str_one, val_cnt);
12048 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080012049 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
developera1255e42023-05-13 17:45:02 +080012050 strncpy(new_ofdmabuf, str_zero, val_cnt);
12051 strncpy(new_mimobuf, str_one, val_cnt);
12052 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO) {
12053 strncpy(new_ofdmabuf, str_one, val_cnt);
12054 strncpy(new_mimobuf, str_one, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080012055 }
developera1255e42023-05-13 17:45:02 +080012056 WIFI_ENTRY_EXIT_DEBUG("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
12057 /*same value, not operation*/
12058 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
12059 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
12060 printf("%s:Reduntant value\n", __func__);
12061 return RETURN_OK;
12062 }
12063 /*modify dat file to new file*/
12064 params[0].name="MuOfdmaDlEnable";
12065 params[0].value=new_ofdmabuf;
12066 params[1].name="MuMimoDlEnable";
12067 params[1].value=new_mimobuf;
12068 wifi_datfileWrite(dat_file, params, 2);
12069 /*hostapd control restarp ap to take effect on these new value*/
12070 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080012071 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12072 return RETURN_OK;
12073}
12074
12075INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
12076{
12077 struct params params={0};
12078 char config_file[64] = {0};
12079 char buf[64] = {0};
12080 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080012081 UCHAR dat_file[64] = {0};
12082 wifi_band band = band_invalid;
12083 char ofdmabuf[32] = {'\0'};
12084 char mimobuf[32] = {'\0'};
12085 char *token = NULL;
12086 UCHAR ofdma = 0;
12087 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080012088
12089 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12090
12091 if (mu_type == NULL)
12092 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080012093 band = wifi_index_to_band(radio_index);
12094 if (band == band_invalid) {
12095 printf("%s:Band Error\n", __func__);
12096 return RETURN_ERR;
12097 }
12098 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12099 /*get current value in dat file*/
12100 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
12101 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080012102
developera1255e42023-05-13 17:45:02 +080012103 token = strtok(ofdmabuf, ";");
12104 ofdma = strtol(token, NULL, 10);
12105 token = strtok(mimobuf, ";");
12106 mimo = strtol(token, NULL, 10);
12107 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d,mimo=%d\n", __func__, ofdma, mimo);
12108 if ((ofdma == 1) && (mimo == 1))
12109 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
12110 else if ((ofdma == 0) && (mimo == 1))
12111 *mu_type = WIFI_DL_MU_TYPE_MIMO;
12112 else if ((ofdma == 1) && (mimo == 0))
12113 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
12114 else
12115 *mu_type = WIFI_DL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080012116 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12117 return RETURN_OK;
12118}
12119
12120INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
12121{
12122 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
developera1255e42023-05-13 17:45:02 +080012123 UCHAR dat_file[64] = {0};
12124 wifi_band band = band_invalid;
12125 char cmd[128] = {0};
12126 char buf[256] = {0};
12127 char ofdmabuf[32] = {'\0'};
12128 char mimobuf[32] = {'\0'};
12129 char new_ofdmabuf[32] = {'\0'};
12130 char new_mimobuf[32] = {'\0'};
12131 struct params params[2];
12132 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
12133 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
12134 UCHAR bss_cnt = 0;
12135 UCHAR val_cnt = 0;
developer72fb0bb2023-01-11 09:46:29 +080012136
developera1255e42023-05-13 17:45:02 +080012137 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12138 band = wifi_index_to_band(radio_index);
12139 if (band == band_invalid) {
12140 printf("%s:Band Error\n", __func__);
12141 return RETURN_ERR;
12142 }
12143 if ((mu_type < WIFI_UL_MU_TYPE_NONE)
12144 || (mu_type > WIFI_UL_MU_TYPE_OFDMA)) {
12145 printf("%s:mu_type input Error\n", __func__);
12146 return RETURN_ERR;
12147 }
12148 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12149 /*get current value in dat file*/
12150 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
12151 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
12152 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
12153 get_bssnum_byindex(radio_index, &bss_cnt);
12154 val_cnt = 2*bss_cnt - 1;
12155 printf("bssNumber:%d,ValCnt:%d\n", bss_cnt, val_cnt);
12156 if ((val_cnt >= sizeof(new_ofdmabuf))
12157 || (val_cnt >= sizeof(new_mimobuf))) {
12158 printf("%s:bss cnt Error\n", __func__, val_cnt);
12159 return RETURN_ERR;
12160 }
12161 /*translate set value*/
12162 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
12163 strncpy(new_ofdmabuf, str_zero, val_cnt);
12164 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080012165 }
developera1255e42023-05-13 17:45:02 +080012166 if (mu_type == WIFI_UL_MU_TYPE_OFDMA) {
12167 strncpy(new_ofdmabuf, str_one, val_cnt);
12168 strncpy(new_mimobuf, str_zero, val_cnt);
12169 }
12170 printf("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
12171 /*same value, not operation*/
12172 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
12173 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
12174 printf("%s:Reduntant value\n", __func__);
12175 return RETURN_OK;
12176 }
12177 /*modify dat file to new file*/
12178 params[0].name="MuOfdmaUlEnable";
12179 params[0].value=new_ofdmabuf;
12180 params[1].name="MuMimoUlEnable";
12181 params[1].value=new_mimobuf;
12182 wifi_datfileWrite(dat_file, params, 2);
12183 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080012184 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12185 return RETURN_OK;
12186}
12187
12188INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
12189{
12190 struct params params={0};
12191 char config_file[64] = {0};
12192 char buf[64] = {0};
12193 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080012194 UCHAR dat_file[64] = {0};
12195 wifi_band band = band_invalid;
12196 char ofdmabuf[32] = {'\0'};
12197 char mimobuf[32] = {'\0'};
12198 char *token = NULL;
12199 UCHAR ofdma = 0;
12200 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080012201
12202 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12203
12204 if (mu_type == NULL)
12205 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080012206 band = wifi_index_to_band(radio_index);
12207 if (band == band_invalid) {
12208 printf("%s:Band Error", __func__);
12209 return RETURN_ERR;
12210 }
12211 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12212 /*get current value in dat file*/
12213 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
12214 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080012215
developera1255e42023-05-13 17:45:02 +080012216 token = strtok(ofdmabuf, ";");
12217 ofdma = strtol(token, NULL, 10);
12218 token = strtok(mimobuf, ";");
12219 mimo = strtol(token, NULL, 10);
12220 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d, mimo=%d\n", __func__, ofdma, mimo);
12221 if ((ofdma == 1) && (mimo == 0))
12222 *mu_type = WIFI_UL_MU_TYPE_OFDMA;
12223 else
12224 *mu_type = WIFI_UL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080012225 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12226 return RETURN_OK;
12227}
12228
12229
12230INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
12231{
12232 char cmd[128] = {0};
12233 char buf[256] = {0};
12234 char config_file[64] = {0};
12235 char GI[8] = {0};
12236 int mode_map = 0;
12237 FILE *f = NULL;
12238 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080012239 char dat_file[64] = {'\0'};
12240 struct params params[3];
developer72fb0bb2023-01-11 09:46:29 +080012241
12242 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12243
12244 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
12245 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
12246 return RETURN_ERR;
12247 }
developera1255e42023-05-13 17:45:02 +080012248 /*sanity check*/
12249 if (((guard_interval == wifi_guard_interval_1600)
12250 || (guard_interval == wifi_guard_interval_3200))
12251 && (mode_map & (WIFI_MODE_BE | WIFI_MODE_AX) == 0)) {
12252 wifi_dbg_printf("%s: N/AC Mode not support 1600/3200ns GI\n", __func__);
12253 return RETURN_ERR;
12254 }
developer72fb0bb2023-01-11 09:46:29 +080012255 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
12256 band = wifi_index_to_band(radio_index);
12257
12258 // Hostapd are not supported HE mode GI 1600, 3200 ns.
12259 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
12260 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
12261 _syscmd(cmd, buf, sizeof(buf));
12262 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
12263 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
12264 if (strstr(buf, "[SHORT-GI-") == NULL) {
12265 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
12266 _syscmd(cmd, buf, sizeof(buf));
12267 }
12268 if (band == band_5) {
12269 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
12270 if (strstr(buf, "[SHORT-GI-") == NULL) {
12271 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
12272 _syscmd(cmd, buf, sizeof(buf));
12273 }
12274 }
12275 }
developera1255e42023-05-13 17:45:02 +080012276 /*wifi_reloadAp(radio_index);
12277 caller "wifi_setRadioOperatingParameters" have done this step.
12278 */
12279 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12280 if (guard_interval == wifi_guard_interval_400) {
12281 params[0].name = "HT_GI";
12282 params[0].value = "1";
12283 params[1].name = "VHT_SGI";
12284 params[1].value = "1";
12285 wifi_datfileWrite(dat_file, params, 2);
developer72fb0bb2023-01-11 09:46:29 +080012286 strcpy(GI, "0.4");
developera1255e42023-05-13 17:45:02 +080012287 } else {
12288 params[0].name = "HT_GI";
12289 params[0].value = "0";
12290 params[1].name = "VHT_SGI";
12291 params[1].value = "0";
12292 /*should enable FIXED_HE_GI_SUPPORT in driver*/
12293 params[2].name = "FgiFltf";
12294 if (guard_interval == wifi_guard_interval_800) {
12295 params[2].value = "800";
12296 strcpy(GI, "0.8");
12297 } else if (guard_interval == wifi_guard_interval_1600) {
12298 params[2].value = "1600";
12299 strcpy(GI, "1.6");
12300 } else if (guard_interval == wifi_guard_interval_3200) {
12301 params[2].value = "3200";
12302 strcpy(GI, "3.2");
12303 } else if (guard_interval == wifi_guard_interval_auto) {
12304 params[2].value = "0";
12305 strcpy(GI, "auto");
12306 }
12307 wifi_datfileWrite(dat_file, params, 3);
12308 }
developer72fb0bb2023-01-11 09:46:29 +080012309 // Record GI for get GI function
12310 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
12311 f = fopen(buf, "w");
12312 if (f == NULL)
12313 return RETURN_ERR;
12314 fprintf(f, "%s", GI);
12315 fclose(f);
12316 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12317 return RETURN_OK;
12318}
12319
12320INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
12321{
12322 char buf[32] = {0};
12323 char cmd[64] = {0};
12324
12325 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12326
12327 if (guard_interval == NULL)
12328 return RETURN_ERR;
12329
developera1255e42023-05-13 17:45:02 +080012330 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer72fb0bb2023-01-11 09:46:29 +080012331 _syscmd(cmd, buf, sizeof(buf));
12332
12333 if (strncmp(buf, "0.4", 3) == 0)
12334 *guard_interval = wifi_guard_interval_400;
12335 else if (strncmp(buf, "0.8", 3) == 0)
12336 *guard_interval = wifi_guard_interval_800;
12337 else if (strncmp(buf, "1.6", 3) == 0)
12338 *guard_interval = wifi_guard_interval_1600;
12339 else if (strncmp(buf, "3.2", 3) == 0)
12340 *guard_interval = wifi_guard_interval_3200;
12341 else
12342 *guard_interval = wifi_guard_interval_auto;
12343
12344 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12345 return RETURN_OK;
12346}
12347
12348INT wifi_setBSSColor(INT radio_index, UCHAR color)
12349{
12350 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12351 struct params params = {0};
12352 char config_file[128] = {0};
12353 char bss_color[4] ={0};
12354
developera1255e42023-05-13 17:45:02 +080012355 if (color < 1 || color > 63) {
12356 wifi_dbg_printf("color value is err:%d.\n", color);
12357 return RETURN_ERR;
12358 }
developer72fb0bb2023-01-11 09:46:29 +080012359 params.name = "he_bss_color";
12360 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
12361 params.value = bss_color;
12362 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
12363 wifi_hostapdWrite(config_file, &params, 1);
developera1255e42023-05-13 17:45:02 +080012364 //wifi_hostapdProcessUpdate(radio_index, &params, 1);
12365 wifi_reloadAp(radio_index);
developer69b61b02023-03-07 17:17:44 +080012366
developer72fb0bb2023-01-11 09:46:29 +080012367 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12368 return RETURN_OK;
12369}
12370
12371INT wifi_getBSSColor(INT radio_index, UCHAR *color)
12372{
12373 char config_file[128] = {0};
12374 char buf[64] = {0};
12375 char temp_output[128] = {'\0'};
12376
12377 wifi_dbg_printf("\nFunc=%s\n", __func__);
12378 if (NULL == color)
12379 return RETURN_ERR;
12380
12381 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
12382 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
12383
12384 if(strlen(buf) > 0) {
12385 snprintf(temp_output, sizeof(temp_output), "%s", buf);
12386 } else {
12387 snprintf(temp_output, sizeof(temp_output), "1"); // default value
12388 }
12389
12390 *color = (UCHAR)strtoul(temp_output, NULL, 10);
12391 wifi_dbg_printf("\noutput_string=%s\n", color);
12392
12393 return RETURN_OK;
12394}
12395
12396/* multi-psk support */
12397INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
12398{
12399 char cmd[256];
12400 char interface_name[16] = {0};
12401
12402 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12403 return RETURN_ERR;
12404
12405 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
12406 interface_name,
12407 mac[0],
12408 mac[1],
12409 mac[2],
12410 mac[3],
12411 mac[4],
12412 mac[5]
12413 );
12414 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
12415 _syscmd(cmd, key->wifi_keyId, 64);
12416
12417
12418 return RETURN_OK;
12419}
12420
12421INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
12422{
12423 char interface_name[16] = {0};
12424 FILE *fd = NULL;
12425 char fname[100];
12426 char cmd[128] = {0};
12427 char out[64] = {0};
12428 wifi_key_multi_psk_t * key = NULL;
12429 if(keysNumber < 0)
12430 return RETURN_ERR;
12431
12432 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
12433 fd = fopen(fname, "w");
12434 if (!fd) {
12435 return RETURN_ERR;
12436 }
12437 key= (wifi_key_multi_psk_t *) keys;
12438 for(int i=0; i<keysNumber; ++i, key++) {
12439 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
12440 }
12441 fclose(fd);
12442
12443 //reload file
12444 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12445 return RETURN_ERR;
12446 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
12447 _syscmd(cmd, out, 64);
12448 return RETURN_OK;
12449}
12450
12451INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
12452{
12453 FILE *fd = NULL;
12454 char fname[100];
12455 char * line = NULL;
12456 char * pos = NULL;
12457 size_t len = 0;
12458 ssize_t read = 0;
12459 INT ret = RETURN_OK;
12460 wifi_key_multi_psk_t *keys_it = NULL;
12461
12462 if (keysNumber < 1) {
12463 return RETURN_ERR;
12464 }
12465
12466 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
12467 fd = fopen(fname, "r");
12468 if (!fd) {
12469 return RETURN_ERR;
12470 }
12471
12472 if (keys == NULL) {
12473 ret = RETURN_ERR;
12474 goto close;
12475 }
12476
12477 keys_it = keys;
12478 while ((read = getline(&line, &len, fd)) != -1) {
12479 //Strip trailing new line if present
12480 if (read > 0 && line[read-1] == '\n') {
12481 line[read-1] = '\0';
12482 }
12483
12484 if(strcmp(line,"keyid=")) {
12485 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
12486 if (!(pos = index(line, ' '))) {
12487 ret = RETURN_ERR;
12488 goto close;
12489 }
12490 pos++;
12491 //Here should be 00:00:00:00:00:00
12492 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
12493 printf("Not supported MAC: %s\n", pos);
12494 }
12495 if (!(pos = index(pos, ' '))) {
12496 ret = RETURN_ERR;
12497 goto close;
12498 }
12499 pos++;
12500
12501 //The rest is PSK
12502 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
12503 keys_it++;
12504
12505 if(--keysNumber <= 0)
12506 break;
12507 }
12508 }
12509
12510close:
12511 free(line);
12512 fclose(fd);
12513 return ret;
12514}
12515/* end of multi-psk support */
12516
12517INT wifi_setNeighborReports(UINT apIndex,
12518 UINT numNeighborReports,
12519 wifi_NeighborReport_t *neighborReports)
12520{
12521 char cmd[256] = { 0 };
12522 char hex_bssid[13] = { 0 };
12523 char bssid[18] = { 0 };
12524 char nr[256] = { 0 };
12525 char ssid[256];
12526 char hex_ssid[256];
12527 char interface_name[16] = {0};
12528 INT ret;
12529
12530 /*rmeove all neighbors*/
12531 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
12532 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12533 return RETURN_ERR;
12534 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);
12535 system(cmd);
12536
12537 for(unsigned int i = 0; i < numNeighborReports; i++)
12538 {
12539 memset(ssid, 0, sizeof(ssid));
12540 ret = wifi_getSSIDName(apIndex, ssid);
12541 if (ret != RETURN_OK)
12542 return RETURN_ERR;
12543
12544 memset(hex_ssid, 0, sizeof(hex_ssid));
12545 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
12546 sprintf(hex_ssid + k,"%02x", ssid[j]);
12547
12548 snprintf(hex_bssid, sizeof(hex_bssid),
12549 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
12550 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
12551 snprintf(bssid, sizeof(bssid),
12552 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
12553 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
12554
12555 snprintf(nr, sizeof(nr),
12556 "%s" // bssid
12557 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
12558 "%02hhx" // operclass
12559 "%02hhx" // channel
12560 "%02hhx", // phy_mode
12561 hex_bssid,
12562 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
12563 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
12564 neighborReports[i].opClass,
12565 neighborReports[i].channel,
12566 neighborReports[i].phyTable);
12567
12568 snprintf(cmd, sizeof(cmd),
12569 "hostapd_cli set_neighbor "
12570 "%s " // bssid
12571 "ssid=%s " // ssid
12572 "nr=%s " // nr
12573 "-i %s",
12574 bssid,hex_ssid,nr, interface_name);
12575
12576 if (WEXITSTATUS(system(cmd)) != 0)
12577 {
12578 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
12579 }
12580 }
12581
12582 return RETURN_OK;
12583}
12584
12585INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
12586{
12587 return RETURN_OK;
12588}
12589
12590#ifdef _WIFI_HAL_TEST_
12591int main(int argc,char **argv)
12592{
12593 int index;
12594 INT ret=0;
12595 char buf[1024]="";
12596
12597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12598 if(argc<3)
12599 {
12600 if(argc==2)
12601 {
12602 if(!strcmp(argv[1], "init"))
12603 return wifi_init();
12604 if(!strcmp(argv[1], "reset"))
12605 return wifi_reset();
12606 if(!strcmp(argv[1], "wifi_getHalVersion"))
12607 {
12608 char buffer[64];
12609 if(wifi_getHalVersion(buffer)==RETURN_OK)
12610 printf("Version: %s\n", buffer);
12611 else
12612 printf("Error in wifi_getHalVersion\n");
12613 return RETURN_OK;
12614 }
12615 }
12616 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
12617 exit(-1);
12618 }
12619
12620 index = atoi(argv[2]);
12621 if(strstr(argv[1], "wifi_getApName")!=NULL)
12622 {
12623 wifi_getApName(index,buf);
12624 printf("Ap name is %s \n",buf);
12625 return 0;
12626 }
developer0f10c772023-05-16 21:43:39 +080012627 if(strstr(argv[1], "wifi_getRadioMode")!=NULL)
12628 {
12629 int mode = 0;
12630
12631 wifi_getRadioMode(index, buf, &mode);
12632 printf("Ap Radio mode is %s , mode = 0x%x\n", buf, mode);
12633 return 0;
12634 }
developer72fb0bb2023-01-11 09:46:29 +080012635 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
12636 {
12637 BOOL b = FALSE;
12638 BOOL *output_bool = &b;
12639 wifi_getRadioAutoChannelEnable(index,output_bool);
12640 printf("Channel enabled = %d \n",b);
12641 return 0;
12642 }
12643 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
12644 {
12645 wifi_getApWpaEncryptionMode(index,buf);
12646 printf("encryption enabled = %s\n",buf);
12647 return 0;
12648 }
12649 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
12650 {
12651 BOOL b = FALSE;
12652 BOOL *output_bool = &b;
12653 wifi_getApSsidAdvertisementEnable(index,output_bool);
12654 printf("advertisment enabled = %d\n",b);
12655 return 0;
12656 }
12657 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
12658 {
12659 if(argc <= 3 )
12660 {
12661 printf("Insufficient arguments \n");
12662 exit(-1);
12663 }
12664
12665 char sta[20] = {'\0'};
12666 ULLONG handle= 0;
12667 strcpy(sta,argv[3]);
12668 mac_address_t st;
12669 mac_addr_aton(st,sta);
12670
12671 wifi_associated_dev_tid_stats_t tid_stats;
12672 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
12673 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
12674 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);
12675 }
12676
12677 if(strstr(argv[1], "getApEnable")!=NULL) {
12678 BOOL enable;
12679 ret=wifi_getApEnable(index, &enable);
12680 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12681 }
12682 else if(strstr(argv[1], "setApEnable")!=NULL) {
12683 BOOL enable = atoi(argv[3]);
12684 ret=wifi_setApEnable(index, enable);
12685 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12686 }
12687 else if(strstr(argv[1], "getApStatus")!=NULL) {
developer69b61b02023-03-07 17:17:44 +080012688 char status[64];
developer72fb0bb2023-01-11 09:46:29 +080012689 ret=wifi_getApStatus(index, status);
12690 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
12691 }
12692 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
12693 {
12694 wifi_getSSIDNameStatus(index,buf);
12695 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
12696 return 0;
12697 }
12698 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
12699 wifi_ssidTrafficStats2_t stats={0};
12700 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
12701 printf("%s %d: returns %d\n", argv[1], index, ret);
12702 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
12703 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
12704 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
12705 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
12706 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
12707 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
12708 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
12709 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
12710 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
12711 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
12712 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
12713 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
12714 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
12715 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
12716 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
12717 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
12718 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
12719 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
12720 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
12721 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
12722 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
12723 }
12724 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
12725 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
12726 UINT array_size=0;
12727 UINT i=0;
12728 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
12729 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080012730 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080012731 printf(" neighbor %d:\n", i);
12732 printf(" ap_SSID =%s\n", pt->ap_SSID);
12733 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
12734 printf(" ap_Mode =%s\n", pt->ap_Mode);
12735 printf(" ap_Channel =%d\n", pt->ap_Channel);
12736 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
12737 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12738 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
12739 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
12740 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
12741 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
12742 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
12743 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
12744 printf(" ap_Noise =%d\n", pt->ap_Noise);
12745 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
12746 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
12747 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
developer69b61b02023-03-07 17:17:44 +080012748 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
developer72fb0bb2023-01-11 09:46:29 +080012749 }
12750 if(neighbor_ap_array)
12751 free(neighbor_ap_array); //make sure to free the list
12752 }
12753 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
12754 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
12755 UINT array_size=0;
12756 UINT i=0;
12757 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
12758 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080012759 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080012760 printf(" associated_dev %d:\n", i);
12761 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
12762 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
12763 printf(" cli_SNR =%d\n", pt->cli_SNR);
12764 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
12765 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
12766 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
12767 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
12768 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
12769 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
12770 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
12771 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
12772 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
12773 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
12774 }
12775 if(associated_dev_array)
12776 free(associated_dev_array); //make sure to free the list
12777 }
12778
12779 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
12780 {
12781#define MAX_ARRAY_SIZE 64
12782 int i, array_size;
12783 char *p, *ch_str;
12784 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
12785
12786 if(argc != 5)
12787 {
12788 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
12789 exit(-1);
12790 }
12791 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
12792
12793 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
12794 {
12795 strtok_r(ch_str, ",", &p);
12796 input_output_channelStats_array[i].ch_number = atoi(ch_str);
12797 }
12798 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
12799 if(!array_size)
12800 array_size=1;//Need to print current channel statistics
12801 for(i=0; i<array_size; i++)
12802 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
12803 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12804 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12805 input_output_channelStats_array[i].ch_number,\
12806 input_output_channelStats_array[i].ch_noise,\
12807 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12808 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12809 input_output_channelStats_array[i].ch_utilization_busy,\
12810 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12811 input_output_channelStats_array[i].ch_utilization_total);
12812 }
12813
12814 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12815 {
12816 if(argc <= 3 )
12817 {
12818 printf("Insufficient arguments \n");
12819 exit(-1);
12820 }
12821 char mac_addr[20] = {'\0'};
12822 wifi_device_t output_struct;
12823 int dev_index = atoi(argv[3]);
12824
12825 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12826 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12827 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);
12828 }
12829
12830 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12831 {
12832 if (argc <= 3)
12833 {
12834 printf("Insufficient arguments\n");
12835 exit(-1);
12836 }
12837 char args[256];
12838 wifi_NeighborReport_t *neighborReports;
12839
12840 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12841 if (!neighborReports)
12842 {
12843 printf("Failed to allocate memory");
12844 exit(-1);
12845 }
12846
12847 for (int i = 3; i < argc; ++i)
12848 {
12849 char *val;
12850 int j = 0;
12851 memset(args, 0, sizeof(args));
12852 strncpy(args, argv[i], sizeof(args));
12853 val = strtok(args, ";");
12854 while (val != NULL)
12855 {
12856 if (j == 0)
12857 {
12858 mac_addr_aton(neighborReports[i - 3].bssid, val);
12859 } else if (j == 1)
12860 {
12861 neighborReports[i - 3].info = strtol(val, NULL, 16);
12862 } else if (j == 2)
12863 {
12864 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12865 } else if (j == 3)
12866 {
12867 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12868 } else if (j == 4)
12869 {
12870 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12871 } else {
12872 printf("Insufficient arguments]n\n");
12873 exit(-1);
12874 }
12875 val = strtok(NULL, ";");
12876 j++;
12877 }
12878 }
12879
12880 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12881 if (ret != RETURN_OK)
12882 {
12883 printf("wifi_setNeighborReports ret = %d", ret);
12884 exit(-1);
12885 }
12886 }
12887 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12888 {
12889 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12890 printf("%s.\n", buf);
12891 else
12892 printf("Error returned\n");
12893 }
12894 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12895 {
12896 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12897 printf("%s.\n", buf);
12898 else
12899 printf("Error returned\n");
12900 }
12901 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12902 {
12903 if (argc <= 2)
12904 {
12905 printf("Insufficient arguments\n");
12906 exit(-1);
12907 }
12908 char buf[64]= {'\0'};
12909 wifi_getRadioOperatingChannelBandwidth(index,buf);
12910 printf("Current bandwidth is %s \n",buf);
12911 return 0;
12912 }
12913 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12914 {
12915 if (argc <= 5)
12916 {
12917 printf("Insufficient arguments\n");
12918 exit(-1);
12919 }
12920 UINT channel = atoi(argv[3]);
12921 UINT width = atoi(argv[4]);
12922 UINT beacon = atoi(argv[5]);
12923 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12924 printf("Result = %d", ret);
12925 }
12926
12927 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12928 return 0;
12929}
12930
12931#endif
12932
12933#ifdef WIFI_HAL_VERSION_3
12934
12935INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12936{
12937 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12938 if (bitMap & WIFI_BITRATE_1MBPS)
12939 strcat(BasicRate, "1,");
12940 if (bitMap & WIFI_BITRATE_2MBPS)
12941 strcat(BasicRate, "2,");
12942 if (bitMap & WIFI_BITRATE_5_5MBPS)
12943 strcat(BasicRate, "5.5,");
12944 if (bitMap & WIFI_BITRATE_6MBPS)
12945 strcat(BasicRate, "6,");
12946 if (bitMap & WIFI_BITRATE_9MBPS)
12947 strcat(BasicRate, "9,");
12948 if (bitMap & WIFI_BITRATE_11MBPS)
12949 strcat(BasicRate, "11,");
12950 if (bitMap & WIFI_BITRATE_12MBPS)
12951 strcat(BasicRate, "12,");
12952 if (bitMap & WIFI_BITRATE_18MBPS)
12953 strcat(BasicRate, "18,");
12954 if (bitMap & WIFI_BITRATE_24MBPS)
12955 strcat(BasicRate, "24,");
12956 if (bitMap & WIFI_BITRATE_36MBPS)
12957 strcat(BasicRate, "36,");
12958 if (bitMap & WIFI_BITRATE_48MBPS)
12959 strcat(BasicRate, "48,");
12960 if (bitMap & WIFI_BITRATE_54MBPS)
12961 strcat(BasicRate, "54,");
12962 if (strlen(BasicRate) != 0) // remove last comma
12963 BasicRate[strlen(BasicRate) - 1] = '\0';
12964 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12965 return RETURN_OK;
12966}
12967
12968INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12969{
12970 UINT BitMap = 0;
12971 char *rate;
12972
12973 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12974 rate = strtok(BasicRatesList, ",");
12975 while(rate != NULL)
12976 {
12977 if (strcmp(rate, "1") == 0)
12978 BitMap |= WIFI_BITRATE_1MBPS;
12979 else if (strcmp(rate, "2") == 0)
12980 BitMap |= WIFI_BITRATE_2MBPS;
12981 else if (strcmp(rate, "5.5") == 0)
12982 BitMap |= WIFI_BITRATE_5_5MBPS;
12983 else if (strcmp(rate, "6") == 0)
12984 BitMap |= WIFI_BITRATE_6MBPS;
12985 else if (strcmp(rate, "9") == 0)
12986 BitMap |= WIFI_BITRATE_9MBPS;
12987 else if (strcmp(rate, "11") == 0)
12988 BitMap |= WIFI_BITRATE_11MBPS;
12989 else if (strcmp(rate, "12") == 0)
12990 BitMap |= WIFI_BITRATE_12MBPS;
12991 else if (strcmp(rate, "18") == 0)
12992 BitMap |= WIFI_BITRATE_18MBPS;
12993 else if (strcmp(rate, "24") == 0)
12994 BitMap |= WIFI_BITRATE_24MBPS;
12995 else if (strcmp(rate, "36") == 0)
12996 BitMap |= WIFI_BITRATE_36MBPS;
12997 else if (strcmp(rate, "48") == 0)
12998 BitMap |= WIFI_BITRATE_48MBPS;
12999 else if (strcmp(rate, "54") == 0)
13000 BitMap |= WIFI_BITRATE_54MBPS;
13001 rate = strtok(NULL, ",");
13002 }
13003 *basicRateBitMap = BitMap;
13004 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13005 return RETURN_OK;
13006}
13007
13008// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
13009INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
13010{
13011 char buf[128] = {0};
13012 char cmd[128] = {0};
13013 char config_file[64] = {0};
13014 int bandwidth;
13015 int set_mode = 0;
13016 wifi_radio_operationParam_t current_param;
13017
13018 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13019
13020 multiple_set = TRUE;
13021 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
13022 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
13023 return RETURN_ERR;
13024 }
13025 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
13026 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
13027 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
13028 return RETURN_ERR;
13029 }
13030 }
13031
13032 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
13033 bandwidth = 20;
13034 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
13035 bandwidth = 40;
13036 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
13037 bandwidth = 80;
13038 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
13039 bandwidth = 160;
13040 if (operationParam->autoChannelEnabled){
13041 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
13042 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
13043 return RETURN_ERR;
13044 }
developer69b61b02023-03-07 17:17:44 +080013045 }else{
developer72fb0bb2023-01-11 09:46:29 +080013046 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
13047 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
13048 return RETURN_ERR;
13049 }
13050 }
13051
13052 if (current_param.variant != operationParam->variant) {
13053 // Two different definition bit map, so need to check every bit.
13054 if (operationParam->variant & WIFI_80211_VARIANT_A)
13055 set_mode |= WIFI_MODE_A;
13056 if (operationParam->variant & WIFI_80211_VARIANT_B)
13057 set_mode |= WIFI_MODE_B;
13058 if (operationParam->variant & WIFI_80211_VARIANT_G)
13059 set_mode |= WIFI_MODE_G;
13060 if (operationParam->variant & WIFI_80211_VARIANT_N)
13061 set_mode |= WIFI_MODE_N;
13062 if (operationParam->variant & WIFI_80211_VARIANT_AC)
13063 set_mode |= WIFI_MODE_AC;
13064 if (operationParam->variant & WIFI_80211_VARIANT_AX)
13065 set_mode |= WIFI_MODE_AX;
13066 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
13067 memset(buf, 0, sizeof(buf));
developer0f10c772023-05-16 21:43:39 +080013068 if (wifi_setRadioMode_by_dat(index, set_mode) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080013069 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
13070 return RETURN_ERR;
13071 }
13072 }
13073 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
13074 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
13075 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
13076 return RETURN_ERR;
13077 }
13078 }
13079 if (current_param.beaconInterval != operationParam->beaconInterval) {
13080 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
13081 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
13082 return RETURN_ERR;
13083 }
13084 }
13085 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
13086 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
13087 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
13088 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
13089 return RETURN_ERR;
13090 }
13091 }
13092 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
13093 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
13094 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
13095 return RETURN_ERR;
13096 }
13097 }
13098 if (current_param.guardInterval != operationParam->guardInterval) {
13099 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
13100 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
13101 return RETURN_ERR;
13102 }
13103 }
13104 if (current_param.transmitPower != operationParam->transmitPower) {
13105 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
13106 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
13107 return RETURN_ERR;
13108 }
13109 }
13110 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
13111 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
13112 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
13113 return RETURN_ERR;
13114 }
13115 }
13116 if (current_param.obssCoex != operationParam->obssCoex) {
13117 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
13118 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
13119 return RETURN_ERR;
13120 }
13121 }
13122 if (current_param.stbcEnable != operationParam->stbcEnable) {
13123 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
13124 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
13125 return RETURN_ERR;
13126 }
13127 }
13128 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
13129 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
13130 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
13131 return RETURN_ERR;
13132 }
13133 }
13134
13135 // if enable is true, then restart the radio
13136 wifi_setRadioEnable(index, FALSE);
13137 if (operationParam->enable == TRUE)
13138 wifi_setRadioEnable(index, TRUE);
13139 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13140
13141 return RETURN_OK;
13142}
13143
13144INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
13145{
13146 char band[64] = {0};
13147 char buf[256] = {0};
13148 char config_file[64] = {0};
13149 char cmd[128] = {0};
13150 int ret = RETURN_ERR;
13151 int mode = 0;
13152 ULONG channel = 0;
13153 BOOL enabled = FALSE;
13154
13155 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13156 printf("Entering %s index = %d\n", __func__, (int)index);
13157
13158 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
13159 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
13160 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
13161 {
13162 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
13163 return RETURN_ERR;
13164 }
13165 operationParam->enable = enabled;
13166
13167 memset(band, 0, sizeof(band));
13168 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
13169 {
13170 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
13171 return RETURN_ERR;
13172 }
13173
13174 if (!strcmp(band, "2.4GHz"))
13175 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
13176 else if (!strcmp(band, "5GHz"))
13177 operationParam->band = WIFI_FREQUENCY_5_BAND;
13178 else if (!strcmp(band, "6GHz"))
13179 operationParam->band = WIFI_FREQUENCY_6_BAND;
13180 else
13181 {
13182 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
13183 band);
13184 }
13185
13186 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
13187 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
13188 operationParam->channel = 0;
13189 operationParam->autoChannelEnabled = TRUE;
13190 } else {
13191 operationParam->channel = strtol(buf, NULL, 10);
13192 operationParam->autoChannelEnabled = FALSE;
13193 }
13194
13195 memset(buf, 0, sizeof(buf));
13196 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
13197 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
13198 return RETURN_ERR;
13199 }
13200 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
13201 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
13202 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
13203 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
13204 else
13205 {
13206 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
13207 return false;
13208 }
13209
13210 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
13211 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
13212 return RETURN_ERR;
13213 }
13214 // Two different definition bit map, so need to check every bit.
13215 if (mode & WIFI_MODE_A)
13216 operationParam->variant |= WIFI_80211_VARIANT_A;
13217 if (mode & WIFI_MODE_B)
13218 operationParam->variant |= WIFI_80211_VARIANT_B;
13219 if (mode & WIFI_MODE_G)
13220 operationParam->variant |= WIFI_80211_VARIANT_G;
13221 if (mode & WIFI_MODE_N)
13222 operationParam->variant |= WIFI_80211_VARIANT_N;
13223 if (mode & WIFI_MODE_AC)
13224 operationParam->variant |= WIFI_80211_VARIANT_AC;
13225 if (mode & WIFI_MODE_AX)
13226 operationParam->variant |= WIFI_80211_VARIANT_AX;
13227 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
13228 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
13229 return RETURN_ERR;
13230 }
13231 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
13232 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
13233 return RETURN_ERR;
13234 }
13235 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
13236 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
13237 return RETURN_ERR;
13238 }
13239
13240 memset(buf, 0, sizeof(buf));
13241 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
13242 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
13243 return RETURN_ERR;
13244 }
13245 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
13246
13247 memset(buf, 0, sizeof(buf));
13248 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
13249 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
13250 return RETURN_ERR;
13251 }
13252 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
13253
13254 memset(buf, 0, sizeof(buf));
13255 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
13256 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
13257
13258 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
13259 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
13260 return RETURN_ERR;
13261 }
developera1255e42023-05-13 17:45:02 +080013262 if (wifi_getRadioPercentageTransmitPower(index, (ULONG *)&operationParam->transmitPower) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080013263 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
13264 return RETURN_ERR;
13265 }
13266
13267 memset(buf, 0, sizeof(buf));
13268 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
13269 if (strcmp(buf, "-1") == 0) {
13270 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
13271 operationParam->ctsProtection = FALSE;
13272 } else {
13273 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
13274 operationParam->ctsProtection = TRUE;
13275 }
13276
13277 memset(buf, 0, sizeof(buf));
13278 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
13279 if (strcmp(buf, "0") == 0)
13280 operationParam->obssCoex = FALSE;
13281 else
13282 operationParam->obssCoex = TRUE;
13283
13284 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
13285 _syscmd(cmd, buf, sizeof(buf));
13286 if (strlen(buf) != 0)
13287 operationParam->stbcEnable = TRUE;
13288 else
13289 operationParam->stbcEnable = FALSE;
13290
13291 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
13292 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
13293 return RETURN_ERR;
13294 }
13295
13296 // Below value is hardcoded
13297
13298 operationParam->numSecondaryChannels = 0;
13299 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
13300 operationParam->channelSecondary[i] = 0;
13301 }
13302 operationParam->csa_beacon_count = 15;
13303 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
13304
13305 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13306 return RETURN_OK;
13307}
13308
13309static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
13310{
13311 int max_radio_num = 0;
13312
13313 wifi_getMaxRadioNumber(&max_radio_num);
13314 if (radioIndex >= max_radio_num) {
13315 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
13316 return RETURN_ERR;
13317 }
13318
13319 return (arrayIndex * max_radio_num) + radioIndex;
13320}
13321
developer96b38512023-02-22 11:17:45 +080013322static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex)
13323{
13324 int max_radio_num = 0;
13325
13326 if ((vapIndex < 0) || (vapIndex > MAX_NUM_VAP_PER_RADIO*MAX_NUM_RADIOS))
13327 return -1;
13328
13329 wifi_getMaxRadioNumber(&max_radio_num);
13330
13331 (*radioIndex) = vapIndex % max_radio_num;
13332 (*arrayIndex) = vapIndex / max_radio_num;
13333
13334 return 0;
13335}
13336
13337
developer72fb0bb2023-01-11 09:46:29 +080013338wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
13339 if (strncmp(beaconRate, "1Mbps", 5) == 0)
13340 return WIFI_BITRATE_1MBPS;
13341 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
13342 return WIFI_BITRATE_2MBPS;
13343 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
13344 return WIFI_BITRATE_5_5MBPS;
13345 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
13346 return WIFI_BITRATE_6MBPS;
13347 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
13348 return WIFI_BITRATE_9MBPS;
13349 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
13350 return WIFI_BITRATE_11MBPS;
13351 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
13352 return WIFI_BITRATE_12MBPS;
13353 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
13354 return WIFI_BITRATE_18MBPS;
13355 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
13356 return WIFI_BITRATE_24MBPS;
13357 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
13358 return WIFI_BITRATE_36MBPS;
13359 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
13360 return WIFI_BITRATE_48MBPS;
13361 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
13362 return WIFI_BITRATE_54MBPS;
13363 return WIFI_BITRATE_DEFAULT;
13364}
13365
13366INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
13367{
13368 if (beacon == WIFI_BITRATE_1MBPS)
13369 strcpy(beacon_str, "1Mbps");
13370 else if (beacon == WIFI_BITRATE_2MBPS)
13371 strcpy(beacon_str, "2Mbps");
13372 else if (beacon == WIFI_BITRATE_5_5MBPS)
13373 strcpy(beacon_str, "5.5Mbps");
13374 else if (beacon == WIFI_BITRATE_6MBPS)
13375 strcpy(beacon_str, "6Mbps");
13376 else if (beacon == WIFI_BITRATE_9MBPS)
13377 strcpy(beacon_str, "9Mbps");
13378 else if (beacon == WIFI_BITRATE_11MBPS)
13379 strcpy(beacon_str, "11Mbps");
13380 else if (beacon == WIFI_BITRATE_12MBPS)
13381 strcpy(beacon_str, "12Mbps");
13382 else if (beacon == WIFI_BITRATE_18MBPS)
13383 strcpy(beacon_str, "18Mbps");
13384 else if (beacon == WIFI_BITRATE_24MBPS)
13385 strcpy(beacon_str, "24Mbps");
13386 else if (beacon == WIFI_BITRATE_36MBPS)
13387 strcpy(beacon_str, "36Mbps");
13388 else if (beacon == WIFI_BITRATE_48MBPS)
13389 strcpy(beacon_str, "48Mbps");
13390 else if (beacon == WIFI_BITRATE_54MBPS)
13391 strcpy(beacon_str, "54Mbps");
13392 return RETURN_OK;
13393}
13394
13395INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13396{
13397 INT mode = 0;
13398 INT ret = -1;
13399 INT output = 0;
13400 int i = 0;
13401 int vap_index = 0;
13402 BOOL enabled = FALSE;
13403 char buf[256] = {0};
13404 wifi_vap_security_t security = {0};
13405 map->num_vaps = 5; // Hardcoded
13406
13407 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13408 printf("Entering %s index = %d\n", __func__, (int)index);
13409
13410 for (i = 0; i < 5; i++)
13411 {
13412 map->vap_array[i].radio_index = index;
13413
13414 vap_index = array_index_to_vap_index(index, i);
13415 if (vap_index < 0)
13416 return RETURN_ERR;
13417
13418 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
13419
13420 map->vap_array[i].vap_index = vap_index;
13421
13422 memset(buf, 0, sizeof(buf));
13423 ret = wifi_getApName(vap_index, buf);
13424 if (ret != RETURN_OK) {
13425 printf("%s: wifi_getApName return error\n", __func__);
13426 return RETURN_ERR;
13427 }
13428 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
13429
13430 memset(buf, 0, sizeof(buf));
13431 ret = wifi_getSSIDName(vap_index, buf);
13432 if (ret != RETURN_OK) {
13433 printf("%s: wifi_getSSIDName return error\n", __func__);
13434 return RETURN_ERR;
13435 }
13436 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
13437
13438 ret = wifi_getSSIDEnable(vap_index, &enabled);
13439 if (ret != RETURN_OK) {
13440 printf("%s: wifi_getSSIDEnable return error\n", __func__);
13441 return RETURN_ERR;
13442 }
13443 map->vap_array[i].u.bss_info.enabled = enabled;
13444
13445 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
13446 if (ret != RETURN_OK) {
13447 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
13448 return RETURN_ERR;
13449 }
13450 map->vap_array[i].u.bss_info.showSsid = enabled;
developer69b61b02023-03-07 17:17:44 +080013451
developer72fb0bb2023-01-11 09:46:29 +080013452 ret = wifi_getApIsolationEnable(vap_index, &enabled);
13453 if (ret != RETURN_OK) {
13454 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
13455 return RETURN_ERR;
13456 }
13457 map->vap_array[i].u.bss_info.isolation = enabled;
13458
13459 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
13460 if (ret != RETURN_OK) {
13461 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
13462 return RETURN_ERR;
13463 }
13464 map->vap_array[i].u.bss_info.bssMaxSta = output;
13465
13466 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
13467 if (ret != RETURN_OK) {
13468 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
13469 return RETURN_ERR;
13470 }
13471 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
13472
13473 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
13474 if (ret != RETURN_OK) {
13475 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
13476 return RETURN_ERR;
13477 }
13478 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
13479
13480 ret = wifi_getApSecurity(vap_index, &security);
13481 if (ret != RETURN_OK) {
13482 printf("%s: wifi_getApSecurity return error\n", __func__);
13483 return RETURN_ERR;
13484 }
13485 map->vap_array[i].u.bss_info.security = security;
13486
13487 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
13488 if (ret != RETURN_OK) {
13489 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
13490 return RETURN_ERR;
13491 }
developer69b61b02023-03-07 17:17:44 +080013492 if (mode == 0)
developer72fb0bb2023-01-11 09:46:29 +080013493 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
developer69b61b02023-03-07 17:17:44 +080013494 else
developer72fb0bb2023-01-11 09:46:29 +080013495 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
developer69b61b02023-03-07 17:17:44 +080013496 if (mode == 1)
developer72fb0bb2023-01-11 09:46:29 +080013497 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
developer69b61b02023-03-07 17:17:44 +080013498 else if (mode == 2)
developer72fb0bb2023-01-11 09:46:29 +080013499 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
13500
13501 ret = wifi_getApWmmEnable(vap_index, &enabled);
13502 if (ret != RETURN_OK) {
13503 printf("%s: wifi_getApWmmEnable return error\n", __func__);
13504 return RETURN_ERR;
13505 }
13506 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
13507
13508 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
13509 if (ret != RETURN_OK) {
13510 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
13511 return RETURN_ERR;
13512 }
13513 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
13514
13515 memset(buf, 0, sizeof(buf));
13516 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
13517 if (ret != RETURN_OK) {
13518 printf("%s: wifi_getApBeaconRate return error\n", __func__);
13519 return RETURN_ERR;
13520 }
13521 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
13522
13523 memset(buf, 0, sizeof(buf));
13524 ret = wifi_getBaseBSSID(vap_index, buf);
13525 if (ret != RETURN_OK) {
13526 printf("%s: wifi_getBaseBSSID return error\n", __func__);
13527 return RETURN_ERR;
13528 }
13529 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
13530 &map->vap_array[i].u.bss_info.bssid[0],
13531 &map->vap_array[i].u.bss_info.bssid[1],
13532 &map->vap_array[i].u.bss_info.bssid[2],
13533 &map->vap_array[i].u.bss_info.bssid[3],
13534 &map->vap_array[i].u.bss_info.bssid[4],
13535 &map->vap_array[i].u.bss_info.bssid[5]);
13536 // 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]);
13537
13538 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
13539 if (ret != RETURN_OK) {
13540 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
13541 return RETURN_ERR;
13542 }
13543 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
13544
13545 // TODO: wps, noack
13546 }
13547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13548 return RETURN_OK;
13549}
13550
developer47cc27a2023-05-17 23:09:58 +080013551void checkVapStatus(int apIndex, BOOL *enable)
developer72fb0bb2023-01-11 09:46:29 +080013552{
13553 char if_name[16] = {0};
13554 char cmd[128] = {0};
13555 char buf[128] = {0};
13556
13557 *enable = FALSE;
13558 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
13559 return;
13560
13561 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
13562 _syscmd(cmd, buf, sizeof(buf));
13563 if (strlen(buf) > 0)
13564 *enable = TRUE;
13565 return;
13566}
13567
13568static int prepareInterface(UINT apIndex, char *new_interface)
13569{
13570 char cur_interface[16] = {0};
13571 char config_file[128] = {0};
developer8a3bbbf2023-03-15 17:47:23 +080013572 char cmd[MAX_CMD_SIZE] = {0};
13573 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013574 int max_radio_num = 0;
13575 int radioIndex = -1;
13576 int phyIndex = -1;
developer8a3bbbf2023-03-15 17:47:23 +080013577 struct params params;
developer72fb0bb2023-01-11 09:46:29 +080013578
13579 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
13580 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
13581
13582 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
developer8a3bbbf2023-03-15 17:47:23 +080013583 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +080013584 radioIndex = apIndex % max_radio_num;
13585 phyIndex = radio_index_to_phy(radioIndex);
13586 // disable and del old interface, then add new interface
13587 wifi_setApEnable(apIndex, FALSE);
developer8a3bbbf2023-03-15 17:47:23 +080013588
13589 params.name = "interface";
13590 params.value = new_interface;
13591 wifi_hostapdWrite(config_file, &params, 1);
13592
13593 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyIndex, config_file);
13594 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080013595 }
developer8a3bbbf2023-03-15 17:47:23 +080013596
developer72fb0bb2023-01-11 09:46:29 +080013597 // update the vap status file
13598 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
13599 _syscmd(cmd, buf, sizeof(buf));
13600 return RETURN_OK;
13601}
13602
13603INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13604{
13605 char interface_name[16] = {0};
13606 unsigned int i;
13607 wifi_vap_info_t *vap_info = NULL;
13608 int acl_mode;
13609 int ret = 0;
13610 char *sec_str = NULL;
13611 char buf[256] = {0};
13612 char cmd[128] = {0};
13613 char config_file[64] = {0};
13614 char bssid[32] = {0};
13615 char psk_file[64] = {0};
developer47cc27a2023-05-17 23:09:58 +080013616 BOOL enable = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080013617
13618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13619 printf("Entering %s index = %d\n", __func__, (int)index);
13620 for (i = 0; i < map->num_vaps; i++)
13621 {
13622 multiple_set = TRUE;
13623 vap_info = &map->vap_array[i];
13624
13625 // Check vap status file to enable multiple ap if the system boot.
13626 checkVapStatus(vap_info->vap_index, &enable);
13627 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
13628 continue;
13629
13630 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
13631
13632 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
13633 enable = FALSE;
13634
13635 // multi-ap first up need to copy current radio config
13636 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
13637 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
13638 _syscmd(cmd, buf, sizeof(buf));
13639 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
13640 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
13641 } else {
13642 // Check whether the interface name is valid or this ap change it.
13643 int apIndex = -1;
13644 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
13645 if (apIndex != -1 && apIndex != vap_info->vap_index)
13646 continue;
13647 prepareInterface(vap_info->vap_index, vap_info->vap_name);
13648 }
13649
13650 struct params params[3];
13651 params[0].name = "interface";
13652 params[0].value = vap_info->vap_name;
13653 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
13654 params[1].name = "bssid";
13655 params[1].value = bssid;
13656 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
13657 params[2].name = "wpa_psk_file";
13658 params[2].value = psk_file;
13659
13660 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
13661 wifi_hostapdWrite(config_file, params, 3);
13662
13663 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
13664 _syscmd(cmd, buf, sizeof(buf));
13665
13666 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
13667 if (ret != RETURN_OK) {
13668 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
13669 return RETURN_ERR;
13670 }
13671
13672 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
13673 if (ret != RETURN_OK) {
13674 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
13675 return RETURN_ERR;
13676 }
13677
13678 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
13679 if (ret != RETURN_OK) {
13680 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
13681 return RETURN_ERR;
13682 }
13683
13684 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
13685 if (ret != RETURN_OK) {
13686 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
13687 return RETURN_ERR;
13688 }
13689
13690 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
13691 if (ret != RETURN_OK) {
13692 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
13693 return RETURN_ERR;
13694 }
13695
13696 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
13697 if (ret != RETURN_OK) {
13698 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
13699 return RETURN_ERR;
13700 }
13701
13702 if (vap_info->u.bss_info.mac_filter_enable == false){
13703 acl_mode = 0;
13704 }else {
13705 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
13706 acl_mode = 2;
13707 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13708 _syscmd(cmd, buf, sizeof(buf));
13709 }else{
13710 acl_mode = 1;
13711 }
13712 }
13713
13714 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
13715 if (ret != RETURN_OK) {
13716 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
13717 return RETURN_ERR;
13718 }
13719
13720 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
13721 if (ret != RETURN_OK) {
13722 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
13723 return RETURN_ERR;
13724 }
13725
developer0f10c772023-05-16 21:43:39 +080013726 memset(buf, 0, sizeof(buf));
13727 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
13728 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
13729 if (ret != RETURN_OK) {
13730 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
13731 return RETURN_ERR;
13732 }
developer72fb0bb2023-01-11 09:46:29 +080013733
13734 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
13735 if (ret != RETURN_OK) {
13736 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
13737 return RETURN_ERR;
13738 }
13739
developer72fb0bb2023-01-11 09:46:29 +080013740 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
13741 if (ret != RETURN_OK) {
13742 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
13743 return RETURN_ERR;
13744 }
13745
developer23e71282023-01-18 10:25:19 +080013746 wifi_setApEnable(vap_info->vap_index, FALSE);
13747 wifi_setApEnable(vap_info->vap_index, TRUE);
13748 multiple_set = FALSE;
13749
13750 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080013751 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
13752 if (ret != RETURN_OK) {
13753 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
13754 return RETURN_ERR;
13755 }
13756
13757 // TODO mgmtPowerControl, interworking, wps
13758 }
13759 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13760 return RETURN_OK;
13761}
13762
13763int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
13764{
13765 char *token, *next;
13766 const char s[2] = ",";
13767 int count =0;
13768
13769 /* get the first token */
13770 token = strtok_r(pchannels, s, &next);
13771
13772 /* walk through other tokens */
13773 while( token != NULL && count < MAX_CHANNELS) {
13774 chlistptr->channels_list[count++] = atoi(token);
13775 token = strtok_r(NULL, s, &next);
13776 }
13777
13778 return count;
13779}
13780
13781static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
13782{
13783 INT status;
13784 wifi_channels_list_t *chlistp;
13785 CHAR output_string[64];
13786 CHAR pchannels[128];
13787 CHAR interface_name[16] = {0};
13788 wifi_band band;
13789
13790 if(rcap == NULL)
13791 {
13792 return RETURN_ERR;
13793 }
13794
13795 rcap->numSupportedFreqBand = 1;
13796 band = wifi_index_to_band(radioIndex);
13797
13798 if (band == band_2_4)
13799 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
13800 else if (band == band_5)
13801 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
13802 else if (band == band_6)
13803 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
13804
13805 chlistp = &(rcap->channel_list[0]);
13806 memset(pchannels, 0, sizeof(pchannels));
13807
13808 /* possible number of radio channels */
13809 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13810 {
13811 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13812 }
13813 /* Number of channels and list*/
13814 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13815
13816 /* autoChannelSupported */
13817 /* always ON with wifi_getRadioAutoChannelSupported */
13818 rcap->autoChannelSupported = TRUE;
13819
13820 /* DCSSupported */
13821 /* always ON with wifi_getRadioDCSSupported */
13822 rcap->DCSSupported = TRUE;
13823
13824 /* zeroDFSSupported - TBD */
13825 rcap->zeroDFSSupported = FALSE;
13826
13827 /* Supported Country List*/
13828 memset(output_string, 0, sizeof(output_string));
13829 status = wifi_getRadioCountryCode(radioIndex, output_string);
13830 if( status != 0 ) {
13831 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13832 return RETURN_ERR;
13833 } else {
13834 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13835 }
13836 if(!strcmp(output_string,"US")){
13837 rcap->countrySupported[0] = wifi_countrycode_US;
13838 rcap->countrySupported[1] = wifi_countrycode_CA;
13839 } else if (!strcmp(output_string,"CA")) {
13840 rcap->countrySupported[0] = wifi_countrycode_CA;
13841 rcap->countrySupported[1] = wifi_countrycode_US;
13842 } else {
13843 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13844 }
13845
13846 rcap->numcountrySupported = 2;
13847
13848 /* csi */
13849 rcap->csi.maxDevices = 8;
13850 rcap->csi.soudingFrameSupported = TRUE;
13851
13852 wifi_GetInterfaceName(radioIndex, interface_name);
13853 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
13854
13855 /* channelWidth - all supported bandwidths */
13856 int i=0;
13857 rcap->channelWidth[i] = 0;
13858 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13859 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13860 WIFI_CHANNELBANDWIDTH_40MHZ);
13861
13862 }
13863 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
13864 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13865 WIFI_CHANNELBANDWIDTH_40MHZ |
13866 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
13867 }
13868
13869
13870 /* mode - all supported variants */
13871 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13872 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
13873 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
13874 }
13875 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
13876 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
13877 }
13878 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13879 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
13880 }
13881 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13882 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13883
13884 /* supportedBitRate - all supported bitrates */
13885 rcap->supportedBitRate[i] = 0;
13886 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13887 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13888 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13889 }
13890 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
13891 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13892 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13893 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13894 }
13895
13896
13897 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13898 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13899 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13900 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13901 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13902 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13903 rcap->cipherSupported = 0;
13904 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13905 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13906
13907 return RETURN_OK;
13908}
13909
13910INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13911{
13912 INT status = 0, radioIndex = 0;
13913 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
13914 int iter = 0;
13915 unsigned int j = 0;
13916 int max_num_radios;
13917 wifi_interface_name_idex_map_t *iface_info = NULL;
13918
13919 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13920
13921 memset(cap, 0, sizeof(wifi_hal_capability_t));
13922
13923 /* version */
13924 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13925 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13926
13927 /* number of radios platform property */
13928 wifi_getMaxRadioNumber(&max_num_radios);
13929 cap->wifi_prop.numRadios = max_num_radios;
13930
13931 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13932 {
13933 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13934 if (status != 0) {
13935 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13936 return RETURN_ERR;
13937 }
13938
13939 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13940 {
13941 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
13942 {
13943 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13944 return RETURN_ERR;
13945 }
13946 iface_info = &cap->wifi_prop.interface_map[iter];
13947 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13948 iface_info->rdk_radio_index = radioIndex;
13949 memset(output, 0, sizeof(output));
13950 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13951 {
13952 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13953 }
13954 // TODO: bridge name
13955 // TODO: vlan id
13956 // TODO: primary
13957 iface_info->index = array_index_to_vap_index(radioIndex, j);
13958 memset(output, 0, sizeof(output));
13959 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
13960 {
13961 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13962 }
13963 iter++;
13964 }
13965 }
13966
13967 cap->BandSteeringSupported = FALSE;
13968 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13969 return RETURN_OK;
13970}
13971
13972INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13973{
13974 struct params h_config={0};
13975 char config_file[64] = {0};
13976
13977 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13978
13979 h_config.name = "okc";
13980 h_config.value = okc_enable?"1":"0";
13981
13982 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13983 wifi_hostapdWrite(config_file, &h_config, 1);
13984 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13985
13986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13987 return RETURN_OK;
13988}
13989
13990INT wifi_setSAEMFP(int ap_index, BOOL enable)
13991{
13992 struct params h_config={0};
13993 char config_file[64] = {0};
13994 char buf[128] = {0};
13995
13996 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13997
13998 h_config.name = "sae_require_mfp";
13999 h_config.value = enable?"1":"0";
14000
14001 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
14002 wifi_hostapdWrite(config_file, &h_config, 1);
14003 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
14004
14005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
14006 return RETURN_OK;
14007}
14008
14009INT wifi_setSAEpwe(int ap_index, int sae_pwe)
14010{
14011 struct params h_config={0};
14012 char config_file[64] = {0};
14013 char buf[128] = {0};
14014
14015 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
14016
14017 h_config.name = "sae_pwe";
14018 snprintf(buf, sizeof(buf), "%d", sae_pwe);
14019 h_config.value = buf;
14020
14021 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
14022 wifi_hostapdWrite(config_file, &h_config, 1);
14023 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
14024
14025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
14026 return RETURN_OK;
14027}
14028
14029INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
14030{
14031 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
14032 struct params h_config={0};
14033 char config_file[64] = {0};
14034
14035 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
14036
14037 h_config.name = "wpa_disable_eapol_key_retries";
14038 h_config.value = disable_EAPOL_retries?"1":"0";
14039
14040 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
14041 wifi_hostapdWrite(config_file, &h_config, 1);
14042 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
14043
14044 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
14045 return RETURN_OK;
14046}
14047
14048INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
14049{
14050 char buf[128] = {0};
14051 char config_file[128] = {0};
developere5750452023-05-15 16:46:42 +080014052 char cmd[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +080014053 char password[64] = {0};
14054 char mfp[32] = {0};
14055 char wpa_mode[32] = {0};
14056 BOOL okc_enable = FALSE;
14057 BOOL sae_MFP = FALSE;
14058 BOOL disable_EAPOL_retries = TRUE;
14059 int sae_pwe = 0;
14060 struct params params = {0};
14061 wifi_band band = band_invalid;
14062
14063 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14064
14065 multiple_set = TRUE;
14066 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
14067 if (security->mode == wifi_security_mode_none) {
14068 strcpy(wpa_mode, "None");
14069 } else if (security->mode == wifi_security_mode_wpa_personal)
14070 strcpy(wpa_mode, "WPA-Personal");
14071 else if (security->mode == wifi_security_mode_wpa2_personal)
14072 strcpy(wpa_mode, "WPA2-Personal");
14073 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
14074 strcpy(wpa_mode, "WPA-WPA2-Personal");
14075 else if (security->mode == wifi_security_mode_wpa_enterprise)
14076 strcpy(wpa_mode, "WPA-Enterprise");
14077 else if (security->mode == wifi_security_mode_wpa2_enterprise)
14078 strcpy(wpa_mode, "WPA2-Enterprise");
14079 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
14080 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
14081 else if (security->mode == wifi_security_mode_wpa3_personal) {
14082 strcpy(wpa_mode, "WPA3-Personal");
14083 okc_enable = TRUE;
14084 sae_MFP = TRUE;
14085 sae_pwe = 2;
14086 disable_EAPOL_retries = FALSE;
14087 } else if (security->mode == wifi_security_mode_wpa3_transition) {
14088 strcpy(wpa_mode, "WPA3-Personal-Transition");
14089 okc_enable = TRUE;
14090 sae_MFP = TRUE;
14091 sae_pwe = 2;
14092 disable_EAPOL_retries = FALSE;
14093 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
14094 strcpy(wpa_mode, "WPA3-Enterprise");
14095 sae_MFP = TRUE;
14096 sae_pwe = 2;
14097 disable_EAPOL_retries = FALSE;
developerd01e3e82023-04-26 19:10:38 +080014098 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer3086e2f2023-01-17 09:40:01 +080014099 strcpy(wpa_mode, "OWE");
14100 sae_MFP = TRUE;
14101 sae_pwe = 2;
14102 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080014103 }
14104
14105 band = wifi_index_to_band(ap_index);
14106 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
14107 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
14108 return RETURN_ERR;
14109 }
14110
14111 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
14112 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
14113 wifi_setSAEMFP(ap_index, sae_MFP);
14114 wifi_setSAEpwe(ap_index, sae_pwe);
14115 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
14116
developerd01e3e82023-04-26 19:10:38 +080014117 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developere5750452023-05-15 16:46:42 +080014118 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_pass || security->u.key.type == wifi_security_key_type_psk_sae) {
14119 int key_len = strlen(security->u.key.key);
14120 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
14121 if (key_len == 64) { // set wpa_psk
14122 strncpy(password, security->u.key.key, 64); // 64 characters
14123 password[64] = '\0';
14124 wifi_setApSecurityPreSharedKey(ap_index, password);
14125 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
14126 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
14127 strncpy(password, security->u.key.key, 63);
14128 password[63] = '\0';
14129 wifi_setApSecurityKeyPassphrase(ap_index, password);
14130 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
14131 } else
14132 return RETURN_ERR;
14133 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080014134 }
14135 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
14136 params.name = "sae_password";
14137 params.value = security->u.key.key;
14138 wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +080014139 } else { // remove sae_password
14140 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
14141 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080014142 }
14143 }
14144
14145 if (security->mode != wifi_security_mode_none) {
14146 memset(&params, 0, sizeof(params));
14147 params.name = "wpa_pairwise";
14148 if (security->encr == wifi_encryption_tkip)
14149 params.value = "TKIP";
14150 else if (security->encr == wifi_encryption_aes)
14151 params.value = "CCMP";
14152 else if (security->encr == wifi_encryption_aes_tkip)
14153 params.value = "TKIP CCMP";
14154 wifi_hostapdWrite(config_file, &params, 1);
14155 }
14156
14157 if (security->mfp == wifi_mfp_cfg_disabled)
14158 strcpy(mfp, "Disabled");
14159 else if (security->mfp == wifi_mfp_cfg_optional)
14160 strcpy(mfp, "Optional");
14161 else if (security->mfp == wifi_mfp_cfg_required)
14162 strcpy(mfp, "Required");
14163 wifi_setApSecurityMFPConfig(ap_index, mfp);
14164
14165 memset(&params, 0, sizeof(params));
14166 params.name = "transition_disable";
14167 if (security->wpa3_transition_disable == TRUE)
14168 params.value = "0x01";
14169 else
14170 params.value = "0x00";
14171 wifi_hostapdWrite(config_file, &params, 1);
14172
14173 memset(&params, 0, sizeof(params));
14174 params.name = "wpa_group_rekey";
14175 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
14176 params.value = buf;
14177 wifi_hostapdWrite(config_file, &params, 1);
14178
14179 memset(&params, 0, sizeof(params));
14180 params.name = "wpa_strict_rekey";
14181 params.value = security->strict_rekey?"1":"0";
14182 wifi_hostapdWrite(config_file, &params, 1);
14183
14184 memset(&params, 0, sizeof(params));
14185 params.name = "wpa_pairwise_update_count";
developere5750452023-05-15 16:46:42 +080014186 if (security->eapol_key_retries == 0)
14187 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer72fb0bb2023-01-11 09:46:29 +080014188 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
14189 params.value = buf;
14190 wifi_hostapdWrite(config_file, &params, 1);
14191
14192 memset(&params, 0, sizeof(params));
14193 params.name = "disable_pmksa_caching";
14194 params.value = security->disable_pmksa_caching?"1":"0";
14195 wifi_hostapdWrite(config_file, &params, 1);
14196
developer23e71282023-01-18 10:25:19 +080014197 if (multiple_set == FALSE) {
14198 wifi_setApEnable(ap_index, FALSE);
14199 wifi_setApEnable(ap_index, TRUE);
14200 }
developer72fb0bb2023-01-11 09:46:29 +080014201
14202 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14203
14204 return RETURN_OK;
14205}
14206
14207INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
14208{
14209 char buf[256] = {0};
14210 char config_file[128] = {0};
14211 int disable = 0;
developere5750452023-05-15 16:46:42 +080014212 bool set_sae = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080014213
14214 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14215 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
14216 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
14217 security->mode = wifi_security_mode_none;
14218 if (strlen(buf) != 0) {
14219 if (!strcmp(buf, "WPA-Personal"))
14220 security->mode = wifi_security_mode_wpa_personal;
14221 else if (!strcmp(buf, "WPA2-Personal"))
14222 security->mode = wifi_security_mode_wpa2_personal;
14223 else if (!strcmp(buf, "WPA-WPA2-Personal"))
14224 security->mode = wifi_security_mode_wpa_wpa2_personal;
14225 else if (!strcmp(buf, "WPA-Enterprise"))
14226 security->mode = wifi_security_mode_wpa_enterprise;
14227 else if (!strcmp(buf, "WPA2-Enterprise"))
14228 security->mode = wifi_security_mode_wpa2_enterprise;
14229 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
14230 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
14231 else if (!strcmp(buf, "WPA3-Personal"))
14232 security->mode = wifi_security_mode_wpa3_personal;
14233 else if (!strcmp(buf, "WPA3-Personal-Transition"))
14234 security->mode = wifi_security_mode_wpa3_transition;
14235 else if (!strcmp(buf, "WPA3-Enterprise"))
14236 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080014237 else if (!strcmp(buf, "OWE"))
developerd01e3e82023-04-26 19:10:38 +080014238 security->mode = wifi_security_mode_enhanced_open;
developer72fb0bb2023-01-11 09:46:29 +080014239 }
14240
14241 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
14242 if (security->mode == wifi_security_mode_none)
14243 security->encr = wifi_encryption_none;
14244 else {
14245 if (strcmp(buf, "TKIP") == 0)
14246 security->encr = wifi_encryption_tkip;
14247 else if (strcmp(buf, "CCMP") == 0)
14248 security->encr = wifi_encryption_aes;
14249 else
14250 security->encr = wifi_encryption_aes_tkip;
14251 }
14252
14253 if (security->mode != wifi_encryption_none) {
14254 memset(buf, 0, sizeof(buf));
14255 // wpa3 can use one or both configs as password, so we check sae_password first.
14256 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developere5750452023-05-15 16:46:42 +080014257 if (strlen(buf) != 0) {
14258 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
14259 security->u.key.type = wifi_security_key_type_sae;
14260 set_sae = TRUE;
14261 strncpy(security->u.key.key, buf, sizeof(buf));
14262 }
14263 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
14264 if (strlen(buf) != 0){
14265 if (set_sae == TRUE)
14266 security->u.key.type = wifi_security_key_type_psk_sae;
14267 else if (strlen(buf) == 64)
14268 security->u.key.type = wifi_security_key_type_psk;
14269 else
14270 security->u.key.type = wifi_security_key_type_pass;
14271 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer72fb0bb2023-01-11 09:46:29 +080014272 }
developer72fb0bb2023-01-11 09:46:29 +080014273 security->u.key.key[255] = '\0';
14274 }
14275
14276 memset(buf, 0, sizeof(buf));
14277 wifi_getApSecurityMFPConfig(ap_index, buf);
14278 if (strcmp(buf, "Disabled") == 0)
14279 security->mfp = wifi_mfp_cfg_disabled;
14280 else if (strcmp(buf, "Optional") == 0)
14281 security->mfp = wifi_mfp_cfg_optional;
14282 else if (strcmp(buf, "Required") == 0)
14283 security->mfp = wifi_mfp_cfg_required;
14284
14285 memset(buf, 0, sizeof(buf));
14286 security->wpa3_transition_disable = FALSE;
14287 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
14288 disable = strtol(buf, NULL, 16);
14289 if (disable != 0)
14290 security->wpa3_transition_disable = TRUE;
14291
14292 memset(buf, 0, sizeof(buf));
14293 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
14294 if (strlen(buf) == 0)
14295 security->rekey_interval = 86400;
14296 else
14297 security->rekey_interval = strtol(buf, NULL, 10);
14298
14299 memset(buf, 0, sizeof(buf));
14300 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
14301 if (strlen(buf) == 0)
14302 security->strict_rekey = 1;
14303 else
14304 security->strict_rekey = strtol(buf, NULL, 10);
14305
14306 memset(buf, 0, sizeof(buf));
14307 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
14308 if (strlen(buf) == 0)
14309 security->eapol_key_retries = 4;
14310 else
14311 security->eapol_key_retries = strtol(buf, NULL, 10);
14312
14313 memset(buf, 0, sizeof(buf));
14314 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
14315 if (strlen(buf) == 0)
14316 security->disable_pmksa_caching = FALSE;
14317 else
14318 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
14319
14320 /* TODO
14321 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
14322 */
14323 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
14324 security->eap_identity_req_timeout = 0;
14325 security->eap_identity_req_retries = 0;
14326 security->eap_req_timeout = 0;
14327 security->eap_req_retries = 0;
14328 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14329 return RETURN_OK;
14330}
14331
14332#endif /* WIFI_HAL_VERSION_3 */
14333
14334#ifdef WIFI_HAL_VERSION_3_PHASE2
14335INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
14336{
14337 char interface_name[16] = {0};
14338 char cmd[128] = {0};
14339 char buf[128] = {0};
14340 char *mac_addr = NULL;
14341 BOOL status = FALSE;
14342 size_t len = 0;
14343
14344 if(ap_index > MAX_APS)
14345 return RETURN_ERR;
14346
14347 *output_numDevices = 0;
14348 wifi_getApEnable(ap_index, &status);
14349 if (status == FALSE)
14350 return RETURN_OK;
14351
14352 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
14353 return RETURN_ERR;
14354 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
14355 _syscmd(cmd, buf, sizeof(buf));
14356
14357 mac_addr = strtok(buf, "\n");
14358 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
14359 *output_numDevices = i + 1;
14360 fprintf(stderr, "mac_addr: %s\n", mac_addr);
14361 addr_ptr = output_deviceMacAddressArray[i];
14362 mac_addr_aton(addr_ptr, mac_addr);
14363 mac_addr = strtok(NULL, "\n");
14364 }
14365
14366 return RETURN_OK;
14367}
14368#else
14369INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
14370{
14371 char interface_name[16] = {0};
14372 char cmd[128];
14373 BOOL status = false;
14374
14375 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
14376 return RETURN_ERR;
14377
14378 output_buf[0] = '\0';
14379
14380 wifi_getApEnable(ap_index,&status);
14381 if (!status)
14382 return RETURN_OK;
14383
14384 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
14385 return RETURN_ERR;
14386 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
14387 _syscmd(cmd, output_buf, output_buf_size);
developer69b61b02023-03-07 17:17:44 +080014388
developer72fb0bb2023-01-11 09:46:29 +080014389 return RETURN_OK;
14390}
14391#endif
14392
14393INT wifi_getProxyArp(INT apIndex, BOOL *enable)
14394{
14395 char output[16]={'\0'};
14396 char config_file[MAX_BUF_SIZE] = {0};
14397
14398 if (!enable)
14399 return RETURN_ERR;
14400
14401 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
14402 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
14403
14404 if (strlen(output) == 0)
14405 *enable = FALSE;
14406 else if (strncmp(output, "1", 1) == 0)
14407 *enable = TRUE;
14408 else
14409 *enable = FALSE;
14410
14411 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
14412 return RETURN_OK;
14413}
14414
14415INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
14416{
14417 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
14418 return RETURN_ERR;
14419 *output_enable=TRUE;
14420 return RETURN_OK;
14421}
14422
14423INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
14424{
14425 char cmd[128] = {0};
14426 char buf[128] = {0};
14427 char line[128] = {0};
14428 size_t len = 0;
14429 FILE *f = NULL;
14430 int index = 0;
14431 int exp = 0;
14432 int mantissa = 0;
14433 int duration = 0;
14434 int radio_index = 0;
14435 int max_radio_num = 0;
14436 uint twt_wake_interval = 0;
14437 int phyId = 0;
14438 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14439
14440 wifi_getMaxRadioNumber(&max_radio_num);
14441
14442 radio_index = ap_index % max_radio_num;
14443
14444 phyId = radio_index_to_phy(radio_index);
14445 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
14446 _syscmd(cmd, buf, sizeof(buf));
14447 *numSessionReturned = strtol(buf, NULL, 10) - 1;
14448 if (*numSessionReturned > maxNumberSessions)
14449 *numSessionReturned = maxNumberSessions;
14450 else if (*numSessionReturned < 1) {
14451 *numSessionReturned = 0;
14452 return RETURN_OK;
14453 }
14454
14455 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
14456 if ((f = popen(cmd, "r")) == NULL) {
14457 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
14458 return RETURN_ERR;
14459 }
14460
14461 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
14462 while((fgets(line, sizeof(line), f)) != NULL) {
14463 char *tmp = NULL;
14464 strcpy(buf, line);
14465 tmp = strtok(buf, " ");
14466 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
14467 tmp = strtok(NULL, " ");
14468 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
14469 tmp = strtok(NULL, " ");
14470 if (strstr(tmp, "t")) {
14471 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
14472 }
14473 if (strstr(tmp, "a")) {
14474 twtSessions[index].twtParameters.operation.announced = TRUE;
14475 }
14476 tmp = strtok(NULL, " ");
14477 exp = strtol(tmp, NULL, 10);
14478 tmp = strtok(NULL, " ");
14479 mantissa = strtol(tmp, NULL, 10);
14480 tmp = strtok(NULL, " ");
14481 duration = strtol(tmp, NULL, 10);
14482
14483 // only implicit supported
14484 twtSessions[index].twtParameters.operation.implicit = TRUE;
14485 // only individual agreement supported
14486 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
14487
14488 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
14489 twt_wake_interval = mantissa * (1 << exp);
14490 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
14491 // Overflow handling
14492 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
14493 } else {
14494 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
14495 }
14496 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
14497 index++;
14498 }
14499
14500 pclose(f);
14501 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14502 return RETURN_OK;
14503}