blob: f9c2f12e3c935f9b5eaed9b92dad9fc4293d409a [file] [log] [blame]
developer06a01d92022-09-07 16:32:39 +08001/*
2 * If not stated otherwise in this file or this component's LICENSE file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2019 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18*/
19
20/*
21* Material from the TR181 data model is Copyright (c) 2010-2017, Broadband Forum
22* Licensed under the BSD-3 license
23*/
24
25/*
26* This file includes material that is Copyright (c) 2020, Plume Design Inc.
27* Licensed under the BSD-3 license
28*/
29
30/* Code in rxStatsInfo_callback and other callbacks is credited as follows:
31Copyright (c) 2007, 2008 Johannes Berg
32Copyright (c) 2007 Andy Lutomirski
33Copyright (c) 2007 Mike Kershaw
34Copyright (c) 2008-2009 Luis R. Rodriguez
35Licensed under the ISC license
36*/
developerda1ed692022-09-13 13:59:20 +080037#define MTK_IMPL
developer06a01d92022-09-07 16:32:39 +080038#define HAL_NETLINK_IMPL
39#define _GNU_SOURCE /* needed for strcasestr */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <string.h>
45#include <fcntl.h>
46#include <stdbool.h>
47#include "wifi_hal.h"
48
49#ifdef HAL_NETLINK_IMPL
50#include <errno.h>
51#include <netlink/attr.h>
52#include <netlink/netlink.h>
53#include <netlink/genl/genl.h>
54#include <netlink/genl/family.h>
55#include <netlink/genl/ctrl.h>
56#include <linux/nl80211.h>
57#include<net/if.h>
58#endif
59
60#include <ev.h>
61#include <wpa_ctrl.h>
62#include <errno.h>
63#include <time.h>
64#define MAC_ALEN 6
65
66#define MAX_BUF_SIZE 128
67#define MAX_CMD_SIZE 1024
68#define MAX_POSSIBLE_CHANNEL_STRING_BUF 512
69#define IF_NAME_SIZE 50
70#define CONFIG_PREFIX "/nvram/hostapd"
71#define ACL_PREFIX "/tmp/hostapd-acl"
developer10adcc12022-09-13 14:39:17 +080072#define DENY_PREFIX "/tmp/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080073//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
74#define SOCK_PREFIX "/var/run/hostapd/wifi"
75#define VAP_STATUS_FILE "/tmp/vap-status"
developera3c68b92022-09-13 15:27:29 +080076#define ESSID_FILE "/tmp/essid"
developer454b9462022-09-13 15:29:16 +080077#define GUARD_INTERVAL_FILE "/tmp/guard-interval"
developera748dcf2022-09-13 15:56:48 +080078#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080079#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080080#define VLAN_FILE "/nvram/hostapd.vlan"
developer8d583982022-09-20 11:28:22 +080081#define PSK_FILE "/tmp/hostapd"
developer2de97692022-09-26 14:00:03 +080082#define CHAIN_MASK_FILE "/tmp/chain_mask"
developer54e6b9f2022-09-28 14:41:20 +080083#define AMSDU_FILE "/tmp/AMSDU"
developerf49437e2022-09-29 19:58:21 +080084#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080085#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080086
developer06a01d92022-09-07 16:32:39 +080087#define DRIVER_2GHZ "ath9k"
88#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080089#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080090
91/*
92 MAX_APS - Number of all AP available in system
93 2x Home AP
94 2x Backhaul AP
95 2x Guest AP
96 2x Secure Onboard AP
97 2x Service AP
98
99*/
100#define MAX_APS 10
101#define NUMBER_OF_RADIOS 2
102
103#ifndef AP_PREFIX
104#define AP_PREFIX "wifi"
105#endif
106
107#ifndef RADIO_PREFIX
108#define RADIO_PREFIX "wlan"
109#endif
110
111#define MAX_BUF_SIZE 128
112#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800113#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800114
115//Uncomment to enable debug logs
116//#define WIFI_DEBUG
117
118#ifdef WIFI_DEBUG
119#define wifi_dbg_printf printf
120#define WIFI_ENTRY_EXIT_DEBUG printf
121#else
122#define wifi_dbg_printf(format, args...) printf("")
123#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
124#endif
125
126#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
127#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
128#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
129#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
130#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
131#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
132#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
133#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
134#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
135#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
136
developer4fb0b922022-09-30 14:29:09 +0800137#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800138
139#define BW_FNAME "/nvram/bw_file.txt"
140
141#define PS_MAX_TID 16
142
143static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
144 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
145 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
148 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
150 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
152 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
153 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
154 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
155 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
156 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
157 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
158 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
159 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
160};
161
162typedef unsigned long long u64;
163
164/* Enum to define WiFi Bands */
165typedef enum
166{
167 band_invalid = -1,
168 band_2_4 = 0,
169 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800170 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800171} wifi_band;
172
developerdb744382022-09-13 15:34:54 +0800173typedef enum {
174 WIFI_MODE_A = 0x01,
175 WIFI_MODE_B = 0x02,
176 WIFI_MODE_G = 0x04,
177 WIFI_MODE_N = 0x08,
178 WIFI_MODE_AC = 0x10,
179 WIFI_MODE_AX = 0x20,
180} wifi_ieee80211_Mode;
181
developer06a01d92022-09-07 16:32:39 +0800182#ifdef WIFI_HAL_VERSION_3
183
184// Return number of elements in array
185#ifndef ARRAY_SIZE
186#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
187#endif /* ARRAY_SIZE */
188
189#ifndef ARRAY_AND_SIZE
190#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
191#endif /* ARRAY_AND_SIZE */
192
193#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
194
195typedef struct {
196 int32_t value;
197 int32_t param;
198 intptr_t key;
199 intptr_t data;
200} wifi_secur_list;
201
202wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
203wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
204char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800205static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800206
207static wifi_secur_list map_security[] =
208{
209 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
210 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
211 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
216 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
217 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise")
218};
219
220wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
221{
222 wifi_secur_list *item;
223 int i;
224
225 for (item = list,i = 0;i < list_sz; item++, i++) {
226 if ((int)(item->key) == key) {
227 return item;
228 }
229 }
230
231 return NULL;
232}
233
234char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
235{
236 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
237
238 if (!item) {
239 return "";
240 }
241
242 return (char *)(item->data);
243}
244
245wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
246{
247 wifi_secur_list *item;
248 int i;
249
250 for (item = list,i = 0;i < list_sz; item++, i++) {
251 if (strcmp((char *)(item->data), str) == 0) {
252 return item;
253 }
254 }
255
256 return NULL;
257}
258#endif /* WIFI_HAL_VERSION_3 */
259
260#ifdef HAL_NETLINK_IMPL
261typedef struct {
262 int id;
263 struct nl_sock* socket;
264 struct nl_cb* cb;
265} Netlink;
266
267static int mac_addr_aton(unsigned char *mac_addr, char *arg)
268{
269 unsigned int mac_addr_int[6]={};
270 sscanf(arg, "%x:%x:%x:%x:%x:%x", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
271 mac_addr[0] = mac_addr_int[0];
272 mac_addr[1] = mac_addr_int[1];
273 mac_addr[2] = mac_addr_int[2];
274 mac_addr[3] = mac_addr_int[3];
275 mac_addr[4] = mac_addr_int[4];
276 mac_addr[5] = mac_addr_int[5];
277 return 0;
278}
279
280static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
281{
282 unsigned int mac_addr_int[6]={};
283 mac_addr_int[0] = arg[0];
284 mac_addr_int[1] = arg[1];
285 mac_addr_int[2] = arg[2];
286 mac_addr_int[3] = arg[3];
287 mac_addr_int[4] = arg[4];
288 mac_addr_int[5] = arg[5];
289 snprintf(mac_addr, 20, "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
290 return;
291}
292
293static int ieee80211_frequency_to_channel(int freq)
294{
295 if (freq == 2484)
296 return 14;
297 else if (freq < 2484)
298 return (freq - 2407) / 5;
299 else if (freq >= 4910 && freq <= 4980)
300 return (freq - 4000) / 5;
301 else if (freq <= 45000)
302 return (freq - 5000) / 5;
303 else if (freq >= 58320 && freq <= 64800)
304 return (freq - 56160) / 2160;
305 else
306 return 0;
307}
308
309static int initSock80211(Netlink* nl) {
310 nl->socket = nl_socket_alloc();
311 if (!nl->socket) {
312 fprintf(stderr, "Failing to allocate the sock\n");
313 return -ENOMEM;
314 }
315
316 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
317
318 if (genl_connect(nl->socket)) {
319 fprintf(stderr, "Failed to connect\n");
320 nl_close(nl->socket);
321 nl_socket_free(nl->socket);
322 return -ENOLINK;
323 }
324
325 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
326 if (nl->id< 0) {
327 fprintf(stderr, "interface not found.\n");
328 nl_close(nl->socket);
329 nl_socket_free(nl->socket);
330 return -ENOENT;
331 }
332
333 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
334 if ((!nl->cb)) {
335 fprintf(stderr, "Failed to allocate netlink callback.\n");
336 nl_close(nl->socket);
337 nl_socket_free(nl->socket);
338 return ENOMEM;
339 }
340
341 return nl->id;
342}
343
344static int nlfree(Netlink *nl)
345{
346 nl_cb_put(nl->cb);
347 nl_close(nl->socket);
348 nl_socket_free(nl->socket);
349 return 0;
350}
351
352static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
353 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
354 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
355 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
356};
357
358static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
359};
360
361static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
362};
363
364typedef struct _wifi_channelStats_loc {
365 INT array_size;
366 INT ch_number;
367 BOOL ch_in_pool;
368 INT ch_noise;
369 BOOL ch_radar_noise;
370 INT ch_max_80211_rssi;
371 INT ch_non_80211_noise;
372 INT ch_utilization;
373 ULLONG ch_utilization_total;
374 ULLONG ch_utilization_busy;
375 ULLONG ch_utilization_busy_tx;
376 ULLONG ch_utilization_busy_rx;
377 ULLONG ch_utilization_busy_self;
378 ULLONG ch_utilization_busy_ext;
379} wifi_channelStats_t_loc;
380
381typedef struct wifi_device_info {
382 INT wifi_devIndex;
383 UCHAR wifi_devMacAddress[6];
384 CHAR wifi_devIPAddress[64];
385 BOOL wifi_devAssociatedDeviceAuthentiationState;
386 INT wifi_devSignalStrength;
387 INT wifi_devTxRate;
388 INT wifi_devRxRate;
389} wifi_device_info_t;
390
391#endif
392
393//For 5g Alias Interfaces
394static BOOL priv_flag = TRUE;
395static BOOL pub_flag = TRUE;
396static BOOL Radio_flag = TRUE;
397//wifi_setApBeaconRate(1, beaconRate);
398
developer1e5aa162022-09-13 16:06:24 +0800399BOOL multiple_set = FALSE;
400
developer06a01d92022-09-07 16:32:39 +0800401struct params
402{
403 char * name;
404 char * value;
405};
406
407static int _syscmd(char *cmd, char *retBuf, int retBufSize)
408{
409 FILE *f;
410 char *ptr = retBuf;
411 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
412
413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
414 if((f = popen(cmd, "r")) == NULL) {
415 fprintf(stderr,"\npopen %s error\n", cmd);
416 return RETURN_ERR;
417 }
418
419 while(!feof(f))
420 {
421 *ptr = 0;
422 if(bufSize>=128) {
423 bufbytes=128;
424 } else {
425 bufbytes=bufSize-1;
426 }
427
428 fgets(ptr,bufbytes,f);
429 readbytes=strlen(ptr);
430
431 if(!readbytes)
432 break;
433
434 bufSize-=readbytes;
435 ptr += readbytes;
436 }
437 cmd_ret = pclose(f);
438 retBuf[retBufSize-1]=0;
439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
440
441 return cmd_ret >> 8;
442}
443
developerc707e972022-09-13 15:38:02 +0800444wifi_band wifi_index_to_band(int apIndex)
445{
446 char cmd[128] = {0};
447 char buf[64] = {0};
448 int freq = 0;
449 wifi_band band = band_invalid;
450
451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
452 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
453 _syscmd(cmd, buf, sizeof(buf));
454 freq = strtol(buf, NULL, 10);
455 if (freq > 2401 && freq < 2495)
456 band = band_2_4;
457 else if (freq > 5160 && freq < 5915)
458 band = band_5;
459 else if (freq > 5955 && freq < 7125)
460 band = band_6;
461
462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
463 return band;
464}
465
developer06a01d92022-09-07 16:32:39 +0800466static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
467{
468 char cmd[MAX_CMD_SIZE]={'\0'};
469 char buf[MAX_BUF_SIZE]={'\0'};
470 int ret = 0;
471
472 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
473 ret = _syscmd(cmd, buf, sizeof(buf));
474 if ((ret != 0) && (strlen(buf) == 0))
475 return -1;
476 snprintf(output, output_size, "%s", buf);
477
478 return 0;
479}
480
481static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
482{
483 char cmd[MAX_CMD_SIZE]={'\0'};
484 char buf[MAX_BUF_SIZE]={'\0'};
485
486 for(int i=0;i<item_count;i++)
487 {
488 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
489 if (strlen(buf) == 0) //Insert
490 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
491 else //Update
492 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
493 if(_syscmd(cmd, buf, sizeof(buf)))
494 return -1;
495 }
496
497 return 0;
498}
499
500static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
501{
developer1e5aa162022-09-13 16:06:24 +0800502 if (multiple_set == TRUE)
503 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800504 char cmd[MAX_CMD_SIZE]="", output[32]="";
505 FILE *fp;
506 int i;
507 //NOTE RELOAD should be done in ApplySSIDSettings
508
509 for(i=0; i<item_count; i++, list++)
510 {
511 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
512 if((fp = popen(cmd, "r"))==NULL)
513 {
514 perror("popen failed");
515 return -1;
516 }
517 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
518 {
519 pclose(fp);
520 perror("fgets failed");
521 return -1;
522 }
523 pclose(fp);
524 }
525 return 0;
526}
527
528static int wifi_reloadAp(int apIndex)
529{
developer1e5aa162022-09-13 16:06:24 +0800530 if (multiple_set == TRUE)
531 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800532 char cmd[MAX_CMD_SIZE]="";
533 char buf[MAX_BUF_SIZE]="";
534
535 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
536 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
537 return RETURN_ERR;
538
539 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
540 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
541 return RETURN_ERR;
542
543 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
544 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
545 return RETURN_ERR;
546
547 return RETURN_OK;
548}
549
550
551//For Getting Current Interface Name from corresponding hostapd configuration
552void GetInterfaceName(char *interface_name, char *conf_file)
553{
554 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
555 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
556 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
557}
558
559INT File_Reading(CHAR *file, char *Value)
560{
561 FILE *fp = NULL;
562 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
563 int count = 0;
564
565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
566 fp = popen(file,"r");
567 if(fp == NULL)
568 return RETURN_ERR;
569
570 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
571 {
572 for(count=0;buf[count]!='\n';count++)
573 copy_buf[count]=buf[count];
574 copy_buf[count]='\0';
575 }
576 strcpy(Value,copy_buf);
577 pclose(fp);
578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
579
580 return RETURN_OK;
581}
582
583void wifi_RestartHostapd_2G()
584{
585 int Public2GApIndex = 4;
586
587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
588 wifi_setApEnable(Public2GApIndex, FALSE);
589 wifi_setApEnable(Public2GApIndex, TRUE);
590 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
591}
592
593void wifi_RestartHostapd_5G()
594{
595 int Public5GApIndex = 5;
596
597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
598 wifi_setApEnable(Public5GApIndex, FALSE);
599 wifi_setApEnable(Public5GApIndex, TRUE);
600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
601}
602
603void wifi_RestartPrivateWifi_2G()
604{
605 int PrivateApIndex = 0;
606
607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
608 wifi_setApEnable(PrivateApIndex, FALSE);
609 wifi_setApEnable(PrivateApIndex, TRUE);
610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
611}
612
613void wifi_RestartPrivateWifi_5G()
614{
615 int Private5GApIndex = 1;
616
617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
618 wifi_setApEnable(Private5GApIndex, FALSE);
619 wifi_setApEnable(Private5GApIndex, TRUE);
620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
621}
622
623static int writeBandWidth(int radioIndex,char *bw_value)
624{
625 char buf[MAX_BUF_SIZE];
626 char cmd[MAX_CMD_SIZE];
627
628 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
629 if(_syscmd(cmd, buf, sizeof(buf)))
630 {
631 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
632 _syscmd(cmd, buf, sizeof(buf));
633 return RETURN_OK;
634 }
635
636 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
637 _syscmd(cmd,buf,sizeof(buf));
638 return RETURN_OK;
639}
640
641static int readBandWidth(int radioIndex,char *bw_value)
642{
643 char buf[MAX_BUF_SIZE];
644 char cmd[MAX_CMD_SIZE];
645 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
646 _syscmd(cmd,buf,sizeof(buf));
647 if(NULL!=strstr(buf,"20MHz"))
648 {
649 strcpy(bw_value,"20MHz");
650 }
651 else if(NULL!=strstr(buf,"40MHz"))
652 {
653 strcpy(bw_value,"40MHz");
654 }
655 else if(NULL!=strstr(buf,"80MHz"))
656 {
657 strcpy(bw_value,"80MHz");
658 }
659 else
660 {
661 return RETURN_ERR;
662 }
663 return RETURN_OK;
664}
665
developer39a5efb2022-09-13 16:09:06 +0800666INT wifi_getMaxRadioNumber(INT *max_radio_num)
667{
668 char cmd[64] = {0};
669 char buf[4] = {0};
670
671 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
672
673 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
674 _syscmd(cmd, buf, sizeof(buf));
675 *max_radio_num = strtoul(buf, NULL, 10);
676
677 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
678
679 return RETURN_OK;
680}
681
developer5f222492022-09-13 15:21:52 +0800682// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800683INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
684{
developer5f222492022-09-13 15:21:52 +0800685 struct params params={'\0'};
686 char config_file[MAX_BUF_SIZE] = {0};
687 char buf[MAX_BUF_SIZE] = {'\0'};
688
689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
690 if (strlen (beaconRate) < 5)
691 return RETURN_ERR;
692 // Copy the numeric value
693 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
694 buf[strlen(beaconRate) - 4] = '\0';
695
696 params.name = "beacon_rate";
697 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
698 if (strncmp(buf, "5.5", 3) == 0) {
699 snprintf(buf, sizeof(buf), "55");
700 params.value = buf;
701 } else {
702 strcat(buf, "0");
703 params.value = buf;
704 }
705
706 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
707 wifi_hostapdWrite(config_file, &params, 1);
708 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
709 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
710
711 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800712}
713
714INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
715{
developer5f222492022-09-13 15:21:52 +0800716 char config_file[MAX_BUF_SIZE] = {'\0'};
717 char temp_output[MAX_BUF_SIZE] = {'\0'};
718 char buf[MAX_BUF_SIZE] = {'\0'};
719 float rate = 0;
720
721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
722 if (NULL == beaconRate)
723 return RETURN_ERR;
724
725 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
726 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
727 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
728 if(strlen(buf) > 0) {
729 rate = atof(buf)/10;
730 snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
731 } else {
732 snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
733 }
734 strncpy(beaconRate, temp_output, sizeof(temp_output));
735 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
736
737 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800738}
739
740INT wifi_setLED(INT radioIndex, BOOL enable)
741{
742 return 0;
743}
744INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
745{
746 return RETURN_OK;
747}
748/**********************************************************************************
749 *
750 * Wifi Subsystem level function prototypes
751 *
752**********************************************************************************/
753//---------------------------------------------------------------------------------------------------
754//Wifi system api
755//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
756INT wifi_getHalVersion(CHAR *output_string) //RDKB
757{
758 if(!output_string)
759 return RETURN_ERR;
760 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
761
762 return RETURN_OK;
763}
764
765
766/* wifi_factoryReset() function */
767/**
768* @description Clears internal variables to implement a factory reset of the Wi-Fi
769* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
770*
771* @param None
772*
773* @return The status of the operation.
774* @retval RETURN_OK if successful.
775* @retval RETURN_ERR if any error is detected
776*
777* @execution Synchronous
778* @sideeffect None
779*
780* @note This function must not suspend and must not invoke any blocking system
781* calls. It should probably just send a message to a driver event handler task.
782*
783*/
784INT wifi_factoryReset()
785{
786 char cmd[128];
787
788 /*delete running hostapd conf files*/
789 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
790 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
791 system(cmd);
792 system("systemctl restart hostapd.service");
793
794 return RETURN_OK;
795}
796
797/* wifi_factoryResetRadios() function */
798/**
799* @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.
800*
801* @param None
802* @return The status of the operation
803* @retval RETURN_OK if successful
804* @retval RETURN_ERR if any error is detected
805*
806* @execution Synchronous
807*
808* @sideeffect None
809*
810* @note This function must not suspend and must not invoke any blocking system
811* calls. It should probably just send a message to a driver event handler task.
812*
813*/
814INT wifi_factoryResetRadios()
815{
816 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
817 return RETURN_OK;
818
819 return RETURN_ERR;
820}
821
822
823/* wifi_factoryResetRadio() function */
824/**
825* @description Restore selected radio parameters without touching access point parameters
826*
827* @param radioIndex - Index of Wi-Fi Radio channel
828*
829* @return The status of the operation.
830* @retval RETURN_OK if successful.
831* @retval RETURN_ERR if any error is detected
832*
833* @execution Synchronous.
834* @sideeffect None.
835*
836* @note This function must not suspend and must not invoke any blocking system
837* calls. It should probably just send a message to a driver event handler task.
838*
839*/
840INT wifi_factoryResetRadio(int radioIndex) //RDKB
841{
developer5ff7f5f2022-09-13 15:12:16 +0800842 system("systemctl stop hostapd.service");
843
developer06a01d92022-09-07 16:32:39 +0800844 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
845 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800846 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800847 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800848 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800849 else
850 return RETURN_ERR;
851
developer5ff7f5f2022-09-13 15:12:16 +0800852 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800853 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
854 return RETURN_OK;
855}
856
857/* wifi_initRadio() function */
858/**
859* Description: This function call initializes the specified radio.
860* Implementation specifics may dictate the functionality since
861* different hardware implementations may have different initilization requirements.
862* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
863*
864* @return The status of the operation.
865* @retval RETURN_OK if successful.
866* @retval RETURN_ERR if any error is detected
867*
868* @execution Synchronous.
869* @sideeffect None.
870*
871* @note This function must not suspend and must not invoke any blocking system
872* calls. It should probably just send a message to a driver event handler task.
873*
874*/
875INT wifi_initRadio(INT radioIndex)
876{
877 //TODO: Initializes the wifi subsystem (for specified radio)
878 return RETURN_OK;
879}
880void macfilter_init()
881{
882 char count[4]={'\0'};
883 char buf[253]={'\0'};
884 char tmp[19]={'\0'};
885 int dev_count,block,mac_entry=0;
886 char res[4]={'\0'};
887 char acl_file_path[64] = {'\0'};
888 FILE *fp = NULL;
889 int index=0;
890 char iface[10]={'\0'};
891 char config_file[MAX_BUF_SIZE] = {0};
892
893
894 sprintf(acl_file_path,"/tmp/mac_filter.sh");
895
896 fp=fopen(acl_file_path,"w+");
897 sprintf(buf,"#!/bin/sh \n");
898 fprintf(fp,"%s\n",buf);
899
900 system("chmod 0777 /tmp/mac_filter.sh");
901
902 for(index=0;index<=1;index++)
903 {
904 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
905 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
906 sprintf(buf,"syscfg get %dcountfilter",index);
907 _syscmd(buf,count,sizeof(count));
908 mac_entry=atoi(count);
909
910 sprintf(buf,"syscfg get %dblockall",index);
911 _syscmd(buf,res,sizeof(res));
912 block = atoi(res);
913
914 //Allow only those macs mentioned in ACL
915 if(block==1)
916 {
917 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
918 fprintf(fp,"%s\n",buf);
919 for(dev_count=1;dev_count<=mac_entry;dev_count++)
920 {
921 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
922 _syscmd(buf,tmp,sizeof(tmp));
923 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
924 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
925 fprintf(fp,"%s\n",buf);
926 }
927 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
928 fprintf(fp,"%s\n",buf);
929 }
930
931 //Block all the macs mentioned in ACL
932 else if(block==2)
933 {
934 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
935 fprintf(fp,"%s\n",buf);
936
937 for(dev_count=1;dev_count<=mac_entry;dev_count++)
938 {
939 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
940 _syscmd(buf,tmp,sizeof(tmp));
941 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
942 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
943 fprintf(fp,"%s\n",buf);
944 }
945 }
946 }
947 fclose(fp);
948}
949
950// Initializes the wifi subsystem (all radios)
951INT wifi_init() //RDKB
952{
953 char interface[MAX_BUF_SIZE]={'\0'};
954 char bridge_name[MAX_BUF_SIZE]={'\0'};
955 INT len=0;
956
957 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
958 //Not intitializing macfilter for Turris-Omnia Platform for now
959 //macfilter_init();
960
961 system("/usr/sbin/iw reg set US");
962 system("systemctl start hostapd.service");
963 sleep(2);//sleep to wait for hostapd to start
964
965 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
966
967 return RETURN_OK;
968}
969
970/* wifi_reset() function */
971/**
972* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
973* Implementation specifics may dictate what is actualy reset since
974* different hardware implementations may have different requirements.
975* Parameters : None
976*
977* @return The status of the operation.
978* @retval RETURN_OK if successful.
979* @retval RETURN_ERR if any error is detected
980*
981* @execution Synchronous.
982* @sideeffect None.
983*
984* @note This function must not suspend and must not invoke any blocking system
985* calls. It should probably just send a message to a driver event handler task.
986*
987*/
988INT wifi_reset()
989{
990 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +0800991 system("systemctl stop hostapd.service");
992 sleep(2);
993 system("systemctl start hostapd.service");
994 sleep(5);
developer06a01d92022-09-07 16:32:39 +0800995 return RETURN_OK;
996}
997
998/* wifi_down() function */
999/**
1000* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1001* Implementation specifics may dictate some functionality since
1002* different hardware implementations may have different requirements.
1003*
1004* @param None
1005*
1006* @return The status of the operation
1007* @retval RETURN_OK if successful
1008* @retval RETURN_ERR if any error is detected
1009*
1010* @execution Synchronous
1011* @sideeffect None
1012*
1013* @note This function must not suspend and must not invoke any blocking system
1014* calls. It should probably just send a message to a driver event handler task.
1015*
1016*/
1017INT wifi_down()
1018{
1019 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001020 system("systemctl stop hostapd.service");
1021 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001022 return RETURN_OK;
1023}
1024
1025
1026/* wifi_createInitialConfigFiles() function */
1027/**
1028* @description This function creates wifi configuration files. The format
1029* and content of these files are implementation dependent. This function call is
1030* used to trigger this task if necessary. Some implementations may not need this
1031* function. If an implementation does not need to create config files the function call can
1032* do nothing and return RETURN_OK.
1033*
1034* @param None
1035*
1036* @return The status of the operation
1037* @retval RETURN_OK if successful
1038* @retval RETURN_ERR if any error is detected
1039*
1040* @execution Synchronous
1041* @sideeffect None
1042*
1043* @note This function must not suspend and must not invoke any blocking system
1044* calls. It should probably just send a message to a driver event handler task.
1045*
1046*/
1047INT wifi_createInitialConfigFiles()
1048{
1049 //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)
1050 return RETURN_OK;
1051}
1052
1053// outputs the country code to a max 64 character string
1054INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1055{
developer7543b3b2022-09-13 13:47:17 +08001056 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1057 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001058 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001059
1060 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1061 _syscmd(cmd, buf, sizeof(buf));
1062 if(strlen(buf) > 0)
1063 snprintf(output_string, 64, "%s", buf);
1064 else
1065 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001066
1067 return RETURN_OK;
1068}
1069
1070INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1071{
1072 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001073 char str[MAX_BUF_SIZE]={'\0'};
1074 char cmd[MAX_CMD_SIZE]={'\0'};
1075 struct params params;
1076 char config_file[MAX_BUF_SIZE] = {0};
1077
1078 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1079 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1080 return RETURN_ERR;
1081
1082 params.name = "country_code";
1083 params.value = CountryCode;
1084 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1085 int ret = wifi_hostapdWrite(config_file, &params, 1);
1086 if (ret) {
1087 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1088 ,__func__, ret);
1089 }
1090
1091 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1092 if (ret) {
1093 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1094 ,__func__, ret);
1095 }
1096 wifi_reloadAp(radioIndex);
1097 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1098
developer06a01d92022-09-07 16:32:39 +08001099 return RETURN_OK;
1100}
1101
developera748dcf2022-09-13 15:56:48 +08001102INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1103{
1104 char channel_util_file[64] = {0};
1105 char cmd[128] = {0};
1106 char buf[128] = {0};
1107 char line[128] = {0};
1108 char *param = NULL, *value = NULL;
1109 int read = 0;
1110 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1111 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1112 size_t len = 0;
1113 FILE *f = NULL;
1114
1115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1116
1117 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1118 _syscmd(cmd, buf, sizeof(buf));
1119 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1120
1121 memset(cmd, 0, sizeof(cmd));
1122 memset(buf, 0, sizeof(buf));
1123 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1124 if ((f = popen(cmd, "r")) == NULL) {
1125 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1126 return RETURN_ERR;
1127 }
1128
1129 read = getline(&line, &len, f);
1130 while (read != -1) {
1131 param = strtok(line, ":\t");
1132 value = strtok(NULL, " ");
1133 if(strstr(param, "frequency") != NULL) {
1134 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1135 }
1136 if(strstr(param, "noise") != NULL) {
1137 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1138 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1139 }
1140 if(strstr(param, "channel active time") != NULL) {
1141 ActiveTime = strtol(value, NULL, 10);
1142 }
1143 if(strstr(param, "channel busy time") != NULL) {
1144 BusyTime = strtol(value, NULL, 10);
1145 }
1146 if(strstr(param, "channel transmit time") != NULL) {
1147 TransmitTime = strtol(value, NULL, 10);
1148 }
1149 read = getline(&line, &len, f);
1150 }
1151 pclose(f);
1152
1153 // The file should store the last active, busy and transmit time
1154 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1155 f = fopen(channel_util_file, "r");
1156 if (f != NULL) {
1157 read = getline(&line, &len, f);
1158 preActiveTime = strtol(line, NULL, 10);
1159 read = getline(&line, &len, f);
1160 preBusyTime = strtol(line, NULL, 10);
1161 read = getline(&line, &len, f);
1162 preTransmitTime = strtol(line, NULL, 10);
1163 fclose(f);
1164 }
1165
1166 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1167 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1168
1169 f = fopen(channel_util_file, "w");
1170 if (f != NULL) {
1171 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1172 fclose(f);
1173 }
1174 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1175 return RETURN_OK;
1176}
1177
developer06a01d92022-09-07 16:32:39 +08001178/**********************************************************************************
1179 *
1180 * Wifi radio level function prototypes
1181 *
1182**********************************************************************************/
1183
1184//Get the total number of radios in this wifi subsystem
1185INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1186{
1187 if (NULL == output)
1188 return RETURN_ERR;
1189 *output = 2;
1190
1191 return RETURN_OK;
1192}
1193
1194//Get the total number of SSID entries in this wifi subsystem
1195INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1196{
1197 if (NULL == output)
1198 return RETURN_ERR;
1199 *output = MAX_APS;
1200
1201 return RETURN_OK;
1202}
1203
1204//Get the Radio enable config parameter
1205INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1206{
1207 char interface_path[MAX_CMD_SIZE] = {0};
1208 FILE *fp = NULL;
1209
1210 if (NULL == output_bool)
1211 return RETURN_ERR;
1212
1213 *output_bool = FALSE;
1214 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1215 return RETURN_ERR;
1216
1217 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1218 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001219 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001220 {
developercf48e482022-09-13 14:49:50 +08001221 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001222 }
1223 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001224 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1225 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1226 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001227
developercf48e482022-09-13 14:49:50 +08001228 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1229 *output_bool = TRUE;
1230 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001231 return RETURN_OK;
1232}
1233
1234INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1235{
1236 char cmd[MAX_CMD_SIZE] = {0};
1237 char buf[MAX_CMD_SIZE] = {0};
1238 int apIndex, ret;
1239 FILE *fp = NULL;
1240
1241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1242 if(enable==FALSE)
1243 {
1244 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1245 {
1246 //Detaching %s%d from hostapd daemon
1247 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1248 _syscmd(cmd, buf, sizeof(buf));
1249 if(strncmp(buf, "OK", 2))
1250 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1251 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1252 _syscmd(cmd, buf, sizeof(buf));
1253 }
developer456aa3e2022-09-13 14:27:36 +08001254 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001255 _syscmd(cmd, buf, sizeof(buf));
1256 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001257 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001258 }
1259 else
1260 {
developer456aa3e2022-09-13 14:27:36 +08001261 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001262 _syscmd(cmd, buf, sizeof(buf));
1263 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001264 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001265 sleep(1);
1266 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1267 {
1268 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1269 fp = fopen(cmd, "r");
1270 if(!fp)
1271 {
1272 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1273 _syscmd(cmd, buf, sizeof(buf));
1274 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1275 _syscmd(cmd, buf, sizeof(buf));
1276 }
1277 if(fp)
1278 fclose(fp);
1279 }
1280 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1281 {
1282 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1283 ret = _syscmd(cmd, buf, sizeof(buf));
1284 if ( ret == RETURN_ERR)
1285 {
1286 fprintf(stderr, "VAP interface creation failed\n");
1287 continue;
1288 }
1289 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1290 _syscmd(cmd, buf, sizeof(buf));
1291 if(*buf == '1')
1292 {
1293 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1294 radioIndex, apIndex);
1295 _syscmd(cmd, buf, sizeof(buf));
1296 if(strncmp(buf, "OK", 2))
1297 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1298 }
1299 }
1300 }
1301
1302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1303 return RETURN_OK;
1304}
1305
1306//Get the Radio enable status
1307INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1308{
1309 if (NULL == output_bool)
1310 return RETURN_ERR;
1311
1312 return wifi_getRadioEnable(radioIndex, output_bool);
1313}
1314
1315//Get the Radio Interface name from platform, eg "wlan0"
1316INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1317{
1318 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1319 return RETURN_ERR;
1320 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1321
1322 return RETURN_OK;
1323}
1324
1325//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1326//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.
1327INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1328{
developerbcc556a2022-09-22 20:02:45 +08001329 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1330 // For max bit rate, we should always choose the best MCS
1331 char mode[64] = {0};
1332 char channel_bandwidth_str[16] = {0};
1333 char *tmp = NULL;
1334 UINT mode_map = 0;
1335 UINT num_subcarrier = 0;
1336 UINT code_bits = 0;
1337 float code_rate = 0; // use max code rate
1338 int NSS = 0;
1339 UINT Symbol_duration = 0;
1340 UINT GI_duration = 0;
1341 wifi_band band = band_invalid;
1342 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1343 BOOL enable = FALSE;
1344 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001345
1346 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1347 if (NULL == output_string)
1348 return RETURN_ERR;
1349
developerbcc556a2022-09-22 20:02:45 +08001350 wifi_getRadioEnable(radioIndex, &enable);
1351 if (enable == FALSE) {
1352 snprintf(output_string, 64, "0 Mb/s");
1353 return RETURN_OK;
1354 }
1355
1356 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1357 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1358 return RETURN_ERR;
1359 }
1360
1361 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1362 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1363 return RETURN_ERR;
1364 }
1365
1366 if (gi == wifi_guard_interval_3200)
1367 GI_duration = 32;
1368 else if (gi == wifi_guard_interval_1600)
1369 GI_duration = 16;
1370 else if (gi == wifi_guard_interval_800)
1371 GI_duration = 8;
1372 else // auto, 400
1373 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001374
developerbcc556a2022-09-22 20:02:45 +08001375 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1376 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1377 return RETURN_ERR;
1378 }
1379
1380 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1381 strcpy(channel_bandwidth_str, "160");
1382
1383 if (mode_map & WIFI_MODE_AX) {
1384 if (strstr(channel_bandwidth_str, "160") != NULL)
1385 num_subcarrier = 1960;
1386 else if (strstr(channel_bandwidth_str, "80") != NULL)
1387 num_subcarrier = 980;
1388 else if (strstr(channel_bandwidth_str, "40") != NULL)
1389 num_subcarrier = 468;
1390 else if (strstr(channel_bandwidth_str, "20") != NULL)
1391 num_subcarrier = 234;
1392 code_bits = 10;
1393 code_rate = (float)5/6;
1394 Symbol_duration = 128;
1395 } else if (mode_map & WIFI_MODE_AC) {
1396 if (strstr(channel_bandwidth_str, "160") != NULL)
1397 num_subcarrier = 468;
1398 else if (strstr(channel_bandwidth_str, "80") != NULL)
1399 num_subcarrier = 234;
1400 else if (strstr(channel_bandwidth_str, "40") != NULL)
1401 num_subcarrier = 108;
1402 else if (strstr(channel_bandwidth_str, "20") != NULL)
1403 num_subcarrier = 52;
1404 code_bits = 8;
1405 code_rate = (float)5/6;
1406 Symbol_duration = 32;
1407 } else if (mode_map & WIFI_MODE_N) {
1408 if (strstr(channel_bandwidth_str, "160") != NULL)
1409 num_subcarrier = 468;
1410 else if (strstr(channel_bandwidth_str, "80") != NULL)
1411 num_subcarrier = 234;
1412 else if (strstr(channel_bandwidth_str, "40") != NULL)
1413 num_subcarrier = 108;
1414 else if (strstr(channel_bandwidth_str, "20") != NULL)
1415 num_subcarrier = 52;
1416 code_bits = 6;
1417 code_rate = (float)3/4;
1418 Symbol_duration = 32;
1419 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1420 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1421 snprintf(output_string, 64, "65 Mb/s");
1422 return RETURN_OK;
1423 } else {
1424 snprintf(output_string, 64, "0 Mb/s");
1425 return RETURN_OK;
1426 }
developer06a01d92022-09-07 16:32:39 +08001427
developerbcc556a2022-09-22 20:02:45 +08001428 // Spatial streams
1429 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1430 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1431 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001432 }
developerbcc556a2022-09-22 20:02:45 +08001433
1434 // multiple 10 is to align duration unit (0.1 us)
1435 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1436 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1437
developer06a01d92022-09-07 16:32:39 +08001438 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1439
1440 return RETURN_OK;
1441}
1442#if 0
1443INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1444{
1445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1446 char cmd[64];
1447 char buf[1024];
1448 int apIndex;
1449
1450 if (NULL == output_string)
1451 return RETURN_ERR;
1452
1453 apIndex=(radioIndex==0)?0:1;
1454
1455 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1456 _syscmd(cmd,buf, sizeof(buf));
1457
1458 snprintf(output_string, 64, "%s", buf);
1459 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1460 return RETURN_OK;
1461}
1462#endif
1463
1464
1465//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1466//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.
1467INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1468{
developer963da0c2022-09-13 15:58:27 +08001469 wifi_band band = band_invalid;
1470
developer06a01d92022-09-07 16:32:39 +08001471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1472 if (NULL == output_string)
1473 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001474
1475 band = wifi_index_to_band(radioIndex);
1476
1477 memset(output_string, 0, 10);
1478 if (band == band_2_4)
1479 strcpy(output_string, "2.4GHz");
1480 else if (band == band_5)
1481 strcpy(output_string, "5GHz");
1482 else if (band == band_6)
1483 strcpy(output_string, "6GHz");
1484 else
1485 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1487
1488 return RETURN_OK;
1489#if 0
1490 char buf[MAX_BUF_SIZE]={'\0'};
1491 char str[MAX_BUF_SIZE]={'\0'};
1492 char cmd[MAX_CMD_SIZE]={'\0'};
1493 char *ch=NULL;
1494 char *ch2=NULL;
1495
1496 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1497 if (NULL == output_string)
1498 return RETURN_ERR;
1499
1500
1501 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1502
1503 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1504 {
1505 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1506 return RETURN_ERR;
1507 }
1508 ch=strchr(buf,'\n');
1509 *ch='\0';
1510 ch=strchr(buf,'=');
1511 if(ch==NULL)
1512 return RETURN_ERR;
1513
1514
1515 ch++;
1516
1517 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1518 strcpy(buf,"0");
1519 if(strlen(ch) == 1)
1520 ch=strcat(buf,ch);
1521
1522
1523 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1524
1525 if(_syscmd(cmd,str,64) == RETURN_ERR)
1526 {
1527 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1528 return RETURN_ERR;
1529 }
1530
1531
1532 ch2=strchr(str,'\n');
1533 //replace \n with \0
1534 *ch2='\0';
1535 ch2=strchr(str,'=');
1536 if(ch2==NULL)
1537 {
1538 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1539 return RETURN_ERR;
1540 }
1541 else
1542 wifi_dbg_printf("%s",ch2+1);
1543
1544
1545 ch2++;
1546
1547
1548 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1549
1550 memset(buf,'\0',sizeof(buf));
1551 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1552 {
1553 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1554 return RETURN_ERR;
1555 }
1556 if (strstr(buf,"2.4") != NULL )
1557 strcpy(output_string,"2.4GHz");
1558 else if(strstr(buf,"5.") != NULL )
1559 strcpy(output_string,"5GHz");
1560 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1561
1562 return RETURN_OK;
1563#endif
1564}
1565
1566//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1567//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.
1568INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1569{
1570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1571 if (NULL == output_string)
1572 return RETURN_ERR;
1573 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1575
1576 return RETURN_OK;
1577#if 0
1578 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1579 char buf[MAX_BUF_SIZE]={'\0'};
1580 char str[MAX_BUF_SIZE]={'\0'};
1581 char cmd[MAX_CMD_SIZE]={'\0'};
1582 char *ch=NULL;
1583 char *ch2=NULL;
1584 char ch1[5]="0";
1585
1586 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1587
1588 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1589 {
1590 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1591 return RETURN_ERR;
1592 }
1593
1594 ch=strchr(buf,'\n');
1595 *ch='\0';
1596 ch=strchr(buf,'=');
1597 if(ch==NULL)
1598 return RETURN_ERR;
1599 ch++;
1600
1601 if(strlen(ch)==1)
1602 {
1603 strcat(ch1,ch);
1604
1605 }
1606 else
1607 {
1608 strcpy(ch1,ch);
1609 }
1610
1611
1612
1613 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1614 if(_syscmd(cmd,str,64) == RETURN_ERR)
1615 {
1616 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1617 return RETURN_ERR;
1618 }
1619
1620
1621 ch2=strchr(str,'\n');
1622 //replace \n with \0
1623 *ch2='\0';
1624 ch2=strchr(str,'=');
1625 if(ch2==NULL)
1626 {
1627 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1628 return RETURN_ERR;
1629 }
1630 else
1631 wifi_dbg_printf("%s",ch2+1);
1632 ch2++;
1633
1634
1635 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1636 memset(buf,'\0',sizeof(buf));
1637 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1638 {
1639 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1640 return RETURN_ERR;
1641 }
1642
1643
1644 if(strstr(buf,"2.4")!=NULL)
1645 {
1646 strcpy(output_string,"2.4GHz");
1647 }
1648 if(strstr(buf,"5.")!=NULL)
1649 {
1650 strcpy(output_string,"5GHz");
1651 }
1652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1653 return RETURN_OK;
1654#endif
1655}
1656
1657//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1658//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.
1659INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1660{
developer963da0c2022-09-13 15:58:27 +08001661 char cmd[128]={0};
1662 char buf[128]={0};
1663 char temp_output[128] = {0};
1664 wifi_band band;
1665
1666 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001667 if (NULL == output_string)
1668 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001669
1670 band = wifi_index_to_band(radioIndex);
1671 if (band == band_2_4) {
1672 strcat(temp_output, "b,g,");
1673 } else if (band == band_5) {
1674 strcat(temp_output, "a,");
1675 }
1676
1677 // ht capabilities
1678 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", radioIndex);
1679 _syscmd(cmd, buf, sizeof(buf));
1680 if (strncmp(buf, "0x00", 4) != 0) {
1681 strcat(temp_output, "n,");
1682 }
developer06a01d92022-09-07 16:32:39 +08001683
developer963da0c2022-09-13 15:58:27 +08001684 // vht capabilities
1685 if (band == band_5) {
1686 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1687 _syscmd(cmd, buf, sizeof(buf));
1688 if (strncmp(buf, "0x00000000", 10) != 0) {
1689 strcat(temp_output, "ac,");
1690 }
1691 }
1692
1693 // he capabilities
1694 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'", radioIndex);
1695 _syscmd(cmd, buf, sizeof(buf));
1696 if (strncmp (buf, "0x0000", 6) != 0) {
1697 strcat(temp_output, "ax,");
1698 }
1699
1700 // Remove the last comma
1701 if (strlen(temp_output) != 0)
1702 temp_output[strlen(temp_output)-1] = '\0';
1703 strncpy(output_string, temp_output, strlen(temp_output));
1704 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001705 return RETURN_OK;
1706}
1707
1708//Get the radio operating mode, and pure mode flag. eg: "ac"
1709//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.
1710INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1711{
1712 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1713 if (NULL == output_string)
1714 return RETURN_ERR;
1715
1716 if (radioIndex == 0) {
1717 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1718 *gOnly = FALSE;
1719 *nOnly = TRUE;
1720 *acOnly = FALSE;
1721 } else {
1722 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1723 *gOnly = FALSE;
1724 *nOnly = FALSE;
1725 *acOnly = FALSE;
1726 }
1727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1728
1729 return RETURN_OK;
1730#if 0
1731 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1732 char buf[64] = {0};
1733 char config_file[MAX_BUF_SIZE] = {0};
1734
1735 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1736 return RETURN_ERR;
1737
1738 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1739 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1740
1741 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1742 if (strlen(buf) == 0)
1743 {
1744 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1745 return RETURN_ERR;
1746 }
1747 if(strcmp(buf,"g")==0)
1748 {
1749 wifi_dbg_printf("\nG\n");
1750 *gOnly=TRUE;
1751 *nOnly=FALSE;
1752 *acOnly=FALSE;
1753 }
1754 else if(strcmp(buf,"n")==0)
1755 {
1756 wifi_dbg_printf("\nN\n");
1757 *gOnly=FALSE;
1758 *nOnly=TRUE;
1759 *acOnly=FALSE;
1760 }
1761 else if(strcmp(buf,"ac")==0)
1762 {
1763 wifi_dbg_printf("\nac\n");
1764 *gOnly=FALSE;
1765 *nOnly=FALSE;
1766 *acOnly=TRUE;
1767 }
1768 /* hostapd-5G.conf has "a" as hw_mode */
1769 else if(strcmp(buf,"a")==0)
1770 {
1771 wifi_dbg_printf("\na\n");
1772 *gOnly=FALSE;
1773 *nOnly=FALSE;
1774 *acOnly=FALSE;
1775 }
1776 else
1777 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1778
1779 //for a,n mode
1780 if(radioIndex == 1)
1781 {
1782 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1783 if(strcmp(buf,"1")==0)
1784 {
1785 strncpy(output_string, "n", 1);
1786 *nOnly=FALSE;
1787 }
1788 }
1789
1790 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1791 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1792 return RETURN_OK;
1793#endif
1794}
1795
developerdb744382022-09-13 15:34:54 +08001796INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1797{
1798 char cmd[128] = {0};
1799 char buf[64] = {0};
1800 char config_file[64] = {0};
1801 wifi_band band;
1802
1803 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1804 if(NULL == output_string || NULL == pureMode)
1805 return RETURN_ERR;
1806
1807 // grep all of the ieee80211 protocol config set to 1
1808 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1809 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1810 _syscmd(cmd, buf, sizeof(buf));
1811
1812 band = wifi_index_to_band(radioIndex);
1813 // puremode is a bit map
1814 *pureMode = 0;
1815 if (band == band_2_4) {
1816 strcat(output_string, "b,g");
1817 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1818 if (strstr(buf, "n") != NULL) {
1819 strcat(output_string, ",n");
1820 *pureMode |= WIFI_MODE_N;
1821 }
1822 if (strstr(buf, "ax") != NULL) {
1823 strcat(output_string, ",ax");
1824 *pureMode |= WIFI_MODE_AX;
1825 }
1826 } else if (band == band_5) {
1827 strcat(output_string, "a");
1828 *pureMode |= WIFI_MODE_A;
1829 if (strstr(buf, "n") != NULL) {
1830 strcat(output_string, ",n");
1831 *pureMode |= WIFI_MODE_N;
1832 }
1833 if (strstr(buf, "ac") != NULL) {
1834 strcat(output_string, ",ac");
1835 *pureMode |= WIFI_MODE_AC;
1836 }
1837 if (strstr(buf, "ax") != NULL) {
1838 strcat(output_string, ",ax");
1839 *pureMode |= WIFI_MODE_AX;
1840 }
1841 } else if (band == band_6) {
1842 if (strstr(buf, "ax") != NULL) {
1843 strcat(output_string, "ax");
1844 *pureMode |= WIFI_MODE_AX;
1845 }
1846 }
1847
1848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1849 return RETURN_OK;
1850}
1851
1852// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001853INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1854{
1855 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1856 if (strcmp (channelMode,"11A") == 0)
1857 {
1858 writeBandWidth(radioIndex,"20MHz");
1859 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1860 printf("\nChannel Mode is 802.11a (5GHz)\n");
1861 }
1862 else if (strcmp (channelMode,"11NAHT20") == 0)
1863 {
1864 writeBandWidth(radioIndex,"20MHz");
1865 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1866 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1867 }
1868 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1869 {
1870 writeBandWidth(radioIndex,"40MHz");
1871 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1872 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1873 }
1874 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1875 {
1876 writeBandWidth(radioIndex,"40MHz");
1877 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1878 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1879 }
1880 else if (strcmp (channelMode,"11ACVHT20") == 0)
1881 {
1882 writeBandWidth(radioIndex,"20MHz");
1883 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1884 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1885 }
1886 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1887 {
1888 writeBandWidth(radioIndex,"40MHz");
1889 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1890 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1891 }
1892 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1893 {
1894 writeBandWidth(radioIndex,"40MHz");
1895 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1896 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1897 }
1898 else if (strcmp (channelMode,"11ACVHT80") == 0)
1899 {
1900 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1901 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1902 }
1903 else if (strcmp (channelMode,"11ACVHT160") == 0)
1904 {
1905 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1906 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1907 }
1908 else if (strcmp (channelMode,"11B") == 0)
1909 {
1910 writeBandWidth(radioIndex,"20MHz");
1911 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1912 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1913 }
1914 else if (strcmp (channelMode,"11G") == 0)
1915 {
1916 writeBandWidth(radioIndex,"20MHz");
1917 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1918 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1919 }
1920 else if (strcmp (channelMode,"11NGHT20") == 0)
1921 {
1922 writeBandWidth(radioIndex,"20MHz");
1923 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1924 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1925 }
1926 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1927 {
1928 writeBandWidth(radioIndex,"40MHz");
1929 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1930 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1931 }
1932 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1933 {
1934 writeBandWidth(radioIndex,"40MHz");
1935 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1936 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1937 }
1938 else
1939 {
1940 return RETURN_ERR;
1941 }
1942 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1943
1944 return RETURN_OK;
1945}
1946
developerdb744382022-09-13 15:34:54 +08001947// Set the radio operating mode, and pure mode flag.
1948INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1949{
1950 int num_hostapd_support_mode = 3; // n, ac, ax
1951 struct params list[num_hostapd_support_mode];
1952 char config_file[64] = {0};
1953 char bandwidth[16] = {0};
1954 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08001955
developerdb744382022-09-13 15:34:54 +08001956
1957 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1958 // Set radio mode
1959 list[0].name = "ieee80211n";
1960 list[1].name = "ieee80211ac";
1961 list[2].name = "ieee80211ax";
1962 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1963
1964 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08001965 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08001966 list[0].value = "1";
1967 else
1968 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08001969 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08001970 list[1].value = "1";
1971 else
1972 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08001973 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08001974 list[2].value = "1";
1975 else
1976 list[2].value = "0";
1977 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
1978
1979 if (channelMode == NULL || strlen(channelMode) == 0)
1980 return RETURN_OK;
1981 // Set bandwidth
1982 if (strstr(channelMode, "40") != NULL)
1983 strcpy(bandwidth, "40MHz");
1984 else if (strstr(channelMode, "80") != NULL)
1985 strcpy(bandwidth, "80MHz");
1986 else if (strstr(channelMode, "160") != NULL)
1987 strcpy(bandwidth, "160MHz");
1988 else // 11A, 11B, 11G....
1989 strcpy(bandwidth, "20MHz");
1990
1991 writeBandWidth(radioIndex, bandwidth);
1992 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
1993
1994 wifi_reloadAp(radioIndex);
1995 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1996
1997 return RETURN_OK;
1998}
1999
developer1d12ebf2022-10-04 15:13:38 +08002000INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2001
2002 char config_file[64] = {0};
2003 struct params params = {0};
2004 wifi_band band = band_invalid;
2005
2006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2007
2008 band = wifi_index_to_band(radioIndex);
2009 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 || band != band_6))
2010 return RETURN_ERR;
2011 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2012 return RETURN_ERR;
2013
2014 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2015 params.name = "hw_mode";
2016 params.value = hw_mode;
2017 wifi_hostapdWrite(config_file, &params, 1);
2018 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2019
2020 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2021 return RETURN_OK;
2022}
2023
developer06a01d92022-09-07 16:32:39 +08002024//Get the list of supported channel. eg: "1-11"
2025//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.
2026INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2027{
developer6318ed52022-09-13 15:17:58 +08002028 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002029 if (NULL == output_string)
2030 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002031 char cmd[256] = {0};
2032 char buf[128] = {0};
2033 BOOL dfs_enable = false;
2034 // Parse possible channel number and separate them with commas.
2035 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer76989232022-10-04 14:13:19 +08002036 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002037 if (dfs_enable)
developer76989232022-10-04 14:13:19 +08002038 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/.$//'", radioIndex);
developer6318ed52022-09-13 15:17:58 +08002039 else
developer76989232022-10-04 14:13:19 +08002040 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/.$//'", radioIndex);
developer6318ed52022-09-13 15:17:58 +08002041
2042 _syscmd(cmd,buf,sizeof(buf));
2043 strncpy(output_string, buf, sizeof(buf));
2044
2045 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2046 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002047}
2048
2049//Get the list for used channel. eg: "1,6,9,11"
2050//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.
2051INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2052{
2053 if (NULL == output_string)
2054 return RETURN_ERR;
2055 snprintf(output_string, 256, (radioIndex == 0)?"1,6,11":"36,40");
2056#if 0
2057 char IFName[50] ={0};
2058 char buf[MAX_BUF_SIZE] = {0};
2059 char cmd[MAX_CMD_SIZE] = {0};
2060 if (NULL == output_string)
2061 return RETURN_ERR;
2062
2063 // snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2064 if(radioIndex == 0)
2065 {
2066 GetInterfaceName(IFName, "/nvram/hostapd0.conf");
2067 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 2'\\.' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | sed 's/^0//g' | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2068 }
2069 else if(radioIndex == 1)
2070 {
2071 GetInterfaceName(IFName, "/nvram/hostapd1.conf");
2072 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 5'\\.[1-9]' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 |tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2073 }
2074 _syscmd(cmd,buf, sizeof(buf));
2075 if(strlen(buf) > 0)
2076 strcpy(output_string,buf);
2077 else
2078 strcpy(output_string,"0");
2079#endif
2080 return RETURN_OK;
2081}
2082
2083//Get the running channel number
2084INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2085{
developerda1ed692022-09-13 13:59:20 +08002086#ifdef MTK_IMPL
2087 if(!wifi_getApChannel(radioIndex, output_ulong))
2088 return RETURN_OK;
2089 else
2090 return RETURN_ERR;
2091#else
developer06a01d92022-09-07 16:32:39 +08002092 char cmd[1024] = {0}, buf[5] = {0};
2093
2094 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2095 if (NULL == output_ulong)
2096 return RETURN_ERR;
2097
2098 snprintf(cmd, sizeof(cmd),
2099 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2100 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2101 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2102 _syscmd(cmd, buf, sizeof(buf));
2103
2104 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2105 if (*output_ulong <= 0) {
2106 *output_ulong = 0;
2107 return RETURN_ERR;
2108 }
2109
2110 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2111 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002112#endif
developer06a01d92022-09-07 16:32:39 +08002113}
2114
2115
2116INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2117{
2118 char cmd[1024] = {0}, buf[5] = {0};
2119 char interface_name[50] = {0};
2120
2121 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2122 if (NULL == output_ulong)
2123 return RETURN_ERR;
2124
2125 wifi_getApName(apIndex,interface_name);
2126 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2127 _syscmd(cmd,buf,sizeof(buf));
2128 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2129 if (*output_ulong == 0) {
2130 return RETURN_ERR;
2131 }
2132
2133 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2134 return RETURN_OK;
2135}
2136
2137//Storing the previous channel value
2138INT wifi_storeprevchanval(INT radioIndex)
2139{
2140 char buf[256] = {0};
2141 char output[4]={'\0'};
2142 char config_file[MAX_BUF_SIZE] = {0};
2143 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2144 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2145 if(radioIndex == 0)
2146 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2147 else if(radioIndex == 1)
2148 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2149 system(buf);
2150 Radio_flag = FALSE;
2151 return RETURN_OK;
2152}
2153
2154//Set the running channel number
2155INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2156{
developer76989232022-10-04 14:13:19 +08002157 // We only write hostapd config here
2158 char str_channel[8]={0};
2159 char *list_channel;
2160 char config_file[128] = {0};
2161 char possible_channels[256] = {0};
2162 int max_radio_num = 0;
2163 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002164
developer76989232022-10-04 14:13:19 +08002165 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002166
developer76989232022-10-04 14:13:19 +08002167 // Check valid
2168 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002169
developer76989232022-10-04 14:13:19 +08002170 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2171 list_channel = strtok(possible_channels, ",");
2172 while(true)
developer06a01d92022-09-07 16:32:39 +08002173 {
developer76989232022-10-04 14:13:19 +08002174 if(list_channel == NULL) { // input not in the list
2175 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2176 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002177 }
developer76989232022-10-04 14:13:19 +08002178 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2179 break;
2180 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002181 }
2182
developer76989232022-10-04 14:13:19 +08002183 list.name = "channel";
2184 list.value = str_channel;
2185 wifi_getMaxRadioNumber(&max_radio_num);
2186 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002187 {
developer76989232022-10-04 14:13:19 +08002188 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2189 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002190 }
2191
developer76989232022-10-04 14:13:19 +08002192 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002193 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002194}
developer06a01d92022-09-07 16:32:39 +08002195
2196INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2197{
developer76989232022-10-04 14:13:19 +08002198 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002199 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002200 char config_file[64];
2201 int max_num_radios = 0;
2202 wifi_band band = band_invalid;
2203
2204 band = wifi_index_to_band(radioIndex);
2205 if (band == band_2_4)
2206 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002207
developer06a01d92022-09-07 16:32:39 +08002208 snprintf(str_idx, sizeof(str_idx), "%d", channel);
developer76989232022-10-04 14:13:19 +08002209 list[0].name = "vht_oper_centr_freq_seg0_idx";
2210 list[0].value = str_idx;
2211 list[1].name = "he_oper_centr_freq_seg0_idx";
2212 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002213
developer76989232022-10-04 14:13:19 +08002214 wifi_getMaxRadioNumber(&max_num_radios);
2215 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002216 {
developer76989232022-10-04 14:13:19 +08002217 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2218 if (band == band_6)
2219 wifi_hostapdWrite(config_file, &list[1], 1);
2220 else
2221 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002222 }
2223
2224 return RETURN_OK;
2225}
2226
2227//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2228//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2229INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2230{
2231 //Set to wifi config only. Wait for wifi reset to apply.
2232 char buf[256] = {0};
2233 char str_channel[256] = {0};
2234 int count = 0;
2235 ULONG Value = 0;
2236 FILE *fp = NULL;
2237 if(enable == TRUE)
2238 {
2239 if(radioIndex == 0)
2240 {
2241 // _syscmd("cat /var/prevchanval2G_AutoChannelEnable", buf, sizeof(buf));
2242 fp = fopen("/var/prevchanval2G_AutoChannelEnable","r");
2243 }
2244 else if(radioIndex == 1)
2245 {
2246 // _syscmd("cat /var/prevchanval5G_AutoChannelEnable", buf, sizeof(buf));
2247 fp = fopen("/var/prevchanval5G_AutoChannelEnable","r");
2248 }
2249 if(fp == NULL) //first time boot-up
2250 {
2251 if(radioIndex == 0)
2252 Value = 6;
2253 else if(radioIndex == 1)
2254 Value = 36;
2255 }
2256 else
2257 {
2258 if(fgets(buf,sizeof(buf),fp) != NULL)
2259 {
2260 for(count = 0;buf[count]!='\n';count++)
2261 str_channel[count] = buf[count];
2262 str_channel[count] = '\0';
2263 Value = atol(str_channel);
2264 printf("%sValue is %ld \n",__FUNCTION__,Value);
2265 pclose(fp);
2266 }
2267 }
2268 Radio_flag = FALSE;//for storing previous channel value
2269 wifi_setRadioChannel(radioIndex,Value);
2270 return RETURN_OK;
2271 }
2272 return RETURN_ERR;
2273}
2274
developer0b246d12022-09-30 15:24:20 +08002275INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2276{
2277 if (output_bool == NULL)
2278 return RETURN_ERR;
2279
2280 *output_bool = TRUE;
2281
2282 return RETURN_OK;
2283}
2284
developer06a01d92022-09-07 16:32:39 +08002285INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2286{
2287 if (NULL == output_bool)
2288 return RETURN_ERR;
2289 *output_bool=FALSE;
2290 return RETURN_OK;
2291}
2292
2293INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2294{
2295 if (NULL == output_bool)
2296 return RETURN_ERR;
2297 *output_bool=FALSE;
2298 return RETURN_OK;
2299}
2300
2301INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2302{
2303 //Set to wifi config only. Wait for wifi reset to apply.
2304 return RETURN_OK;
2305}
2306
2307INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2308{
2309 return RETURN_OK;
2310}
2311
2312INT wifi_factoryResetAP(int apIndex)
2313{
developer838cca92022-10-03 13:19:57 +08002314 char ap_config_file[64] = {0};
2315 char cmd[128] = {0};
2316
developer06a01d92022-09-07 16:32:39 +08002317 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002318
2319 wifi_setApEnable(apIndex, FALSE);
2320 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2321 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2322 wifi_setApEnable(apIndex, TRUE);
2323
developer06a01d92022-09-07 16:32:39 +08002324 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002325
developer06a01d92022-09-07 16:32:39 +08002326 return RETURN_OK;
2327}
2328
2329//To set Band Steering AP group
2330//To-do
2331INT wifi_setBandSteeringApGroup(char *ApGroup)
2332{
2333 return RETURN_OK;
2334}
2335
developer1e5aa162022-09-13 16:06:24 +08002336INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2337{
2338 char config_file[128] = {'\0'};
2339 char buf[128] = {'\0'};
2340
2341 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2342 if (dtimInterval == NULL)
2343 return RETURN_ERR;
2344
2345 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2346 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2347
2348 if (strlen(buf) == 0) {
2349 *dtimInterval = 2;
2350 } else {
2351 *dtimInterval = strtoul(buf, NULL, 10);
2352 }
2353
2354 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2355 return RETURN_OK;
2356}
2357
developer06a01d92022-09-07 16:32:39 +08002358INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2359{
developer5f222492022-09-13 15:21:52 +08002360 struct params params={0};
2361 char config_file[MAX_BUF_SIZE] = {'\0'};
2362 char buf[MAX_BUF_SIZE] = {'\0'};
2363
2364 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2365 if (dtimInterval < 1 || dtimInterval > 255) {
2366 return RETURN_ERR;
2367 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2368 }
2369
2370 params.name = "dtim_period";
2371 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2372 params.value = buf;
2373
2374 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2375 wifi_hostapdWrite(config_file, &params, 1);
2376 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2377
2378 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2379 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002380}
2381
2382//Check if the driver support the Dfs
2383INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2384{
2385 if (NULL == output_bool)
2386 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002387 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002388 return RETURN_OK;
2389}
2390
2391//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.
2392//The value of this parameter is a comma seperated list of channel number
2393INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2394{
2395 if (NULL == output_pool)
2396 return RETURN_ERR;
2397 if (radioIndex==1)
2398 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2399 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2400
2401 return RETURN_OK;
2402}
2403
2404INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2405{
2406 //Set to wifi config. And apply instantly.
2407 return RETURN_OK;
2408}
2409
2410INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2411{
2412 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2413 return RETURN_ERR;
2414 *output_interval_seconds=1800;
2415 *output_dwell_milliseconds=40;
2416
2417 return RETURN_OK;
2418}
2419
2420INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2421{
2422 //Set to wifi config. And apply instantly.
2423 return RETURN_OK;
2424}
2425
developerbfc18512022-10-05 17:54:28 +08002426INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2427{
2428 if (output_bool == NULL)
2429 return RETURN_ERR;
2430 *output_bool = true;
2431 return RETURN_OK;
2432}
2433
2434INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2435{
2436 return RETURN_OK;
2437}
2438
developer06a01d92022-09-07 16:32:39 +08002439//Get the Dfs enable status
2440INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2441{
developer9964b5b2022-09-13 15:59:34 +08002442 char buf[16] = {0};
2443 FILE *f = NULL;
2444 wifi_band band;
2445
2446 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2447
2448 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002449 if (NULL == output_bool)
2450 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002451
2452 band = wifi_index_to_band(radioIndex);
2453 if (band != band_5)
2454 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002455
developer9964b5b2022-09-13 15:59:34 +08002456 f = fopen(DFS_ENABLE_FILE, "r");
2457 if (f != NULL) {
2458 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002459 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002460 *output_bool = FALSE;
2461 fclose(f);
2462 }
2463 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002464 return RETURN_OK;
2465}
2466
2467//Set the Dfs enable status
2468INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2469{
developer9964b5b2022-09-13 15:59:34 +08002470 char config_file[128] = {0};
2471 FILE *f = NULL;
2472 struct params params={0};
2473 wifi_band band;
2474
2475 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2476
2477 band = wifi_index_to_band(radioIndex);
2478 if (band != band_5)
2479 return RETURN_OK;
2480
2481 f = fopen(DFS_ENABLE_FILE, "w");
2482 if (f == NULL)
2483 return RETURN_ERR;
2484 fprintf(f, "%d", enable);
2485 fclose(f);
2486
2487 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002488 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002489 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2490 wifi_hostapdWrite(config_file, &params, 1);
2491 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2492
2493 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2494
developer9964b5b2022-09-13 15:59:34 +08002495 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002496 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002497}
2498
2499//Check if the driver support the AutoChannelRefreshPeriod
2500INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2501{
2502 if (NULL == output_bool)
2503 return RETURN_ERR;
2504 *output_bool=FALSE; //not support
2505
2506 return RETURN_OK;
2507}
2508
2509//Get the ACS refresh period in seconds
2510INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2511{
2512 if (NULL == output_ulong)
2513 return RETURN_ERR;
2514 *output_ulong=300;
2515
2516 return RETURN_OK;
2517}
2518
2519//Set the ACS refresh period in seconds
2520INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2521{
2522 return RETURN_ERR;
2523}
2524
2525//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2526//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.
2527INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2528{
developer70490032022-09-13 15:45:20 +08002529 char cmd[128] = {0}, buf[64] = {0};
2530 char interface_name[64] = {0};
2531 int ret = 0, len=0;
2532 BOOL radio_enable = FALSE;
2533
2534 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2535
developer06a01d92022-09-07 16:32:39 +08002536 if (NULL == output_string)
2537 return RETURN_ERR;
2538
developer70490032022-09-13 15:45:20 +08002539 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2540 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002541
developer70490032022-09-13 15:45:20 +08002542 if (radio_enable != TRUE)
2543 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002544
developer70490032022-09-13 15:45:20 +08002545 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002546 ret = _syscmd(cmd, buf, sizeof(buf));
2547 len = strlen(buf);
2548 if((ret != 0) || (len == 0))
2549 {
2550 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2551 return RETURN_ERR;
2552 }
2553
2554 buf[len-1] = '\0';
2555 snprintf(output_string, 64, "%sMHz", buf);
2556 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2557
2558#if 0
2559 //TODO: revisit below implementation
2560 char output_buf[8]={0};
2561 char bw_value[10];
2562 char config_file[MAX_BUF_SIZE] = {0};
2563
2564 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2565 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2566 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2567 readBandWidth(radioIndex,bw_value);
2568
2569 if(strstr (output_buf,"0") != NULL )
2570 {
2571 strcpy(output_string,bw_value);
2572 }
2573 else if (strstr (output_buf,"1") != NULL)
2574 {
2575 strcpy(output_string,"80MHz");
2576 }
2577 else if (strstr (output_buf,"2") != NULL)
2578 {
2579 strcpy(output_string,"160MHz");
2580 }
2581 else if (strstr (output_buf,"3") != NULL)
2582 {
2583 strcpy(output_string,"80+80");
2584 }
2585 else
2586 {
2587 strcpy(output_string,"Auto");
2588 }
2589 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2590#endif
2591
2592 return RETURN_OK;
2593}
2594
2595//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002596INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002597{
developerf7a466e2022-09-29 11:55:56 +08002598 char config_file[128];
2599 char set_value[16];
2600 struct params params[2];
2601 int max_radio_num = 0;
2602
developer06a01d92022-09-07 16:32:39 +08002603 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002604
developerf7a466e2022-09-29 11:55:56 +08002605 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002606 return RETURN_ERR;
2607
developerf7a466e2022-09-29 11:55:56 +08002608 if(strstr(bandwidth,"80+80") != NULL)
2609 strcpy(set_value, "3");
2610 else if(strstr(bandwidth,"160") != NULL)
2611 strcpy(set_value, "2");
2612 else if(strstr(bandwidth,"80") != NULL)
2613 strcpy(set_value, "1");
2614 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2615 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002616 else
2617 {
developerf7a466e2022-09-29 11:55:56 +08002618 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002619 return RETURN_ERR;
2620 }
2621
developerf7a466e2022-09-29 11:55:56 +08002622 params[0].name = "vht_oper_chwidth";
2623 params[0].value = set_value;
2624 params[1].name = "he_oper_chwidth";
2625 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002626
developerf7a466e2022-09-29 11:55:56 +08002627 wifi_getMaxRadioNumber(&max_radio_num);
2628 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002629 {
developerf7a466e2022-09-29 11:55:56 +08002630 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2631 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002632 }
2633
2634 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2635 return RETURN_OK;
2636}
2637
2638//Getting current radio extension channel
2639INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2640{
2641 CHAR buf[150] = {0};
2642 CHAR cmd[150] = {0};
2643 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2644 _syscmd(cmd, buf, sizeof(buf));
2645 if(NULL != strstr(buf,"HT40+"))
2646 strcpy(Value,"AboveControlChannel");
2647 else if(NULL != strstr(buf,"HT40-"))
2648 strcpy(Value,"BelowControlChannel");
2649 return RETURN_OK;
2650}
2651
2652//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2653//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.
2654INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2655{
2656 if (NULL == output_string)
2657 return RETURN_ERR;
2658
2659 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2660#if 0
2661 CHAR Value[100] = {0};
2662 if (NULL == output_string)
2663 return RETURN_ERR;
2664 if(radioIndex == 0)
2665 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2666 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2667 {
2668 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2669 if(strcmp(Value,"40MHz") == 0)
2670 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2671 else
2672 strcpy(Value,"Auto");
2673 }
2674 strcpy(output_string,Value);
2675#endif
2676
2677 return RETURN_OK;
2678}
2679
2680//Set the extension channel.
2681INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2682{
2683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2684 struct params params={'\0'};
2685 char config_file[MAX_BUF_SIZE] = {0};
2686 char ext_channel[127]={'\0'};
2687
2688 params.name = "ht_capab";
2689
2690 if(radioIndex == 0)
2691 {
2692 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002693 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002694 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002695 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002696 else
developer3cc0f2e2022-09-15 18:25:39 +08002697 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002698 }
2699 else if(radioIndex == 1)
2700 {
2701 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002702 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002703 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002704 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002705 else
developer3cc0f2e2022-09-15 18:25:39 +08002706 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002707 }
2708
2709 params.value = ext_channel;
2710 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2711 {
2712 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2713 wifi_hostapdWrite(config_file, &params, 1);
2714 }
2715
2716 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2718 return RETURN_OK;
2719}
2720
2721//Get the guard interval value. eg "400nsec" or "800nsec"
2722//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.
2723INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2724{
developer454b9462022-09-13 15:29:16 +08002725 wifi_guard_interval_t GI;
2726
2727 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2728
2729 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002730 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002731
2732 if (GI == wifi_guard_interval_400)
2733 strcpy(output_string, "400nsec");
2734 else if (GI == wifi_guard_interval_800)
2735 strcpy(output_string, "800nsec");
2736 else if (GI == wifi_guard_interval_1600)
2737 strcpy(output_string, "1600nsec");
2738 else if (GI == wifi_guard_interval_3200)
2739 strcpy(output_string, "3200nsec");
2740 else
2741 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002742
developer454b9462022-09-13 15:29:16 +08002743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002744 return RETURN_OK;
2745}
2746
2747//Set the guard interval value.
2748INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2749{
developer454b9462022-09-13 15:29:16 +08002750 wifi_guard_interval_t GI;
2751 int ret = 0;
2752
2753 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2754
2755 if (strcmp(string, "400nsec") == 0)
2756 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002757 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002758 GI = wifi_guard_interval_800;
2759 else if (strcmp(string , "1600nsec") == 0)
2760 GI = wifi_guard_interval_1600;
2761 else if (strcmp(string , "3200nsec") == 0)
2762 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002763 else
2764 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002765
2766 ret = wifi_setGuardInterval(radioIndex, GI);
2767
2768 if (ret == RETURN_ERR) {
2769 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2770 return RETURN_ERR;
2771 }
2772
2773 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2774 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002775}
2776
2777//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2778INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2779{
developerf49437e2022-09-29 19:58:21 +08002780 char buf[32]={0};
2781 char mcs_file[64] = {0};
2782 char cmd[64] = {0};
2783 int mode_bitmap = 0;
2784
2785 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2786 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002787 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002788 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2789
2790 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2791 _syscmd(cmd, buf, sizeof(buf));
2792 if (strlen(buf) > 0)
2793 *output_int = strtol(buf, NULL, 10);
2794 else {
2795 // output the max MCS for the current radio mode
2796 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2797 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2798 return RETURN_ERR;
2799 }
2800 if (mode_bitmap & WIFI_MODE_AX) {
2801 *output_int = 11;
2802 } else if (mode_bitmap & WIFI_MODE_AC) {
2803 *output_int = 9;
2804 } else if (mode_bitmap & WIFI_MODE_N) {
2805 *output_int = 7;
2806 }
2807 }
2808 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002809
2810 return RETURN_OK;
2811}
2812
2813//Set the Modulation Coding Scheme index
2814INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2815{
developerf49437e2022-09-29 19:58:21 +08002816 // Only HE mode can specify MCS capability. We don't support MCS in HT mode, because that would be ambiguous (MCS code 8~11 refer to 2 NSS in HT but 1 NSS in HE adn VHT).
2817 char config_file[64] = {0};
2818 char set_value[16] = {0};
2819 char mcs_file[32] = {0};
2820 wifi_band band = band_invalid;
2821 struct params set_config = {0};
2822 FILE *f = NULL;
2823
2824 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2825
2826 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2827
2828 if (MCS > 11 || MCS < 0) {
2829 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2830 return RETURN_ERR;
2831 }
2832
2833 if (MCS <= 7)
2834 strcpy(set_value, "0");
2835 else if (MCS <= 9)
2836 strcpy(set_value, "1");
2837 else
2838 strcpy(set_value, "2");
2839
2840 set_config.name = "he_basic_mcs_nss_set";
2841 set_config.value = set_value;
2842
2843 wifi_hostapdWrite(config_file, &set_config, 1);
2844 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2845
2846 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2847 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2848 f = fopen(mcs_file, "w");
2849 if (f == NULL) {
2850 fprintf(stderr, "%s: fopen failed\n", __func__);
2851 return RETURN_ERR;
2852 }
2853 fprintf(f, "%d", MCS);
2854 fclose(f);
2855
2856 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2857 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002858}
2859
2860//Get supported Transmit Power list, eg : "0,25,50,75,100"
2861//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.
2862INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2863{
2864 if (NULL == output_list)
2865 return RETURN_ERR;
2866 snprintf(output_list, 64,"0,25,50,75,100");
2867 return RETURN_OK;
2868}
2869
developera5005b62022-09-13 15:43:35 +08002870//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002871//The transmite power level is in units of full power for this radio.
2872INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2873{
2874 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002875 char buf[16]={0};
2876 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002877
developera5005b62022-09-13 15:43:35 +08002878 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002879 return RETURN_ERR;
2880
developera5005b62022-09-13 15:43:35 +08002881 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002882 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002883
developera5005b62022-09-13 15:43:35 +08002884 *output_ulong = strtol(buf, NULL, 10);
2885
2886 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002887 return RETURN_OK;
2888}
2889
2890//Set Transmit Power
2891//The transmite power level is in units of full power for this radio.
2892INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2893{
developera5005b62022-09-13 15:43:35 +08002894 char *support;
developer06a01d92022-09-07 16:32:39 +08002895 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002896 char buf[128]={0};
2897 char txpower_str[64] = {0};
2898 int txpower = 0;
2899 int maximum_tx = 0;
2900
2901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002902
developera5005b62022-09-13 15:43:35 +08002903 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002904 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002905 maximum_tx = strtol(buf, NULL, 10);
2906
2907 // Get the Tx power supported list and check that is the input in the list
2908 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2909 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2910 support = strtok(buf, ",");
2911 while(true)
2912 {
2913 if(support == NULL) { // input not in the list
2914 wifi_dbg_printf("Input value is invalid.\n");
2915 return RETURN_ERR;
2916 }
2917 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2918 break;
2919 }
2920 support = strtok(NULL, ",");
2921 }
2922 txpower = TransmitPower*maximum_tx/100;
2923 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2924 _syscmd(cmd, buf, sizeof(buf));
2925 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002926
2927 return RETURN_OK;
2928}
2929
2930//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2931INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2932{
2933 if (NULL == Supported)
2934 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002935 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002936
2937 return RETURN_OK;
2938}
2939
2940//Get 80211h feature enable
2941INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2942{
developer3885fec2022-09-13 15:13:47 +08002943 char buf[64]={'\0'};
2944 char config_file[64] = {'\0'};
2945
2946 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2947 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002948 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002949
2950 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2951 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002952
developer3885fec2022-09-13 15:13:47 +08002953 if (strncmp(buf, "1", 1) == 0)
2954 *enable = TRUE;
2955 else
2956 *enable = FALSE;
2957
2958 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002959 return RETURN_OK;
2960}
2961
2962//Set 80211h feature enable
2963INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2964{
developer3885fec2022-09-13 15:13:47 +08002965 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2966 struct params params={'\0'};
2967 char config_file[MAX_BUF_SIZE] = {0};
2968
2969 params.name = "ieee80211h";
2970
2971 if (enable) {
2972 params.value = "1";
2973 } else {
2974 params.value = "0";
2975 }
2976
2977 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2978 wifi_hostapdWrite(config_file, &params, 1);
2979
2980 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2981 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2982 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002983}
2984
2985//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.
2986INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2987{
2988 if (NULL == output)
2989 return RETURN_ERR;
2990 *output=100;
2991
2992 return RETURN_OK;
2993}
2994
2995//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.
2996INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2997{
2998 if (NULL == output)
2999 return RETURN_ERR;
3000 *output = -99;
3001
3002 return RETURN_OK;
3003}
3004
3005INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3006{
3007 return RETURN_ERR;
3008}
3009
3010
3011//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3012INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3013{
developer5f222492022-09-13 15:21:52 +08003014 char cmd[MAX_BUF_SIZE]={'\0'};
3015 char buf[MAX_CMD_SIZE]={'\0'};
3016
3017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3018 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003019 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003020
3021 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3022 _syscmd(cmd, buf, sizeof(buf));
3023 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003024
developer5f222492022-09-13 15:21:52 +08003025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003026 return RETURN_OK;
3027}
3028
3029INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3030{
developer5f222492022-09-13 15:21:52 +08003031 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3032 struct params params={'\0'};
3033 char buf[MAX_BUF_SIZE] = {'\0'};
3034 char config_file[MAX_BUF_SIZE] = {'\0'};
3035
3036 params.name = "beacon_int";
3037 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3038 params.value = buf;
3039
3040 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3041 wifi_hostapdWrite(config_file, &params, 1);
3042
3043 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3044 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3045 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003046}
3047
3048//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.
3049INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3050{
developer06a01d92022-09-07 16:32:39 +08003051 //TODO: need to revisit below implementation
3052 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003053 char temp_output[128] = {0};
3054 char temp_TransmitRates[64] = {0};
3055 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003056
3057 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3058 if (NULL == output)
3059 return RETURN_ERR;
3060 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003061 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3062
3063 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3064 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3065 } else {
3066 temp = strtok(temp_TransmitRates," ");
3067 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003068 {
developere9d0abd2022-09-13 15:40:57 +08003069 // Convert 100 kbps to Mbps
3070 temp[strlen(temp)-1]=0;
3071 if((temp[0]=='5') && (temp[1]=='\0'))
3072 {
3073 temp="5.5";
3074 }
3075 strcat(temp_output,temp);
3076 temp = strtok(NULL," ");
3077 if(temp!=NULL)
3078 {
3079 strcat(temp_output,",");
3080 }
developer06a01d92022-09-07 16:32:39 +08003081 }
developere9d0abd2022-09-13 15:40:57 +08003082 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003083 }
developer06a01d92022-09-07 16:32:39 +08003084 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003085 return RETURN_OK;
3086}
3087
3088INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3089{
3090 char *temp;
3091 char temp1[128];
3092 char temp_output[128];
3093 char temp_TransmitRates[128];
3094 char set[128];
3095 char sub_set[128];
3096 int set_count=0,subset_count=0;
3097 int set_index=0,subset_index=0;
3098 char *token;
3099 int flag=0, i=0;
3100 struct params params={'\0'};
3101 char config_file[MAX_BUF_SIZE] = {0};
3102
3103 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3104 if(NULL == TransmitRates)
3105 return RETURN_ERR;
3106 strcpy(sub_set,TransmitRates);
3107
3108 //Allow only supported Data transmit rate to be set
3109 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3110 token = strtok(sub_set,",");
3111 while( token != NULL ) /* split the basic rate to be set, by comma */
3112 {
3113 sub_set[subset_count]=atoi(token);
3114 subset_count++;
3115 token=strtok(NULL,",");
3116 }
3117 token=strtok(set,",");
3118 while(token!=NULL) /* split the supported rate by comma */
3119 {
3120 set[set_count]=atoi(token);
3121 set_count++;
3122 token=strtok(NULL,",");
3123 }
3124 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3125 {
3126 for(set_index=0;set_index < set_count;set_index++)
3127 {
3128 flag=0;
3129 if(sub_set[subset_index]==set[set_index])
3130 break;
3131 else
3132 flag=1; /* No match found */
3133 }
3134 if(flag==1)
3135 return RETURN_ERR; //If value not found return Error
3136 }
3137 strcpy(temp_TransmitRates,TransmitRates);
3138
3139 for(i=0;i<strlen(temp_TransmitRates);i++)
3140 {
3141 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3142 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3143 {
3144 continue;
3145 }
3146 else
3147 {
3148 return RETURN_ERR;
3149 }
3150 }
3151 strcpy(temp_output,"");
3152 temp = strtok(temp_TransmitRates,",");
3153 while(temp!=NULL)
3154 {
3155 strcpy(temp1,temp);
3156 if(radioIndex==1)
3157 {
3158 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3159 {
3160 return RETURN_ERR;
3161 }
3162 }
3163
3164 if(strcmp(temp,"5.5")==0)
3165 {
3166 strcpy(temp1,"55");
3167 }
3168 else
3169 {
3170 strcat(temp1,"0");
3171 }
3172 strcat(temp_output,temp1);
3173 temp = strtok(NULL,",");
3174 if(temp!=NULL)
3175 {
3176 strcat(temp_output," ");
3177 }
3178 }
3179 strcpy(TransmitRates,temp_output);
3180
3181 params.name= "basic_rates";
3182 params.value =TransmitRates;
3183
3184 wifi_dbg_printf("\n%s:",__func__);
3185 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3186 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3187 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3188 wifi_hostapdWrite(config_file,&params,1);
3189 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3190 return RETURN_OK;
3191}
3192
3193//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3194INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3195{
3196 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3197 FILE *fp = NULL;
3198 char path[256] = {0}, output_string[256] = {0};
3199 int count = 0;
3200 char *interface = NULL;
3201
3202 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3203 if (fp == NULL)
3204 {
3205 printf("Failed to run command in Function %s\n", __FUNCTION__);
3206 return RETURN_ERR;
3207 }
3208 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3209 {
3210 interface = strchr(path, '=');
3211
3212 if (interface != NULL)
3213 {
3214 strcpy(output_string, interface + 1);
3215 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3216 interface_name[count] = output_string[count];
3217
3218 interface_name[count] = '\0';
3219 }
3220 }
3221 pclose(fp);
3222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3223 return RETURN_OK;
3224}
3225
3226INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3227{
3228 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3229 output_struct->radio_BytesSent = 0;
3230 output_struct->radio_BytesReceived = 0;
3231 output_struct->radio_PacketsSent = 0;
3232 output_struct->radio_PacketsReceived = 0;
3233 output_struct->radio_ErrorsSent = 0;
3234 output_struct->radio_ErrorsReceived = 0;
3235 output_struct->radio_DiscardPacketsSent = 0;
3236 output_struct->radio_DiscardPacketsReceived = 0;
3237 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3238 return RETURN_OK;
3239}
3240
3241
3242INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3243{
3244 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3245 CHAR buf[MAX_CMD_SIZE] = {0};
3246 CHAR Value[MAX_BUF_SIZE] = {0};
3247 FILE *fp = NULL;
3248
3249 if (ifname == NULL || strlen(ifname) <= 1)
3250 return RETURN_OK;
3251
3252 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3253 system(buf);
3254
3255 fp = fopen("/tmp/Radio_Stats.txt", "r");
3256 if(fp == NULL)
3257 {
3258 printf("/tmp/Radio_Stats.txt not exists \n");
3259 return RETURN_ERR;
3260 }
3261 fclose(fp);
3262
3263 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3264 File_Reading(buf, Value);
3265 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3266
3267 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3268 File_Reading(buf, Value);
3269 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3270
3271 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3272 File_Reading(buf, Value);
3273 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3274
3275 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3276 File_Reading(buf, Value);
3277 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3278
3279 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3280 File_Reading(buf, Value);
3281 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3282
3283 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3284 File_Reading(buf, Value);
3285 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3286
3287 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3288 File_Reading(buf, Value);
3289 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3290
3291 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3292 File_Reading(buf, Value);
3293 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3294
3295 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3296 return RETURN_OK;
3297}
3298
3299INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3300{
3301 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3302 CHAR buf[MAX_CMD_SIZE] = {0};
3303 FILE *fp = NULL;
3304 INT count = 0;
3305
3306 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3307 {
3308 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3309 File_Reading(buf, status);
3310 }
3311 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3312 return RETURN_OK;
3313}
3314
3315//Get detail radio traffic static info
3316INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3317{
3318
3319#if 0
3320 //ifconfig radio_x
3321 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3322 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3323 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3324 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3325
3326 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3327 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3328 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.
3329 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.
3330
3331 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3332 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].
3333 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3334 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.
3335 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
3336 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
3337 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
3338 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
3339 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
3340
3341 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
3342 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
3343 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
3344 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.
3345
3346 return RETURN_OK;
3347#endif
3348
developera91d99f2022-09-29 15:59:10 +08003349 CHAR interface_name[64] = {0};
3350 CHAR config_path[64] = {0};
3351 BOOL iface_status = FALSE;
3352 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003353
3354 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3355 if (NULL == output_struct)
3356 return RETURN_ERR;
3357
developera91d99f2022-09-29 15:59:10 +08003358 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3359 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003360
developera91d99f2022-09-29 15:59:10 +08003361 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003362
developera91d99f2022-09-29 15:59:10 +08003363 if (iface_status == TRUE)
3364 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3365 else
3366 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003367
developera91d99f2022-09-29 15:59:10 +08003368 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3369 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3370 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3371 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3372 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3373 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3374 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3375 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003376
3377 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3378 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].
3379 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3380 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.
3381 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
3382 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
3383 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
3384 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
3385 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
3386
3387 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
3388 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
3389 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
3390 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.
3391
3392 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3393
3394 return RETURN_OK;
3395}
3396
3397//Set radio traffic static Measureing rules
3398INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3399{
3400 //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
3401 // Else, save the MeasuringRate and MeasuringInterval for future usage
3402
3403 return RETURN_OK;
3404}
3405
3406//To start or stop RadioTrafficStats
3407INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3408{
3409 //zqiu: If the RadioTrafficStats process running
3410 // if(enable)
3411 // return RETURN_OK.
3412 // else
3413 // Stop RadioTrafficStats process
3414 // Else
3415 // if(enable)
3416 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3417 // else
3418 // return RETURN_OK.
3419
3420 return RETURN_OK;
3421}
3422
3423//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
3424INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3425{
3426 //zqiu: Please ignor signalIndex.
3427 if (NULL == SignalLevel)
3428 return RETURN_ERR;
3429 *SignalLevel=(radioIndex==0)?-19:-19;
3430
3431 return RETURN_OK;
3432}
3433
3434//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3435INT wifi_applyRadioSettings(INT radioIndex)
3436{
3437 return RETURN_OK;
3438}
3439
3440//Get the radio index assocated with this SSID entry
3441INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3442{
3443 if (NULL == radioIndex)
3444 return RETURN_ERR;
3445 *radioIndex=ssidIndex%2;
3446
3447 return RETURN_OK;
3448}
3449
3450//Device.WiFi.SSID.{i}.Enable
3451//Get SSID enable configuration parameters (not the SSID enable status)
3452INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3453{
3454 if (NULL == output_bool)
3455 return RETURN_ERR;
3456
3457 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3458 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3459 return wifi_getApEnable(ssidIndex, output_bool);
3460}
3461
3462//Device.WiFi.SSID.{i}.Enable
3463//Set SSID enable configuration parameters
3464INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3465{
3466 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3467 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3468 return wifi_setApEnable(ssidIndex, enable);
3469}
3470
3471//Device.WiFi.SSID.{i}.Status
3472//Get the SSID enable status
3473INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3474{
3475 char cmd[MAX_CMD_SIZE]={0};
3476 char buf[MAX_BUF_SIZE]={0};
3477 BOOL output_bool;
3478
3479 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3480 if (NULL == output_string)
3481 return RETURN_ERR;
3482 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3483 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3484
3485 wifi_getApEnable(ssidIndex,&output_bool);
3486 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3487
3488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3489 return RETURN_OK;
3490}
3491
3492// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3493INT wifi_getSSIDName(INT apIndex, CHAR *output)
3494{
3495 char config_file[MAX_BUF_SIZE] = {0};
3496
3497 if (NULL == output)
3498 return RETURN_ERR;
3499
3500 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3501 wifi_hostapdRead(config_file,"ssid",output,32);
3502
3503 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3504 return RETURN_OK;
3505}
3506
3507// Set a max 32 byte string and sets an internal variable to the SSID name
3508INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3509{
3510 char str[MAX_BUF_SIZE]={'\0'};
3511 char cmd[MAX_CMD_SIZE]={'\0'};
3512 struct params params;
3513 char config_file[MAX_BUF_SIZE] = {0};
3514
3515 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3516 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3517 return RETURN_ERR;
3518
3519 params.name = "ssid";
3520 params.value = ssid_string;
3521 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3522 wifi_hostapdWrite(config_file, &params, 1);
3523 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3524 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3525
3526 return RETURN_OK;
3527}
3528
3529//Get the BSSID
3530INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3531{
3532 char cmd[MAX_CMD_SIZE]="";
3533
3534 if (NULL == output_string)
3535 return RETURN_ERR;
3536
3537 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3538 {
3539 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3540 _syscmd(cmd, output_string, 64);
3541 return RETURN_OK;
3542 }
3543 strncpy(output_string, "\0", 1);
3544
3545 return RETURN_ERR;
3546}
3547
3548//Get the MAC address associated with this Wifi SSID
3549INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3550{
3551 wifi_getBaseBSSID(ssidIndex,output_string);
3552 return RETURN_OK;
3553}
3554
3555//Get the basic SSID traffic static info
3556//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3557//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3558INT wifi_applySSIDSettings(INT ssidIndex)
3559{
3560 BOOL status = false;
3561 char cmd[MAX_CMD_SIZE] = {0};
3562 char buf[MAX_CMD_SIZE] = {0};
3563 int apIndex, ret;
3564 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3565
3566 wifi_getApEnable(ssidIndex,&status);
3567 // Do not apply when ssid index is disabled
3568 if (status == false)
3569 return RETURN_OK;
3570
3571 /* Doing full remove and add for ssid Index
3572 * Not all hostapd options are supported with reload
3573 * for example macaddr_acl
3574 */
3575 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3576 return RETURN_ERR;
3577
3578 ret = wifi_setApEnable(ssidIndex,true);
3579
3580 /* Workaround for hostapd issue with multiple bss definitions
3581 * when first created interface will be removed
3582 * then all vaps other vaps on same phy are removed
3583 * after calling setApEnable to false readd all enabled vaps */
3584 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3585 apIndex = 2*i+radioIndex;
3586 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3587 _syscmd(cmd, buf, sizeof(buf));
3588 if(*buf == '1')
3589 wifi_setApEnable(apIndex, true);
3590 }
3591
3592 return ret;
3593}
3594
developera3c68b92022-09-13 15:27:29 +08003595struct channels_noise {
3596 int channel;
3597 int noise;
3598};
3599
3600// Return noise array for each channel
3601int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3602{
3603 FILE *f = NULL;
3604 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003605 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003606 size_t len = 0;
3607 ssize_t read = 0;
3608 int tmp = 0, arr_index = -1;
3609
3610 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3611
3612 if ((f = popen(cmd, "r")) == NULL) {
3613 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3614 return RETURN_ERR;
3615 }
developer5550e242022-09-30 09:59:32 +08003616
3617 while(fgets(line, sizeof(line), f) != NULL) {
3618 if(arr_index < channels_num){
3619 sscanf(line, "%d", &tmp);
3620 if (tmp > 0) { // channel frequency, the first line must be frequency
3621 arr_index++;
3622 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3623 } else { // noise
3624 channels_noise_arr[arr_index].noise = tmp;
3625 }
3626 }else{
3627 break;
developera3c68b92022-09-13 15:27:29 +08003628 }
3629 }
developera3c68b92022-09-13 15:27:29 +08003630 pclose(f);
3631 return RETURN_OK;
3632}
3633
developer06a01d92022-09-07 16:32:39 +08003634//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3635//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3636INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3637{
developera3c68b92022-09-13 15:27:29 +08003638 int index = -1;
3639 wifi_neighbor_ap2_t *scan_array = NULL;
3640 char cmd[256]={0};
3641 char buf[128]={0};
3642 char file_name[32] = {0};
3643 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003644 char line[256] = {0};
3645 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003646 int freq=0;
3647 FILE *f = NULL;
3648 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003649 int channels_num = 0;
3650 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003651 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003652 bool filter_enable = false;
3653 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003654
developer615510b2022-09-27 10:14:35 +08003655 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003656
3657 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3658 f = fopen(file_name, "r");
3659 if (f != NULL) {
3660 fgets(filter_SSID, sizeof(file_name), f);
3661 if (strlen(filter_SSID) != 0)
3662 filter_enable = true;
3663 fclose(f);
3664 }
3665
3666 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003667 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003668 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003669
developer5550e242022-09-30 09:59:32 +08003670
developer06a01d92022-09-07 16:32:39 +08003671
developera3c68b92022-09-13 15:27:29 +08003672 sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
developer615510b2022-09-27 10:14:35 +08003673 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex);
developera3c68b92022-09-13 15:27:29 +08003674 fprintf(stderr, "cmd: %s\n", cmd);
3675 if ((f = popen(cmd, "r")) == NULL) {
3676 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3677 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003678 }
developer5550e242022-09-30 09:59:32 +08003679
3680 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3681 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3682
developer615510b2022-09-27 10:14:35 +08003683 ret = fgets(line, sizeof(line), f);
3684 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003685 if(strstr(line, "BSS") != NULL) { // new neighbor info
3686 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3687 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3688 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
developer06a01d92022-09-07 16:32:39 +08003689
developera3c68b92022-09-13 15:27:29 +08003690 if (!filter_BSS) {
3691 index++;
3692 wifi_neighbor_ap2_t *tmp;
3693 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3694 if (tmp == NULL) { // no more memory to use
3695 index--;
3696 wifi_dbg_printf("%s: realloc failed\n", __func__);
3697 break;
3698 }
3699 scan_array = tmp;
3700 }
3701 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3702
3703 filter_BSS = false;
3704 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3705 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3706 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3707 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3708 } else if (strstr(line, "freq") != NULL) {
3709 sscanf(line," freq: %d", &freq);
3710 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3711
3712 if (freq >= 2412 && freq <= 2484) {
3713 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3714 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3715 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3716 }
3717 else if (freq >= 5160 && freq <= 5805) {
3718 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3719 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3720 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3721 }
3722
3723 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003724 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003725 for (int i = 0; i < channels_num; i++) {
3726 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3727 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3728 break;
3729 }
3730 }
3731 }
3732 } else if (strstr(line, "beacon interval") != NULL) {
3733 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3734 } else if (strstr(line, "signal") != NULL) {
3735 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3736 } else if (strstr(line,"SSID") != NULL) {
3737 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3738 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3739 filter_BSS = true;
3740 }
3741 } else if (strstr(line, "Supported rates") != NULL) {
3742 char SRate[80] = {0}, *tmp = NULL;
3743 memset(buf, 0, sizeof(buf));
3744 strcpy(SRate, line);
3745 tmp = strtok(SRate, ":");
3746 tmp = strtok(NULL, ":");
3747 strcpy(buf, tmp);
3748 memset(SRate, 0, sizeof(SRate));
3749
3750 tmp = strtok(buf, " \n");
3751 while (tmp != NULL) {
3752 strcat(SRate, tmp);
3753 if (SRate[strlen(SRate) - 1] == '*') {
3754 SRate[strlen(SRate) - 1] = '\0';
3755 }
3756 strcat(SRate, ",");
3757
3758 tmp = strtok(NULL, " \n");
3759 }
3760 SRate[strlen(SRate) - 1] = '\0';
3761 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3762 } else if (strstr(line, "DTIM") != NULL) {
3763 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3764 } else if (strstr(line, "VHT capabilities") != NULL) {
3765 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3766 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3767 } else if (strstr(line, "HT capabilities") != NULL) {
3768 strcat(scan_array[index].ap_SupportedStandards, ",n");
3769 strcpy(scan_array[index].ap_OperatingStandards, "n");
3770 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003771 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003772 sscanf(line," * channel width: %d", &vht_channel_width);
3773 if(vht_channel_width == 1) {
3774 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3775 } else {
3776 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3777 }
3778 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3779 continue;
3780 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003781 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003782 sscanf(line," * secondary channel offset: %s", &buf);
3783 if (!strcmp(buf, "above")) {
3784 //40Mhz +
3785 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3786 }
3787 else if (!strcmp(buf, "below")) {
3788 //40Mhz -
3789 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3790 } else {
3791 //20Mhz
3792 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3793 }
3794 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3795 continue;
3796 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003797 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3798 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3799 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003800 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3801 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003802 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003803 else
developer615510b2022-09-27 10:14:35 +08003804 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003805 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003806 if (strstr(line, "HE80/5GHz") != NULL) {
3807 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3808 ret = fgets(line, sizeof(line), f);
3809 } else
3810 continue;
developera3c68b92022-09-13 15:27:29 +08003811 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003812 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003813 }
developer615510b2022-09-27 10:14:35 +08003814 continue;
developera3c68b92022-09-13 15:27:29 +08003815 } else if (strstr(line, "WPA") != NULL) {
3816 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3817 } else if (strstr(line, "RSN") != NULL) {
3818 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3819 } else if (strstr(line, "Group cipher") != NULL) {
3820 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3821 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3822 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3823 }
3824 }
developer615510b2022-09-27 10:14:35 +08003825 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003826 }
3827
3828 if (!filter_BSS) {
3829 *output_array_size = index + 1;
3830 } else {
3831 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3832 *output_array_size = index;
3833 }
3834 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003835 pclose(f);
developer5550e242022-09-30 09:59:32 +08003836 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003837 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003838 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003839}
3840
3841//>> Deprecated: used for old RDKB code.
3842INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3843{
3844 INT status = RETURN_ERR;
3845
3846 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3847 output_struct->wifi_PLCPErrorCount = 0;
3848 output_struct->wifi_FCSErrorCount = 0;
3849 output_struct->wifi_InvalidMACCount = 0;
3850 output_struct->wifi_PacketsOtherReceived = 0;
3851 output_struct->wifi_Noise = 0;
3852 status = RETURN_OK;
3853 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3854 return status;
3855}
3856
3857INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3858{
3859 char cmd[128];
3860 char buf[1280];
3861 char *pos = NULL;
3862
3863 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3864 if (NULL == output_struct)
3865 return RETURN_ERR;
3866
3867 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3868
3869 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3870 _syscmd(cmd, buf, sizeof(buf));
3871
3872 pos = buf;
3873 if ((pos = strstr(pos, "RX packets:")) == NULL)
3874 return RETURN_ERR;
3875 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3876
3877 if ((pos = strstr(pos, "TX packets:")) == NULL)
3878 return RETURN_ERR;
3879 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3880
3881 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3882 return RETURN_ERR;
3883 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3884
3885 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3886 return RETURN_ERR;
3887 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3888
3889 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3890 _syscmd(cmd, buf, sizeof(buf));
3891 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3892
3893#if 0
3894 //TODO: need to revisit below implementation
3895 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3896 char interface_name[MAX_BUF_SIZE] = {0};
3897 char interface_status[MAX_BUF_SIZE] = {0};
3898 char Value[MAX_BUF_SIZE] = {0};
3899 char buf[MAX_CMD_SIZE] = {0};
3900 char cmd[MAX_CMD_SIZE] = {0};
3901 FILE *fp = NULL;
3902
3903 if (NULL == output_struct) {
3904 return RETURN_ERR;
3905 }
3906
3907 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3908
3909 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3910 {
3911 if(apIndex == 0) //private_wifi for 2.4G
3912 {
3913 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3914 }
3915 else if(apIndex == 1) //private_wifi for 5G
3916 {
3917 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3918 }
3919 else if(apIndex == 4) //public_wifi for 2.4G
3920 {
3921 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3922 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3923 {
3924 return RETURN_ERR;
3925 }
3926 if(buf[0] == '#')//tp-link
3927 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3928 else//tenda
3929 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3930 }
3931 else if(apIndex == 5) //public_wifi for 5G
3932 {
3933 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3934 }
3935
3936 GetIfacestatus(interface_name, interface_status);
3937
3938 if(0 != strcmp(interface_status, "1"))
3939 return RETURN_ERR;
3940
3941 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3942 system(cmd);
3943
3944 fp = fopen("/tmp/SSID_Stats.txt", "r");
3945 if(fp == NULL)
3946 {
3947 printf("/tmp/SSID_Stats.txt not exists \n");
3948 return RETURN_ERR;
3949 }
3950 fclose(fp);
3951
3952 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3953 File_Reading(buf, Value);
3954 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3955
3956 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3957 File_Reading(buf, Value);
3958 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3959
3960 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3961 File_Reading(buf, Value);
3962 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3963
3964 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3965 File_Reading(buf, Value);
3966 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3967
3968 /* There is no specific parameter from caller to associate the value wifi_Associations */
3969 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3970 //_syscmd(cmd, buf, sizeof(buf));
3971 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3972 }
3973#endif
3974 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3975 return RETURN_OK;
3976}
3977
3978INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3979{
3980 char interface_name[MAX_BUF_SIZE] = {0};
3981 char interface_status[MAX_BUF_SIZE] = {0};
3982 char Value[MAX_BUF_SIZE] = {0};
3983 char buf[MAX_CMD_SIZE] = {0};
3984 char cmd[MAX_CMD_SIZE] = {0};
3985 FILE *fp = NULL;
3986
3987 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3988 if (NULL == output_struct)
3989 return RETURN_ERR;
3990
3991 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
3992
3993 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3994 {
3995 if(apIndex == 0) //private_wifi for 2.4G
3996 {
3997 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3998 }
3999 else if(apIndex == 1) //private_wifi for 5G
4000 {
4001 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4002 }
4003 else if(apIndex == 4) //public_wifi for 2.4G
4004 {
4005 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4006 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4007 {
4008 return RETURN_ERR;
4009 }
4010 if(buf[0] == '#')
4011 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4012 else
4013 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4014 }
4015 else if(apIndex == 5) //public_wifi for 5G
4016 {
4017 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4018 }
4019
4020 GetIfacestatus(interface_name, interface_status);
4021
4022 if(0 != strcmp(interface_status, "1"))
4023 return RETURN_ERR;
4024
4025 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4026 system(cmd);
4027
4028 fp = fopen("/tmp/SSID_Stats.txt", "r");
4029 if(fp == NULL)
4030 {
4031 printf("/tmp/SSID_Stats.txt not exists \n");
4032 return RETURN_ERR;
4033 }
4034 fclose(fp);
4035
4036 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4037 File_Reading(buf, Value);
4038 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4039
4040 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4041 File_Reading(buf, Value);
4042 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4043
4044 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4045 File_Reading(buf, Value);
4046 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4047
4048 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4049 File_Reading(buf, Value);
4050 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4051 }
4052
4053 output_struct->wifi_UnicastPacketsSent = 0;
4054 output_struct->wifi_UnicastPacketsReceived = 0;
4055 output_struct->wifi_MulticastPacketsSent = 0;
4056 output_struct->wifi_MulticastPacketsReceived = 0;
4057 output_struct->wifi_BroadcastPacketsSent = 0;
4058 output_struct->wifi_BroadcastPacketsRecevied = 0;
4059 output_struct->wifi_UnknownPacketsReceived = 0;
4060
4061 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4062 return RETURN_OK;
4063}
4064
4065INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4066{
4067 INT status = RETURN_ERR;
4068
4069 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4070 //Below values should get updated from hal
4071 output_struct->wifi_RetransCount=0;
4072 output_struct->wifi_FailedRetransCount=0;
4073 output_struct->wifi_RetryCount=0;
4074 output_struct->wifi_MultipleRetryCount=0;
4075 output_struct->wifi_ACKFailureCount=0;
4076 output_struct->wifi_AggregatedPacketCount=0;
4077
4078 status = RETURN_OK;
4079 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4080
4081 return status;
4082}
4083
4084INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4085{
4086 INT status = RETURN_ERR;
4087 UINT index;
4088 wifi_neighbor_ap_t *pt=NULL;
4089
4090 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4091 *output_array_size=2;
4092 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4093 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4094 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4095 strcpy(pt->ap_Radio,"");
4096 strcpy(pt->ap_SSID,"");
4097 strcpy(pt->ap_BSSID,"");
4098 strcpy(pt->ap_Mode,"");
4099 pt->ap_Channel=1;
4100 pt->ap_SignalStrength=0;
4101 strcpy(pt->ap_SecurityModeEnabled,"");
4102 strcpy(pt->ap_EncryptionMode,"");
4103 strcpy(pt->ap_OperatingFrequencyBand,"");
4104 strcpy(pt->ap_SupportedStandards,"");
4105 strcpy(pt->ap_OperatingStandards,"");
4106 strcpy(pt->ap_OperatingChannelBandwidth,"");
4107 pt->ap_BeaconPeriod=1;
4108 pt->ap_Noise=0;
4109 strcpy(pt->ap_BasicDataTransferRates,"");
4110 strcpy(pt->ap_SupportedDataTransferRates,"");
4111 pt->ap_DTIMPeriod=1;
4112 pt->ap_ChannelUtilization = 1;
4113 }
4114
4115 status = RETURN_OK;
4116 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4117
4118 return status;
4119}
4120
4121//----------------- AP HAL -------------------------------
4122
4123//>> Deprecated: used for old RDKB code.
4124INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4125{
4126 if (NULL == output_ulong || NULL == output_struct)
4127 return RETURN_ERR;
4128 *output_ulong = 0;
4129 *output_struct = NULL;
4130 return RETURN_OK;
4131}
4132
4133#ifdef HAL_NETLINK_IMPL
4134static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4135 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4136 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4137 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4138 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4139 char mac_addr[20];
4140 static int count=0;
4141 int rate=0;
4142
4143 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4144
4145 nla_parse(tb,
4146 NL80211_ATTR_MAX,
4147 genlmsg_attrdata(gnlh, 0),
4148 genlmsg_attrlen(gnlh, 0),
4149 NULL);
4150
4151 if(!tb[NL80211_ATTR_STA_INFO]) {
4152 fprintf(stderr, "sta stats missing!\n");
4153 return NL_SKIP;
4154 }
4155
4156
4157 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4158 fprintf(stderr, "failed to parse nested attributes!\n");
4159 return NL_SKIP;
4160 }
4161
4162 //devIndex starts from 1
4163 if( ++count == out->wifi_devIndex )
4164 {
4165 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4166 //Getting the mac addrress
4167 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4168
4169 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4170 fprintf(stderr, "failed to parse nested rate attributes!");
4171 return NL_SKIP;
4172 }
4173
4174 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4175 if(rinfo[NL80211_RATE_INFO_BITRATE])
4176 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4177 out->wifi_devTxRate = rate/10;
4178 }
4179
4180 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4181 fprintf(stderr, "failed to parse nested rate attributes!");
4182 return NL_SKIP;
4183 }
4184
4185 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4186 if(rinfo[NL80211_RATE_INFO_BITRATE])
4187 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4188 out->wifi_devRxRate = rate/10;
4189 }
4190 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4191 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4192
4193 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4194 count = 0; //starts the count for next cycle
4195 return NL_STOP;
4196 }
4197
4198 return NL_SKIP;
4199
4200}
4201#endif
4202
4203INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4204{
4205#ifdef HAL_NETLINK_IMPL
4206 Netlink nl;
4207 char if_name[10];
4208
4209 wifi_device_info_t info;
4210 info.wifi_devIndex = devIndex;
4211
4212 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4213
4214 nl.id = initSock80211(&nl);
4215
4216 if (nl.id < 0) {
4217 fprintf(stderr, "Error initializing netlink \n");
4218 return -1;
4219 }
4220
4221 struct nl_msg* msg = nlmsg_alloc();
4222
4223 if (!msg) {
4224 fprintf(stderr, "Failed to allocate netlink message.\n");
4225 nlfree(&nl);
4226 return -2;
4227 }
4228
4229 genlmsg_put(msg,
4230 NL_AUTO_PORT,
4231 NL_AUTO_SEQ,
4232 nl.id,
4233 0,
4234 NLM_F_DUMP,
4235 NL80211_CMD_GET_STATION,
4236 0);
4237
4238 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4239 nl_send_auto(nl.socket, msg);
4240 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4241 nl_recvmsgs(nl.socket, nl.cb);
4242 nlmsg_free(msg);
4243 nlfree(&nl);
4244
4245 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4246 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4247 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4248 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4249 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4250 return RETURN_OK;
4251#else
4252 //iw utility to retrieve station information
4253#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4254#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4255#define MACFILE "/tmp/wifi_AssoMac.txt"
4256#define TXRATEFILE "/tmp/wifi_txrate.txt"
4257#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4258 FILE *file = NULL;
4259 char if_name[10] = {'\0'};
4260 char pipeCmd[256] = {'\0'};
4261 char line[256];
4262 int count,device = 0;
4263
4264 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4265
4266 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4267 file = popen(pipeCmd, "r");
4268
4269 if(file == NULL)
4270 return RETURN_ERR; //popen failed
4271
4272 fgets(line, sizeof line, file);
4273 device = atoi(line);
4274 pclose(file);
4275
4276 if(device == 0)
4277 return RETURN_ERR; //No devices are connected
4278
4279 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4280 system(pipeCmd);
4281
4282 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4283
4284 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4285
4286 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4287
4288 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4289
4290 //devIndex starts from 1, ++count
4291 if((file = fopen(SIGNALFILE, "r")) != NULL )
4292 {
4293 for(count =0;fgets(line, sizeof line, file) != NULL;)
4294 {
4295 if (++count == devIndex)
4296 {
4297 output_struct->wifi_devSignalStrength = atoi(line);
4298 break;
4299 }
4300 }
4301 fclose(file);
4302 }
4303 else
4304 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4305
4306 if((file = fopen(MACFILE, "r")) != NULL )
4307 {
4308 for(count =0;fgets(line, sizeof line, file) != NULL;)
4309 {
4310 if (++count == devIndex)
4311 {
4312 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]);
4313 break;
4314 }
4315 }
4316 fclose(file);
4317 }
4318 else
4319 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4320
4321 if((file = fopen(TXRATEFILE, "r")) != NULL )
4322 {
4323 for(count =0;fgets(line, sizeof line, file) != NULL;)
4324 {
4325 if (++count == devIndex)
4326 {
4327 output_struct->wifi_devTxRate = atoi(line);
4328 break;
4329 }
4330 }
4331 fclose(file);
4332 }
4333 else
4334 fprintf(stderr,"fopen wifi_txrate.txt failed");
4335
4336 if((file = fopen(RXRATEFILE, "r")) != NULL)
4337 {
4338 for(count =0;fgets(line, sizeof line, file) != NULL;)
4339 {
4340 if (++count == devIndex)
4341 {
4342 output_struct->wifi_devRxRate = atoi(line);
4343 break;
4344 }
4345 }
4346 fclose(file);
4347 }
4348 else
4349 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4350
4351 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4352
4353 return RETURN_OK;
4354#endif
4355}
4356
4357INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4358{
4359 if (NULL == device)
4360 return RETURN_ERR;
4361 return RETURN_OK;
4362}
4363//<<
4364
4365
4366//--------------wifi_ap_hal-----------------------------
4367//enables CTS protection for the radio used by this AP
4368INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4369{
4370 //save config and Apply instantly
4371 return RETURN_ERR;
4372}
4373
4374// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4375INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4376{
developer463d39a2022-09-13 15:32:51 +08004377 char config_file[64] = {'\0'};
4378 char buf[64] = {'\0'};
4379 struct params list;
4380
4381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4382 list.name = "ht_coex";
4383 snprintf(buf, sizeof(buf), "%d", enable);
4384 list.value = buf;
4385
4386 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4387 wifi_hostapdWrite(config_file, &list, 1);
4388 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4389
4390 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4391
4392 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004393}
4394
4395//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4396INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4397{
developerea4bcce2022-09-13 15:26:13 +08004398 char config_file[MAX_BUF_SIZE] = {'\0'};
4399 char buf[MAX_BUF_SIZE] = {'\0'};
4400 struct params list;
4401
4402 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4403 if (threshold < 256 || threshold > 2346 )
4404 return RETURN_ERR;
4405 list.name = "fragm_threshold";
4406 snprintf(buf, sizeof(buf), "%d", threshold);
4407 list.value = buf;
4408
4409 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4410 wifi_hostapdWrite(config_file, &list, 1);
4411 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004412
developerea4bcce2022-09-13 15:26:13 +08004413 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004414
4415 return RETURN_OK;
4416}
4417
4418// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4419INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4420{
developer51a927d2022-09-13 15:42:22 +08004421 char config_file[64] = {'\0'};
4422 char cmd[128] = {'\0'};
4423 char buf[64] = {'\0'};
4424 char stbc_config[16] = {'\0'};
4425 wifi_band band;
4426 int iterator = 0;
4427 BOOL current_stbc = FALSE;
4428
4429 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4430
4431 band = wifi_index_to_band(radioIndex);
4432 if (band == band_invalid)
4433 return RETURN_ERR;
4434
4435 if (band == band_2_4)
4436 iterator = 1;
4437 else if (band == band_5)
4438 iterator = 2;
4439 else
4440 return RETURN_OK;
4441
4442 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4443
4444 // set ht and vht config
4445 for (int i = 0; i < iterator; i++) {
4446 memset(stbc_config, 0, sizeof(stbc_config));
4447 memset(cmd, 0, sizeof(cmd));
4448 memset(buf, 0, sizeof(buf));
4449 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4450 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4451 _syscmd(cmd, buf, sizeof(buf));
4452 if (strlen(buf) != 0)
4453 current_stbc = TRUE;
4454 if (current_stbc == STBC_Enable)
4455 continue;
4456
4457 if (STBC_Enable == TRUE) {
4458 // Append the STBC flags in capab config
4459 memset(cmd, 0, sizeof(cmd));
4460 if (i == 0)
4461 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4462 else
4463 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4464 _syscmd(cmd, buf, sizeof(buf));
4465 } else if (STBC_Enable == FALSE) {
4466 // Remove the STBC flags and remain other flags in capab
4467 memset(cmd, 0, sizeof(cmd));
4468 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4469 _syscmd(cmd, buf, sizeof(buf));
4470 memset(cmd, 0, sizeof(cmd));
4471 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4472 _syscmd(cmd, buf, sizeof(buf));
4473 }
4474 }
4475
4476 wifi_reloadAp(radioIndex);
4477
4478 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4479 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004480}
4481
4482// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4483INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4484{
developer54e6b9f2022-09-28 14:41:20 +08004485 char AMSDU_file_path[64] = {0};
4486
4487 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4488
4489 if(output_bool == NULL)
4490 return RETURN_ERR;
4491
4492 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4493
4494 if (access(AMSDU_file_path, F_OK) == 0)
4495 *output_bool = TRUE;
4496 else
4497 *output_bool = FALSE;
4498
4499 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4500 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004501}
4502
4503// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4504INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4505{
developer54e6b9f2022-09-28 14:41:20 +08004506 char cmd[64]={0};
4507 char buf[64]={0};
4508 char AMSDU_file_path[64] = {0};
4509
4510 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4511
4512 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4513 _syscmd(cmd, buf, sizeof(buf));
4514
4515 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4516 memset(cmd, 0, sizeof(cmd));
4517 if (amsduEnable == TRUE)
4518 sprintf(cmd, "touch %s", AMSDU_file_path);
4519 else
4520 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4521 _syscmd(cmd, buf, sizeof(buf));
4522
4523 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4524 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004525}
4526
4527//P2 // outputs the number of Tx streams
4528INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4529{
developer2de97692022-09-26 14:00:03 +08004530 char buf[8] = {0};
4531 char cmd[128] = {0};
4532
4533 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4534
4535 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4536 _syscmd(cmd, buf, sizeof(buf));
4537
4538 // if there is no record, output the max number of spatial streams
4539 if (strlen(buf) == 0) {
4540 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4541 _syscmd(cmd, buf, sizeof(buf));
4542 }
4543
4544 *output_int = (INT)strtol(buf, NULL, 10);
4545
4546 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4547
4548 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004549}
4550
4551//P2 // sets the number of Tx streams to an enviornment variable
4552INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4553{
developer2de97692022-09-26 14:00:03 +08004554 char cmd[128] = {0};
4555 char buf[128] = {0};
4556 char chain_mask_file[128] = {0};
4557 FILE *f = NULL;
4558
4559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4560
4561 if (numStreams == 0) {
4562 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4563 return RETURN_ERR;
4564 }
4565 wifi_setRadioEnable(radioIndex, FALSE);
4566 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4567 _syscmd(cmd, buf, sizeof(buf));
4568
4569 if (strlen(buf) > 0) {
4570 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4571 return RETURN_ERR;
4572 }
4573 wifi_setRadioEnable(radioIndex, TRUE);
4574
4575 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4576 f = fopen(chain_mask_file, "w");
4577 if (f == NULL) {
4578 fprintf(stderr, "%s: fopen failed.\n", __func__);
4579 return RETURN_ERR;
4580 }
4581 fprintf(f, "%d", numStreams);
4582 fclose(f);
4583 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4584 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004585}
4586
4587//P2 // outputs the number of Rx streams
4588INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4589{
developer2de97692022-09-26 14:00:03 +08004590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4591 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4592 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004593 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004594 }
4595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004596 return RETURN_OK;
4597}
4598
4599//P2 // sets the number of Rx streams to an enviornment variable
4600INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4601{
developer2de97692022-09-26 14:00:03 +08004602 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4603 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4604 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4605 return RETURN_ERR;
4606 }
4607 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004608 return RETURN_ERR;
4609}
4610
4611//Get radio RDG enable setting
4612INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4613{
4614 if (NULL == output_bool)
4615 return RETURN_ERR;
4616 *output_bool = TRUE;
4617 return RETURN_OK;
4618}
4619
4620//Get radio RDG enable setting
4621INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4622{
4623 if (NULL == output_bool)
4624 return RETURN_ERR;
4625 *output_bool = TRUE;
4626 return RETURN_OK;
4627}
4628
4629//Set radio RDG enable setting
4630INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4631{
4632 return RETURN_ERR;
4633}
4634
4635//Get radio ADDBA enable setting
4636INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4637{
4638 if (NULL == output_bool)
4639 return RETURN_ERR;
4640 *output_bool = TRUE;
4641 return RETURN_OK;
4642}
4643
4644//Set radio ADDBA enable setting
4645INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4646{
4647 return RETURN_ERR;
4648}
4649
4650//Get radio auto block ack enable setting
4651INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4652{
4653 if (NULL == output_bool)
4654 return RETURN_ERR;
4655 *output_bool = TRUE;
4656 return RETURN_OK;
4657}
4658
4659//Set radio auto block ack enable setting
4660INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4661{
4662 return RETURN_ERR;
4663}
4664
4665//Get radio 11n pure mode enable support
4666INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4667{
4668 if (NULL == output_bool)
4669 return RETURN_ERR;
4670 *output_bool = TRUE;
4671 return RETURN_OK;
4672}
4673
4674//Get radio 11n pure mode enable setting
4675INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4676{
4677 if (NULL == output_bool)
4678 return RETURN_ERR;
4679 *output_bool = TRUE;
4680 return RETURN_OK;
4681}
4682
4683//Set radio 11n pure mode enable setting
4684INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4685{
4686 return RETURN_ERR;
4687}
4688
4689//Get radio IGMP snooping enable setting
4690INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4691{
developer81bf2ed2022-09-13 15:31:14 +08004692 char cmd[128]={0};
4693 char buf[4]={0};
4694 bool bridge = FALSE, mac80211 = FALSE;
4695 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4696
4697 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004698 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004699
4700 *output_bool = FALSE;
4701
4702 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4703 _syscmd(cmd, buf, sizeof(buf));
4704 if (strncmp(buf, "1", 1) == 0)
4705 bridge = TRUE;
4706
4707 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4708 _syscmd(cmd, buf, sizeof(buf));
4709 if (strncmp(buf, "1", 1) == 0)
4710 mac80211 = TRUE;
4711
4712 if (bridge && mac80211)
4713 *output_bool = TRUE;
4714
4715 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004716 return RETURN_OK;
4717}
4718
4719//Set radio IGMP snooping enable setting
4720INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4721{
developer81bf2ed2022-09-13 15:31:14 +08004722 char cmd[128]={0};
4723 char buf[4]={0};
4724
4725 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4726
4727 // bridge
4728 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4729 _syscmd(cmd, buf, sizeof(buf));
4730
4731 // mac80211
4732 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4733 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4734 _syscmd(cmd, buf, sizeof(buf));
4735 }
4736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4737 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004738}
4739
4740//Get the Reset count of radio
4741INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4742{
4743 if (NULL == output_int)
4744 return RETURN_ERR;
4745 *output_int = (radioIndex==0)? 1: 3;
4746
4747 return RETURN_OK;
4748}
4749
4750
4751//---------------------------------------------------------------------------------------------------
4752//
4753// Additional Wifi AP level APIs used for Access Point devices
4754//
4755//---------------------------------------------------------------------------------------------------
4756
4757// creates a new ap and pushes these parameters to the hardware
4758INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4759{
4760 char buf[1024];
4761 char cmd[128];
4762
4763 if (NULL == essid)
4764 return RETURN_ERR;
4765
4766 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4767 _syscmd(cmd, buf, sizeof(buf));
4768
4769 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4770 _syscmd(cmd, buf, sizeof(buf));
4771
4772 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4773
4774 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4775 _syscmd(cmd, buf, sizeof(buf));
4776
4777 return RETURN_OK;
4778}
4779
4780// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4781INT wifi_deleteAp(INT apIndex)
4782{
4783 char buf[1024];
4784 char cmd[128];
4785
4786 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4787 _syscmd(cmd, buf, sizeof(buf));
4788
4789 wifi_removeApSecVaribles(apIndex);
4790
4791 return RETURN_OK;
4792}
4793
4794// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4795INT wifi_getApName(INT apIndex, CHAR *output_string)
4796{
4797 if(NULL == output_string)
4798 return RETURN_ERR;
4799
4800 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4801 return RETURN_OK;
4802}
4803
4804// Outputs the index number in that corresponds to the SSID string
4805INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4806{
4807 CHAR *pos = NULL;
4808
4809 *output_int = -1;
4810 pos = strstr(inputSsidString, AP_PREFIX);
4811 if(pos)
4812 {
4813 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4814 return RETURN_OK;
4815 }
4816 return RETURN_ERR;
4817}
4818
4819INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4820{
4821 return wifi_getIndexFromName(inputSsidString, output_int);
4822}
4823
4824// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4825INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4826{
4827 char buf[MAX_BUF_SIZE] = {0};
4828 char cmd[MAX_CMD_SIZE] = {0};
4829 char config_file[MAX_BUF_SIZE] = {0};
4830
4831 if(NULL == output_string)
4832 return RETURN_ERR;
4833
4834 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4835 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4836 if((strcmp(buf,"3")==0))
4837 snprintf(output_string, 32, "WPAand11i");
4838 else if((strcmp(buf,"2")==0))
4839 snprintf(output_string, 32, "11i");
4840 else if((strcmp(buf,"1")==0))
4841 snprintf(output_string, 32, "WPA");
4842 else
4843 snprintf(output_string, 32, "None");
4844
4845 return RETURN_OK;
4846}
4847
4848// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4849INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4850{
4851 char config_file[MAX_BUF_SIZE] = {0};
4852 struct params list;
4853
4854 if (NULL == beaconTypeString)
4855 return RETURN_ERR;
4856 list.name = "wpa";
4857 list.value = "0";
4858
4859 if((strcmp(beaconTypeString,"WPAand11i")==0))
4860 list.value="3";
4861 else if((strcmp(beaconTypeString,"11i")==0))
4862 list.value="2";
4863 else if((strcmp(beaconTypeString,"WPA")==0))
4864 list.value="1";
4865
4866 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4867 wifi_hostapdWrite(config_file, &list, 1);
4868 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4869 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4870 return RETURN_OK;
4871}
4872
4873// sets the beacon interval on the hardware for this AP
4874INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4875{
developer5f222492022-09-13 15:21:52 +08004876 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4877 struct params params={'\0'};
4878 char buf[MAX_BUF_SIZE] = {'\0'};
4879 char config_file[MAX_BUF_SIZE] = {'\0'};
4880
4881 params.name = "beacon_int";
4882 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4883 params.value = buf;
4884
4885 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4886 wifi_hostapdWrite(config_file, &params, 1);
4887
4888 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4889 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4890 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004891}
4892
4893INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4894{
4895 //save config and apply instantly
4896 return RETURN_ERR;
4897}
4898
4899// Get the packet size threshold supported.
4900INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4901{
4902 //save config and apply instantly
4903 if (NULL == output_bool)
4904 return RETURN_ERR;
4905 *output_bool = FALSE;
4906 return RETURN_OK;
4907}
4908
4909// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4910INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4911{
4912 char cmd[128];
4913 char buf[512];
4914
4915 if (threshold > 0)
4916 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4917 else
4918 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4919 _syscmd(cmd, buf, sizeof(buf));
4920
4921 return RETURN_OK;
4922}
4923
4924// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4925INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4926{
4927 if (NULL == output_string)
4928 return RETURN_ERR;
4929 snprintf(output_string, 32, "TKIPandAESEncryption");
4930 return RETURN_OK;
4931
4932}
4933
4934// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4935INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4936{
4937 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4938 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4939
4940 if(NULL == output_string)
4941 return RETURN_ERR;
4942
4943 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4944 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4945
4946 if(strcmp(buf,"0")==0)
4947 {
4948 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4949 snprintf(output_string, 32, "None");
4950 return RETURN_OK;
4951 }
4952 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4953 param_name = "rsn_pairwise";
4954 else if((strcmp(buf,"1")==0))
4955 param_name = "wpa_pairwise";
4956 else
4957 return RETURN_ERR;
4958 memset(output_string,'\0',32);
4959 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4960 wifi_hostapdRead(config_file,param_name,output_string,32);
4961 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4962
4963 if(strcmp(output_string,"TKIP") == 0)
4964 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4965 else if(strcmp(output_string,"CCMP") == 0)
4966 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4967 else if(strcmp(output_string,"TKIP CCMP") == 0)
4968 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4969
4970 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4971 return RETURN_OK;
4972}
4973
4974// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4975INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4976{
4977 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4978 struct params params={'\0'};
4979 char output_string[32];
4980 char config_file[MAX_BUF_SIZE] = {0};
4981
4982 memset(output_string,'\0',32);
4983 wifi_getApWpaEncryptionMode(apIndex,output_string);
4984
4985 if(strcmp(encMode, "TKIPEncryption") == 0)
4986 params.value = "TKIP";
4987 else if(strcmp(encMode,"AESEncryption") == 0)
4988 params.value = "CCMP";
4989 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
4990 params.value = "TKIP CCMP";
4991
4992 if((strcmp(output_string,"WPAand11i")==0))
4993 {
4994 params.name = "wpa_pairwise";
4995 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4996 wifi_hostapdWrite(config_file, &params, 1);
4997 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4998
4999 params.name,"rsn_pairwise";
5000 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5001 wifi_hostapdWrite(config_file, &params, 1);
5002 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5003
5004 return RETURN_OK;
5005 }
5006 else if((strcmp(output_string,"11i")==0))
5007 {
5008 params.name = "rsn_pairwise";
5009 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5010 wifi_hostapdWrite(config_file, &params, 1);
5011 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5012 return RETURN_OK;
5013 }
5014 else if((strcmp(output_string,"WPA")==0))
5015 {
5016 params.name = "wpa_pairwise";
5017 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5018 wifi_hostapdWrite(config_file, &params, 1);
5019 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5020 return RETURN_OK;
5021 }
5022
5023 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5024 return RETURN_OK;
5025}
5026
5027// deletes internal security varable settings for this ap
5028INT wifi_removeApSecVaribles(INT apIndex)
5029{
5030 //TODO: remove the entry in hostapd config file
5031 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5032 //_syscmd(cmd, buf, sizeof(buf));
5033
5034 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5035 //_syscmd(cmd, buf, sizeof(buf));
5036 return RETURN_ERR;
5037}
5038
5039// changes the hardware settings to disable encryption on this ap
5040INT wifi_disableApEncryption(INT apIndex)
5041{
5042 //Apply instantly
5043 return RETURN_ERR;
5044}
5045
5046// set the authorization mode on this ap
5047// mode mapping as: 1: open, 2: shared, 4:auto
5048INT wifi_setApAuthMode(INT apIndex, INT mode)
5049{
developeraf95c502022-09-13 16:18:22 +08005050 struct params params={0};
5051 char config_file[64] = {0};
5052 int ret;
5053
5054 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5055
5056 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5057 params.name = "auth_algs";
5058
5059 if (mode & 1 && mode & 2)
5060 params.value = "3";
5061 else if (mode & 2)
5062 params.value = "2";
5063 else if (mode & 1)
5064 params.value = "1";
5065 else
5066 params.value = "0";
5067
5068 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5069 wifi_hostapdWrite(config_file, &params, 1);
5070 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5071 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5072
5073 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005074}
5075
5076// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5077INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5078{
5079 //save to wifi config, and wait for wifi restart to apply
5080 struct params params={'\0'};
5081 char config_file[MAX_BUF_SIZE] = {0};
5082 int ret;
5083
5084 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5085 if(authMode == NULL)
5086 return RETURN_ERR;
5087
5088 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5089 params.name = "wpa_key_mgmt";
5090
5091 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5092 params.value = "WPA-PSK";
5093 else if(strcmp(authMode,"EAPAuthentication") == 0)
5094 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005095 else if (strcmp(authMode, "SAEAuthentication") == 0)
5096 params.value = "SAE";
5097 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5098 params.value = "WPA-EAP-SUITE-B-192";
developer06a01d92022-09-07 16:32:39 +08005099 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5100 return RETURN_OK; //This is taken careof in beaconType
5101
5102 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5103 ret=wifi_hostapdWrite(config_file,&params,1);
5104 if(!ret)
5105 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5106 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5107
5108 return ret;
5109}
5110
5111// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5112INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5113{
5114 //save to wifi config, and wait for wifi restart to apply
5115 char BeaconType[50] = {0};
5116 char config_file[MAX_BUF_SIZE] = {0};
5117
5118 *authMode = 0;
5119 wifi_getApBeaconType(apIndex,BeaconType);
5120 printf("%s____%s \n",__FUNCTION__,BeaconType);
5121
5122 if(strcmp(BeaconType,"None") == 0)
5123 strcpy(authMode,"None");
5124 else
5125 {
5126 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5127 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5128 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5129 if(strcmp(authMode,"WPA-PSK") == 0)
5130 strcpy(authMode,"SharedAuthentication");
5131 else if(strcmp(authMode,"WPA-EAP") == 0)
5132 strcpy(authMode,"EAPAuthentication");
5133 }
5134
5135 return RETURN_OK;
5136}
5137
5138// Outputs the number of stations associated per AP
5139INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5140{
5141 char cmd[128]={0};
5142 char buf[128]={0};
5143 BOOL status = false;
5144
5145 if(apIndex > MAX_APS)
5146 return RETURN_ERR;
5147
5148 wifi_getApEnable(apIndex,&status);
5149 if (!status)
5150 return RETURN_OK;
5151
5152 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5153 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5154 _syscmd(cmd, buf, sizeof(buf));
5155 sscanf(buf,"%lu", output_ulong);
5156
5157 return RETURN_OK;
5158}
5159
5160// manually removes any active wi-fi association with the device specified on this ap
5161INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5162{
5163 char buf[126]={'\0'};
5164
5165 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5166 system(buf);
5167
5168 return RETURN_OK;
5169}
5170
5171// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5172INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5173{
5174 if(NULL == output_int)
5175 return RETURN_ERR;
5176 *output_int = apIndex%2;
5177 return RETURN_OK;
5178}
5179
5180// sets the radio index for the specific ap
5181INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5182{
5183 //set to config only and wait for wifi reset to apply settings
5184 return RETURN_ERR;
5185}
5186
5187// Get the ACL MAC list per AP
5188INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5189{
5190 char cmd[MAX_CMD_SIZE]={'\0'};
5191 int ret = 0;
5192
5193 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5194 ret = _syscmd(cmd,macArray,buf_size);
5195 if (ret != 0)
5196 return RETURN_ERR;
5197
5198 return RETURN_OK;
5199}
5200
developere6aafda2022-09-13 14:59:28 +08005201INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5202{
5203 char cmd[MAX_CMD_SIZE]={'\0'};
5204 int ret = 0;
5205
5206 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5207 ret = _syscmd(cmd,macArray,buf_size);
5208 if (ret != 0)
5209 return RETURN_ERR;
5210
5211 return RETURN_OK;
5212}
5213
5214
developer06a01d92022-09-07 16:32:39 +08005215// Get the list of stations associated per AP
5216INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5217{
5218 char cmd[128];
5219
5220 if(apIndex > 3) //Currently supporting apIndex upto 3
5221 return RETURN_ERR;
5222 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5223 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5224 _syscmd(cmd, macArray, buf_size);
5225
5226 return RETURN_OK;
5227}
5228
5229// adds the mac address to the filter list
5230//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5231INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5232{
5233 char cmd[MAX_CMD_SIZE]={'\0'};
5234 char buf[MAX_BUF_SIZE]={'\0'};
5235
5236#if 0
5237 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5238 if(_syscmd(cmd,buf,sizeof(buf)))
5239 return RETURN_ERR;
5240#endif
5241 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5242 if(_syscmd(cmd,buf,sizeof(buf)))
5243 return RETURN_ERR;
5244
5245 return RETURN_OK;
5246}
5247
5248// deletes the mac address from the filter list
5249//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5250INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5251{
5252 char cmd[MAX_CMD_SIZE]={'\0'};
5253 char buf[MAX_BUF_SIZE]={'\0'};
5254
5255#if 0
5256 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5257 if(_syscmd(cmd,buf,sizeof(buf)))
5258 return RETURN_ERR;
5259
5260#endif
5261 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5262 if(_syscmd(cmd,buf,sizeof(buf)))
5263 return RETURN_ERR;
5264
5265 return RETURN_OK;
5266}
5267
5268// outputs the number of devices in the filter list
5269INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5270{
developere6aafda2022-09-13 14:59:28 +08005271 char cmd[MAX_BUF_SIZE]={0};
5272 char buf[MAX_CMD_SIZE]={0};
5273
5274 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5275 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005276 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005277
5278 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5279 _syscmd(cmd, buf, sizeof(buf));
5280
5281 *output_uint = atoi(buf);
5282
5283 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5284 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005285}
5286
5287INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5288{
5289 char cmd[128]={'\0'};
5290 char buf[128]={'\0'};
5291
5292 if(strcmp(action,"DENY")==0)
5293 {
5294 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5295 system(buf);
5296 return RETURN_OK;
5297 }
5298
5299 if(strcmp(action,"ALLOW")==0)
5300 {
5301 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5302 system(buf);
5303 return RETURN_OK;
5304 }
5305
5306 return RETURN_ERR;
5307
5308}
5309
5310// enable kick for devices on acl black list
5311INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5312{
5313 char aclArray[512] = {0}, *acl = NULL;
5314 char assocArray[512] = {0}, *asso = NULL;
5315
developere6aafda2022-09-13 14:59:28 +08005316 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005317 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5318
5319 // if there are no devices connected there is nothing to do
5320 if (strlen(assocArray) < 17)
5321 return RETURN_OK;
5322
5323 if (enable == TRUE)
5324 {
5325 //kick off the MAC which is in ACL array (deny list)
5326 acl = strtok(aclArray, "\r\n");
5327 while (acl != NULL) {
5328 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5329 wifi_kickApAssociatedDevice(apIndex, acl);
5330
5331 acl = strtok(NULL, "\r\n");
5332 }
developere6aafda2022-09-13 14:59:28 +08005333 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005334 }
5335 else
5336 {
developere6aafda2022-09-13 14:59:28 +08005337 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005338 }
5339
5340#if 0
5341 //TODO: need to revisit below implementation
5342 char aclArray[512]={0}, *acl=NULL;
5343 char assocArray[512]={0}, *asso=NULL;
5344 char buf[256]={'\0'};
5345 char action[10]={'\0'};
5346 FILE *fr=NULL;
5347 char interface[10]={'\0'};
5348 char config_file[MAX_BUF_SIZE] = {0};
5349
5350 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5351 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5352 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5353 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5354
5355 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5356 system(buf);
5357 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5358 system(buf);
5359 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5360 system(buf);
5361 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5362 system(buf);
5363 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5364 system(buf);
5365
5366 if ( enable == TRUE )
5367 {
5368 int device_count=0;
5369 strcpy(action,"DENY");
5370 //kick off the MAC which is in ACL array (deny list)
5371 acl = strtok (aclArray,",");
5372 while (acl != NULL) {
5373 if(strlen(acl)>=17)
5374 {
5375 apply_rules(apIndex, acl,action,interface);
5376 device_count++;
5377 //Register mac to be blocked ,in syscfg.db persistent storage
5378 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5379 system(buf);
5380 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5381 system(buf);
5382 system("syscfg commit");
5383
5384 wifi_kickApAssociatedDevice(apIndex, acl);
5385 }
5386 acl = strtok (NULL, ",");
5387 }
5388 }
5389 else
5390 {
5391 int device_count=0;
5392 char cmdmac[20]={'\0'};
5393 strcpy(action,"ALLOW");
5394 //kick off the MAC which is not in ACL array (allow list)
5395 acl = strtok (aclArray,",");
5396 while (acl != NULL) {
5397 if(strlen(acl)>=17)
5398 {
5399 apply_rules(apIndex, acl,action,interface);
5400 device_count++;
5401 //Register mac to be Allowed ,in syscfg.db persistent storage
5402 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5403 system(buf);
5404 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5405 system(buf);
5406 sprintf(cmdmac,"%s",acl);
5407 }
5408 acl = strtok (NULL, ",");
5409 }
5410 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5411 system(buf);
5412
5413 //Disconnect the mac which is not in ACL
5414 asso = strtok (assocArray,",");
5415 while (asso != NULL) {
5416 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5417 wifi_kickApAssociatedDevice(apIndex, asso);
5418 asso = strtok (NULL, ",");
5419 }
5420 }
5421#endif
5422 return RETURN_OK;
5423}
5424
5425INT wifi_setPreferPrivateConnection(BOOL enable)
5426{
5427 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5428 char buf[1024] = {0};
5429
5430 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5431 if(enable == TRUE)
5432 {
5433 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5434 sprintf(buf,"ifconfig %s down" ,interface_name);
5435 system(buf);
5436 memset(buf,0,sizeof(buf));
5437 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5438 sprintf(buf,"ifconfig %s down" ,interface_name);
5439 system(buf);
5440 }
5441 else
5442 {
5443 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5444 if(strcmp(ssid_cur_value,"1") == 0)
5445 wifi_RestartPrivateWifi_5G();
5446 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5447 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5448 if(strcmp(ssid_cur_value,"1") == 0)
5449 wifi_RestartHostapd_2G();
5450 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5451 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5452 if(strcmp(ssid_cur_value,"1") == 0)
5453 wifi_RestartHostapd_5G();
5454 }
5455 return RETURN_OK;
5456}
5457
5458// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5459INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5460{
5461 int items = 1;
5462 struct params list[2];
5463 char buf[MAX_BUF_SIZE] = {0};
5464 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005465 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005466
5467 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005468
developer10adcc12022-09-13 14:39:17 +08005469 if (filterMode == 0) {
5470 sprintf(buf, "%d", 0);
5471 list[0].value = buf;
5472
5473 char cmd[128], rtn[128];
5474 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5475 _syscmd(cmd, rtn, sizeof(rtn));
5476 memset(cmd,0,sizeof(cmd));
5477 // Delete deny_mac_file in hostapd configuration
5478 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5479 _syscmd(cmd, rtn, sizeof(rtn));
5480 }
5481 else if (filterMode == 1) {
5482 sprintf(buf, "%d", filterMode);
5483 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005484 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5485 list[1].name = "accept_mac_file";
5486 list[1].value = acl_file;
5487 items = 2;
developer10adcc12022-09-13 14:39:17 +08005488 } else if (filterMode == 2) {
5489 //TODO: deny_mac_file
5490 sprintf(buf, "%d", 0);
5491 list[0].value = buf;
5492 list[1].name = "deny_mac_file";
5493 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5494 list[1].value = deny_file;
5495 items = 2;
5496 } else {
5497 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005498 }
developer10adcc12022-09-13 14:39:17 +08005499
developer06a01d92022-09-07 16:32:39 +08005500 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5501 wifi_hostapdWrite(config_file, list, items);
5502
5503 return RETURN_OK;
5504
5505#if 0
5506 if(apIndex==0 || apIndex==1)
5507 {
5508 //set the filtermode
5509 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5510 system(buf);
5511 system("syscfg commit");
5512
5513 if(filterMode==0)
5514 {
5515 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5516 system(buf);
5517 return RETURN_OK;
5518 }
5519 }
5520 return RETURN_OK;
5521#endif
5522}
5523
5524// 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.
5525INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5526{
5527 return RETURN_ERR;
5528}
5529
5530// gets the vlan ID for this ap from an internal enviornment variable
5531INT wifi_getApVlanID(INT apIndex, INT *output_int)
5532{
5533 if(apIndex=0)
5534 {
5535 *output_int=100;
5536 return RETURN_OK;
5537 }
5538
5539 return RETURN_ERR;
5540}
5541
5542// sets the vlan ID for this ap to an internal enviornment variable
5543INT wifi_setApVlanID(INT apIndex, INT vlanId)
5544{
5545 //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)
5546 return RETURN_ERR;
5547}
5548
5549// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5550INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5551{
5552 snprintf(bridgeName, 32, "brlan0");
5553 snprintf(IP, 32, "10.0.0.1");
5554 snprintf(subnet, 32, "255.255.255.0");
5555
5556 return RETURN_OK;
5557}
5558
5559//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5560INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5561{
5562 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5563 return RETURN_ERR;
5564}
5565
5566// reset the vlan configuration for this ap
5567INT wifi_resetApVlanCfg(INT apIndex)
5568{
developerf5fef612022-09-20 19:38:26 +08005569 char original_config_file[64] = {0};
5570 char current_config_file[64] = {0};
5571 char buf[64] = {0};
5572 char cmd[64] = {0};
5573 char vlan_file[64] = {0};
5574 char vlan_tagged_interface[16] = {0};
5575 char vlan_bridge[16] = {0};
5576 char vlan_naming[16] = {0};
5577 struct params list[4] = {0};
5578 wifi_band band;
5579
5580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5581
5582 band = wifi_index_to_band(apIndex);
5583 if (band == band_2_4)
5584 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5585 else if (band = band_5)
5586 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5587 else if (band = band_6)
5588 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5589
5590 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5591
5592 if (strlen(vlan_file) == 0)
5593 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005594
developerf5fef612022-09-20 19:38:26 +08005595 // The file should exist or this vap would not work.
5596 if (access(vlan_file, F_OK) != 0) {
5597 sprintf(cmd, "touch %s", vlan_file);
5598 _syscmd(cmd, buf, sizeof(buf));
5599 }
5600 list[0].name = "vlan_file";
5601 list[0].value = vlan_file;
5602
5603 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5604 list[1].name = "vlan_tagged_interface";
5605 list[1].value = vlan_tagged_interface;
5606
5607 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5608 list[2].name = "vlan_bridge";
5609 list[2].value = vlan_bridge;
5610
5611 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5612 list[3].name = "vlan_naming";
5613 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005614
developerf5fef612022-09-20 19:38:26 +08005615 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5616 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005617 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005618 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005619
developerf5fef612022-09-20 19:38:26 +08005620 // restart this ap
5621 wifi_setApEnable(apIndex, FALSE);
5622 wifi_setApEnable(apIndex, TRUE);
5623
5624 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5625
5626 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005627}
5628
5629// 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.
5630INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5631{
5632 return RETURN_ERR;
5633}
5634
5635// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5636INT wifi_startHostApd()
5637{
5638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5639 system("systemctl start hostapd.service");
5640 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5641 return RETURN_OK;
5642 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5643}
5644
5645// stops hostapd
5646INT wifi_stopHostApd()
5647{
5648 char cmd[128] = {0};
5649 char buf[128] = {0};
5650
5651 sprintf(cmd,"systemctl stop hostapd");
5652 _syscmd(cmd, buf, sizeof(buf));
5653
5654 return RETURN_OK;
5655}
5656
5657// restart hostapd dummy function
5658INT wifi_restartHostApd()
5659{
5660 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5661 system("systemctl restart hostapd-global");
5662 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5663
5664 return RETURN_OK;
5665}
5666
5667static int align_hostapd_config(int index)
5668{
5669 ULONG lval;
5670 wifi_getRadioChannel(index%2, &lval);
5671 wifi_setRadioChannel(index%2, lval);
5672}
5673
5674// sets the AP enable status variable for the specified ap.
5675INT wifi_setApEnable(INT apIndex, BOOL enable)
5676{
5677 char config_file[MAX_BUF_SIZE] = {0};
5678 char cmd[MAX_CMD_SIZE] = {0};
5679 char buf[MAX_BUF_SIZE] = {0};
5680 BOOL status;
5681
5682 wifi_getApEnable(apIndex,&status);
5683 if (enable == status)
5684 return RETURN_OK;
5685
5686 if (enable == TRUE) {
5687 int radioIndex = apIndex % NUMBER_OF_RADIOS;
5688 align_hostapd_config(apIndex);
5689 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5690 //Hostapd will bring up this interface
5691 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5692 _syscmd(cmd, buf, sizeof(buf));
5693 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5694 _syscmd(cmd, buf, sizeof(buf));
5695 }
5696 else {
5697 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5698 _syscmd(cmd, buf, sizeof(buf));
5699 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5700 _syscmd(cmd, buf, sizeof(buf));
5701 }
5702 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5703 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5704 _syscmd(cmd, buf, sizeof(buf));
5705 //Wait for wifi up/down to apply
5706 return RETURN_OK;
5707}
5708
5709// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5710INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5711{
5712 char cmd[MAX_CMD_SIZE] = {'\0'};
5713 char buf[MAX_BUF_SIZE] = {'\0'};
5714
5715 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5716 return RETURN_ERR;
5717
5718 *output_bool = 0;
5719
5720 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5721 {
developer70490032022-09-13 15:45:20 +08005722 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005723 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5724 }
5725
5726 return RETURN_OK;
5727}
5728
5729// Outputs the AP "Enabled" "Disabled" status from driver
5730INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5731{
5732 char cmd[128] = {0};
5733 char buf[128] = {0};
5734 BOOL output_bool;
5735
5736 if ( NULL == output_string)
5737 return RETURN_ERR;
5738 wifi_getApEnable(apIndex,&output_bool);
5739
5740 if(output_bool == 1)
5741 snprintf(output_string, 32, "Up");
5742 else
5743 snprintf(output_string, 32, "Disable");
5744
5745 return RETURN_OK;
5746}
5747
5748//Indicates whether or not beacons include the SSID name.
5749// outputs a 1 if SSID on the AP is enabled, else outputs 0
5750INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5751{
5752 //get the running status
5753 char config_file[MAX_BUF_SIZE] = {0};
5754 char buf[16] = {0};
5755
5756 if (!output)
5757 return RETURN_ERR;
5758
5759 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5760 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5761 *output = (strncmp("0",buf,1) == 0);
5762
5763 return RETURN_OK;
5764}
5765
5766// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5767INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5768{
5769 //store the config, apply instantly
5770 char config_file[MAX_BUF_SIZE] = {0};
5771 struct params list;
5772
5773 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5774 list.name = "ignore_broadcast_ssid";
5775 list.value = enable?"0":"1";
5776
5777 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5778 wifi_hostapdWrite(config_file, &list, 1);
5779 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5780 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005781 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005782 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5783
5784 return RETURN_OK;
5785}
5786
5787//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5788INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5789{
5790 //get the running status
5791 if(!output_uint)
5792 return RETURN_ERR;
5793 *output_uint=16;
5794 return RETURN_OK;
5795}
5796
5797INT wifi_setApRetryLimit(INT apIndex, UINT number)
5798{
5799 //apply instantly
5800 return RETURN_ERR;
5801}
5802
5803//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5804INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5805{
5806 if(!output)
5807 return RETURN_ERR;
5808 *output=TRUE;
5809 return RETURN_OK;
5810}
5811
5812//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5813INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5814{
5815 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005816 char cmd[128] = {0};
5817 char buf[128] = {0};
5818 int max_radio_num = 0, radioIndex = 0;
developer3ab38042022-09-13 14:17:03 +08005819
developer0b246d12022-09-30 15:24:20 +08005820 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005821
developer0b246d12022-09-30 15:24:20 +08005822 wifi_getMaxRadioNumber(&max_radio_num);
5823 radioIndex = apIndex % max_radio_num;
5824 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", radioIndex);
5825 _syscmd(cmd,buf, sizeof(buf));
5826
5827 if (strlen(buf) > 0)
5828 *output = true;
5829
5830 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005831
developer06a01d92022-09-07 16:32:39 +08005832 return RETURN_OK;
5833}
5834
5835//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5836INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5837{
5838 //get the running status from driver
5839 if(!output)
5840 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005841
5842 char config_file[MAX_BUF_SIZE] = {0};
5843 char buf[16] = {0};
5844
5845 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5846 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5847 if (strncmp("1",buf,1) == 0)
5848 *output = TRUE;
5849 else
5850 *output = FALSE;
5851
developer06a01d92022-09-07 16:32:39 +08005852 return RETURN_OK;
5853}
5854
5855// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5856INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5857{
5858 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005859 char config_file[MAX_BUF_SIZE] = {0};
5860 struct params list;
5861
5862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5863 list.name = "wmm_enabled";
5864 list.value = enable?"1":"0";
5865
5866 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5867 wifi_hostapdWrite(config_file, &list, 1);
5868 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5869 wifi_reloadAp(apIndex);
5870 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5871
5872 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005873}
5874
5875//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.
5876INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5877{
5878 //get the running status from driver
5879 if(!output)
5880 return RETURN_ERR;
5881 *output=TRUE;
5882 return RETURN_OK;
5883}
5884
5885// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5886INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5887{
5888 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005889 char config_file[MAX_BUF_SIZE] = {0};
5890 struct params list;
5891
5892 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5893 list.name = "uapsd_advertisement_enabled";
5894 list.value = enable?"1":"0";
5895
5896 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5897 wifi_hostapdWrite(config_file, &list, 1);
5898 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5899 wifi_reloadAp(apIndex);
5900 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5901
5902 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005903}
5904
developer6daeb3f2022-09-30 13:36:39 +08005905// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08005906INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5907{
developer6daeb3f2022-09-30 13:36:39 +08005908 // assume class 0->BE, 1->BK, 2->VI, 3->VO
5909 char cmd[128] = {0};
5910 char buf[128] = {0};
5911 char ack_filepath[128] = {0};
5912 uint16_t bitmap = 0;
5913 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
5914 FILE *f = NULL;
5915
5916 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5917
5918 // Get current setting
5919 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
5920 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
5921 _syscmd(cmd, buf, sizeof(buf));
5922 if (strlen(buf) > 0)
5923 bitmap = strtoul(buf, NULL, 10);
5924
5925 bitmap = strtoul(buf, NULL, 10);
5926
5927 if (ackPolicy == TRUE) { // True, unset this class
5928 bitmap &= ~class_map[class];
5929 } else { // False, set this class
5930 bitmap |= class_map[class];
5931 }
5932
5933 f = fopen(ack_filepath, "w");
5934 if (f == NULL) {
5935 fprintf(stderr, "%s: fopen failed\n", __func__);
5936 return RETURN_ERR;
5937 }
5938 fprintf(f, "%hu", bitmap);
5939 fclose(f);
5940
5941 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
5942 _syscmd(cmd, buf, sizeof(buf));
5943
5944 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5945 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005946}
5947
5948//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.
5949INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5950{
5951 //get the running status from driver
5952 if(!output_uint)
5953 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005954
5955 char output[16]={'\0'};
5956 char config_file[MAX_BUF_SIZE] = {0};
5957
5958 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5959 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5960 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5961 else {
5962 int device_num = atoi(output);
5963 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5964 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5965 return RETURN_ERR;
5966 }
5967 else {
5968 *output_uint = device_num;
5969 }
5970 }
5971
developer06a01d92022-09-07 16:32:39 +08005972 return RETURN_OK;
5973}
5974
5975INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5976{
5977 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005978 char str[MAX_BUF_SIZE]={'\0'};
5979 char cmd[MAX_CMD_SIZE]={'\0'};
5980 struct params params;
5981 char config_file[MAX_BUF_SIZE] = {0};
5982
5983 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5984 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5985 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5986 return RETURN_ERR;
5987 }
5988 sprintf(str, "%d", number);
5989 params.name = "max_num_sta";
5990 params.value = str;
5991
5992 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5993 int ret = wifi_hostapdWrite(config_file, &params, 1);
5994 if (ret) {
5995 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5996 ,__func__, ret);
5997 }
5998
5999 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6000 if (ret) {
6001 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6002 ,__func__, ret);
6003 }
6004 wifi_reloadAp(apIndex);
6005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6006
6007 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006008}
6009
6010//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.
6011INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6012{
6013 //get the current threshold
6014 if(!output_uint)
6015 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006016 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6017 if (*output_uint == 0)
6018 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006019 return RETURN_OK;
6020}
6021
6022INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6023{
6024 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006025 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6026 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006027 return RETURN_ERR;
6028}
6029
6030//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.
6031INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6032{
6033 if(!output_uint)
6034 return RETURN_ERR;
6035 *output_uint = 3;
6036 return RETURN_OK;
6037}
6038
6039//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6040INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6041{
6042 if(!output_uint)
6043 return RETURN_ERR;
6044 *output_uint = 3;
6045 return RETURN_OK;
6046}
6047
6048//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.
6049INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6050{
6051 if(!output_in_seconds)
6052 return RETURN_ERR;
6053 *output_in_seconds = 0;
6054 return RETURN_OK;
6055}
6056
6057//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
6058INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6059{
6060 if(!output || apIndex>=MAX_APS)
6061 return RETURN_ERR;
6062 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006063 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006064 return RETURN_OK;
6065}
6066
6067//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6068INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6069{
developer587c1b62022-09-27 15:58:59 +08006070 char config_file[128] = {0};
6071 char wpa[16] = {0};
6072 char key_mgmt[64] = {0};
6073 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006074 if (!output)
6075 return RETURN_ERR;
6076
6077 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006078 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006079
developer587c1b62022-09-27 15:58:59 +08006080 strcpy(output, "None");//Copying "None" to output string for default case
6081 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6082 if (strstr(key_mgmt, "WPA-PSK")) {
developer517a9792022-10-05 19:37:42 +08006083 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006084 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006085 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006086 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006087 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006088 snprintf(output, 32, "WPA-WPA2-Personal");
6089
6090 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006091 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006092 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006093 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006094 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006095 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006096 snprintf(output, 32, "WPA-WPA2-Enterprise");
6097 } else if (strstr(key_mgmt, "SAE")) {
6098 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
6099 int disable = strtol(buf, NULL, 16);
6100 if (disable & 0x1)
6101 snprintf(output, 32, "WPA3-Personal");
6102 else
6103 snprintf(output, 32, "WPA3-Transition");
6104 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6105 snprintf(output, 32, "WPA3-Enterprise");
6106 }
developer06a01d92022-09-07 16:32:39 +08006107
6108 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6109 return RETURN_OK;
6110#if 0
6111 //TODO: need to revisit below implementation
6112 char securityType[32], authMode[32];
6113 int enterpriseMode=0;
6114
6115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6116 if(!output)
6117 return RETURN_ERR;
6118
6119 wifi_getApBeaconType(apIndex, securityType);
6120 strcpy(output,"None");//By default, copying "None" to output string
6121 if (strncmp(securityType,"None", strlen("None")) == 0)
6122 return RETURN_OK;
6123
6124 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6125 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6126
6127 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6128 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6129 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6130 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6131 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6132 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6133 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6134
6135 return RETURN_OK;
6136#endif
6137}
6138
6139INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6140{
6141 char securityType[32];
6142 char authMode[32];
6143
6144 //store settings and wait for wifi up to apply
6145 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6146 if(!encMode)
6147 return RETURN_ERR;
6148
developer06a01d92022-09-07 16:32:39 +08006149 if (strcmp(encMode, "None")==0)
6150 {
6151 strcpy(securityType,"None");
6152 strcpy(authMode,"None");
6153 }
6154 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6155 {
6156 strcpy(securityType,"WPAand11i");
6157 strcpy(authMode,"PSKAuthentication");
6158 }
6159 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6160 {
6161 strcpy(securityType,"WPAand11i");
6162 strcpy(authMode,"EAPAuthentication");
6163 }
6164 else if (strcmp(encMode, "WPA-Personal")==0)
6165 {
6166 strcpy(securityType,"WPA");
6167 strcpy(authMode,"PSKAuthentication");
6168 }
6169 else if (strcmp(encMode, "WPA-Enterprise")==0)
6170 {
6171 strcpy(securityType,"WPA");
6172 strcpy(authMode,"EAPAuthentication");
6173 }
6174 else if (strcmp(encMode, "WPA2-Personal")==0)
6175 {
6176 strcpy(securityType,"11i");
6177 strcpy(authMode,"PSKAuthentication");
6178 }
6179 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6180 {
6181 strcpy(securityType,"11i");
6182 strcpy(authMode,"EAPAuthentication");
6183 }
developer587c1b62022-09-27 15:58:59 +08006184 else if (strcmp(encMode, "WPA3-Personal") == 0)
6185 {
6186 strcpy(securityType,"11i");
6187 strcpy(authMode,"SAEAuthentication");
6188 }
6189 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6190 {
6191 strcpy(securityType,"11i");
6192 strcpy(authMode,"EAP_192-bit_Authentication");
6193 }
developer06a01d92022-09-07 16:32:39 +08006194 else
6195 {
6196 strcpy(securityType,"None");
6197 strcpy(authMode,"None");
6198 }
6199 wifi_setApBeaconType(apIndex, securityType);
6200 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6201 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6202
6203 return RETURN_OK;
6204}
6205
6206
6207//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6208// output_string must be pre-allocated as 64 character string by caller
6209// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6210INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6211{
6212 char buf[16];
6213 char config_file[MAX_BUF_SIZE] = {0};
6214
6215 if(output_string==NULL)
6216 return RETURN_ERR;
6217
6218 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6219 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6220
6221 if(strcmp(buf,"0")==0)
6222 {
6223 printf("wpa_mode is %s ......... \n",buf);
6224 return RETURN_ERR;
6225 }
6226
6227 wifi_dbg_printf("\nFunc=%s\n",__func__);
6228 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6229 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6230 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6231
6232 return RETURN_OK;
6233}
6234
6235// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6236// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6237INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6238{
6239 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6240 struct params params={'\0'};
6241 int ret;
6242 char config_file[MAX_BUF_SIZE] = {0};
6243
6244 if(NULL == preSharedKey)
6245 return RETURN_ERR;
6246
6247 params.name = "wpa_passphrase";
6248
6249 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6250 {
6251 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6252 return RETURN_ERR;
6253 }
6254 params.value = preSharedKey;
6255 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6256 ret = wifi_hostapdWrite(config_file, &params, 1);
6257 if(!ret)
6258 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6259 return ret;
6260 //TODO: call hostapd_cli for dynamic_config_control
6261}
6262
6263//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6264// outputs the passphrase, maximum 63 characters
6265INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6266{
6267 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6268
6269 wifi_dbg_printf("\nFunc=%s\n",__func__);
6270 if (NULL == output_string)
6271 return RETURN_ERR;
6272
6273 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6274 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6275 if(strcmp(buf,"0")==0)
6276 {
6277 printf("wpa_mode is %s ......... \n",buf);
6278 return RETURN_ERR;
6279 }
6280
6281 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6282 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6283
6284 return RETURN_OK;
6285}
6286
6287// sets the passphrase enviornment variable, max 63 characters
6288INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6289{
6290 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6291 struct params params={'\0'};
6292 char config_file[MAX_BUF_SIZE] = {0};
6293 int ret;
6294
6295 if(NULL == passPhrase)
6296 return RETURN_ERR;
6297
6298 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6299 {
6300 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6301 return RETURN_ERR;
6302 }
6303 params.name = "wpa_passphrase";
6304 params.value = passPhrase;
6305 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6306 ret=wifi_hostapdWrite(config_file,&params,1);
6307 if(!ret)
6308 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6309
6310 return ret;
6311}
6312
6313//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.
6314INT wifi_setApSecurityReset(INT apIndex)
6315{
developer8d583982022-09-20 11:28:22 +08006316 char original_config_file[64] = {0};
6317 char current_config_file[64] = {0};
6318 char buf[64] = {0};
6319 char cmd[64] = {0};
6320 char wpa[4] = {0};
6321 char wpa_psk[64] = {0};
6322 char wpa_passphrase[64] = {0};
6323 char wpa_psk_file[128] = {0};
6324 char wpa_key_mgmt[64] = {0};
6325 char wpa_pairwise[32] = {0};
6326 wifi_band band;
6327 struct params list[6];
6328
6329 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6330
6331 band = wifi_index_to_band(apIndex);
6332 if (band == band_2_4)
6333 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6334 else if (band = band_5)
6335 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6336 else if (band = band_6)
6337 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6338 else
6339 return RETURN_ERR;
6340
6341 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6342 list[0].name = "wpa";
6343 list[0].value = wpa;
6344
6345 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6346 list[1].name = "wpa_psk";
6347 list[1].value = wpa_psk;
6348
6349 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6350 list[2].name = "wpa_passphrase";
6351 list[2].value = wpa_passphrase;
6352
6353 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6354
6355 if (strlen(wpa_psk_file) == 0)
6356 strcpy(wpa_psk_file, PSK_FILE);
6357
6358 if (access(wpa_psk_file, F_OK) != 0) {
6359 sprintf(cmd, "touch %s", wpa_psk_file);
6360 _syscmd(cmd, buf, sizeof(buf));
6361 }
6362 list[3].name = "wpa_psk_file";
6363 list[3].value = wpa_psk_file;
6364
6365 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6366 list[4].name = "wpa_key_mgmt";
6367 list[4].value = wpa_key_mgmt;
6368
6369 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6370 list[5].name = "wpa_pairwise";
6371 list[5].value = wpa_pairwise;
6372
6373 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6374 wifi_hostapdWrite(current_config_file, list, 6);
6375
6376 wifi_setApEnable(apIndex, FALSE);
6377 wifi_setApEnable(apIndex, TRUE);
6378
6379 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6380 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006381}
6382
6383//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).
6384INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6385{
developer8f2ddd52022-09-13 15:39:24 +08006386 char config_file[64] = {0};
6387 char buf[64] = {0};
6388 char cmd[256] = {0};
6389
6390 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6391
developer06a01d92022-09-07 16:32:39 +08006392 if(!IP_output || !Port_output || !RadiusSecret_output)
6393 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006394
developer8f2ddd52022-09-13 15:39:24 +08006395 // Read the first matched config
6396 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6397 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6398 _syscmd(cmd, buf, sizeof(buf));
6399 strncpy(IP_output, buf, 64);
6400
6401 memset(buf, 0, sizeof(buf));
6402 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6403 _syscmd(cmd, buf, sizeof(buf));
6404 *Port_output = atoi(buf);
6405
6406 memset(buf, 0, sizeof(buf));
6407 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6408 _syscmd(cmd, buf, sizeof(buf));
6409 strncpy(RadiusSecret_output, buf, 64);
6410
6411 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006412 return RETURN_OK;
6413}
6414
6415INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6416{
developer8f2ddd52022-09-13 15:39:24 +08006417 char config_file[64] = {0};
6418 char port_str[8] = {0};
6419 char cmd[256] = {0};
6420 char buf[128] = {0};
6421
6422 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6423
6424 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6425
6426 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6427 _syscmd(cmd, buf, sizeof(buf));
6428 memset(cmd, 0, sizeof(cmd));
6429
6430 snprintf(port_str, sizeof(port_str), "%d", port);
6431 if (strlen(buf) == 0)
6432 // Append
6433 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6434 "auth_server_addr=%s\\n"
6435 "auth_server_port=%s\\n"
6436 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6437 else {
6438 // Delete the three lines setting after the "# radius 1" comment
6439 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6440 _syscmd(cmd, buf, sizeof(buf));
6441 memset(cmd, 0, sizeof(cmd));
6442 // Use "# radius 1" comment to find the location to insert the radius setting
6443 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6444 "# radius 1\\n"
6445 "auth_server_addr=%s\\n"
6446 "auth_server_port=%s\\n"
6447 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6448 }
6449 if(_syscmd(cmd, buf, sizeof(buf))) {
6450 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6451 return RETURN_ERR;
6452 }
6453
6454 wifi_reloadAp(apIndex);
6455 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6456 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006457}
6458
6459INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6460{
developer8f2ddd52022-09-13 15:39:24 +08006461 char config_file[64] = {0};
6462 char buf[64] = {0};
6463 char cmd[256] = {0};
6464
6465 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6466
developer06a01d92022-09-07 16:32:39 +08006467 if(!IP_output || !Port_output || !RadiusSecret_output)
6468 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006469
6470 // Read the second matched config
6471 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6472 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6473 _syscmd(cmd, buf, sizeof(buf));
6474 strncpy(IP_output, buf, 64);
6475
6476 memset(buf, 0, sizeof(buf));
6477 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6478 _syscmd(cmd, buf, sizeof(buf));
6479 *Port_output = atoi(buf);
6480
6481 memset(buf, 0, sizeof(buf));
6482 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6483 _syscmd(cmd, buf, sizeof(buf));
6484 strncpy(RadiusSecret_output, buf, 64);
6485
6486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006487 return RETURN_OK;
6488}
6489
6490INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6491{
developer8f2ddd52022-09-13 15:39:24 +08006492 char config_file[64] = {0};
6493 char port_str[8] = {0};
6494 char cmd[256] = {0};
6495 char buf[128] = {0};
6496
6497 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6498
6499 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6500
6501 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6502 _syscmd(cmd, buf, sizeof(buf));
6503 memset(cmd, 0, sizeof(cmd));
6504
6505 snprintf(port_str, sizeof(port_str), "%d", port);
6506 if (strlen(buf) == 0)
6507 // Append
6508 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6509 "auth_server_addr=%s\\n"
6510 "auth_server_port=%s\\n"
6511 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6512 else {
6513 // Delete the three lines setting after the "# radius 2" comment
6514 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6515 _syscmd(cmd, buf, sizeof(buf));
6516 memset(cmd, 0, sizeof(cmd));
6517 // Use "# radius 2" comment to find the location to insert the radius setting
6518 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6519 "# radius 2\\n"
6520 "auth_server_addr=%s\\n"
6521 "auth_server_port=%s\\n"
6522 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6523 }
6524 if(_syscmd(cmd, buf, sizeof(buf))) {
6525 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6526 return RETURN_ERR;
6527 }
6528
6529 wifi_reloadAp(apIndex);
6530 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6531 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006532}
6533
6534//RadiusSettings
6535INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6536{
6537 if(!output)
6538 return RETURN_ERR;
6539
6540 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6541 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6542 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6543 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6544 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6545 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.
6546 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6547 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6548 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6549 //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.
6550
6551 return RETURN_OK;
6552}
6553
6554INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6555{
6556 //store the paramters, and apply instantly
6557 return RETURN_ERR;
6558}
6559
6560//Device.WiFi.AccessPoint.{i}.WPS.Enable
6561//Enables or disables WPS functionality for this access point.
6562// outputs the WPS enable state of this ap in output_bool
6563INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6564{
6565 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6566 if(!output_bool || !(apIndex==0 || apIndex==1))
6567 return RETURN_ERR;
6568 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6569 _syscmd(cmd, buf, sizeof(buf));
6570 if(strstr(buf, "configured"))
6571 *output_bool=TRUE;
6572 else
6573 *output_bool=FALSE;
6574
6575 return RETURN_OK;
6576}
6577
6578//Device.WiFi.AccessPoint.{i}.WPS.Enable
6579// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6580INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6581{
6582 char config_file[MAX_BUF_SIZE] = {0};
6583 struct params params;
6584
6585 if(!(apIndex==0 || apIndex==1))
6586 return RETURN_ERR;
6587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6588 //store the paramters, and wait for wifi up to apply
6589 params.name = "wps_state";
6590 params.value = enable ? "2":"0";
6591
6592 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6593 wifi_hostapdWrite(config_file, &params, 1);
6594 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6595 wifi_reloadAp(apIndex);
6596
6597 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6598 return RETURN_OK;
6599}
6600
6601//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
6602INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6603{
6604 if(!output)
6605 return RETURN_ERR;
6606 snprintf(output, 128, "PushButton,PIN");
6607 return RETURN_OK;
6608}
6609
6610//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6611//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.
6612// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6613INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6614{
6615 if(!output)
6616 return RETURN_ERR;
6617 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6618
6619 return RETURN_OK;
6620}
6621
6622//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6623// 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
6624INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6625{
6626 //apply instantly. No setting need to be stored.
6627 char methods[MAX_BUF_SIZE], *token, *next_token;
6628 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6629 struct params params;
6630
6631 if(!methodString || !(apIndex==0 || apIndex==1))
6632 return RETURN_ERR;
6633 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6634 //store the paramters, and wait for wifi up to apply
6635
6636 snprintf(methods, sizeof(methods), "%s", methodString);
6637 for(token=methods; *token; token=next_token)
6638 {
6639 strtok_r(token, ",", &next_token);
6640 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6641 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6642 else if(*token=='E')
6643 {
6644 if(!strcmp(methods, "Ethernet"))
6645 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6646 else if(!strcmp(methods, "ExternalNFCToken"))
6647 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6648 else
6649 printf("%s: Unknown WpsConfigMethod\n", __func__);
6650 }
6651 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6652 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6653 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6654 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6655 else if(*token=='P' )
6656 {
6657 if(!strcmp(token, "PushButton"))
6658 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6659 else if(!strcmp(token, "PIN"))
6660 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6661 else
6662 printf("%s: Unknown WpsConfigMethod\n", __func__);
6663 }
6664 else
6665 printf("%s: Unknown WpsConfigMethod\n", __func__);
6666 }
6667 params.name = "config_methods";
6668 params.value = config_methods;
6669 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6670 wifi_hostapdWrite(config_file, &params, 1);
6671 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6672 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6673
6674 return RETURN_OK;
6675}
6676
6677// outputs the pin value, ulong_pin must be allocated by the caller
6678INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6679{
6680 char buf[MAX_BUF_SIZE] = {0};
6681 char cmd[MAX_CMD_SIZE] = {0};
6682
6683 if(!output_ulong || !(apIndex==0 || apIndex==1))
6684 return RETURN_ERR;
6685 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6686 _syscmd(cmd, buf, sizeof(buf));
6687 if(strlen(buf) > 0)
6688 *output_ulong=strtoul(buf, NULL, 10);
6689
6690 return RETURN_OK;
6691}
6692
6693// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6694INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6695{
6696 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6697 char ap_pin[16] = {0};
6698 char buf[MAX_BUF_SIZE] = {0};
6699 char config_file[MAX_BUF_SIZE] = {0};
6700 ULONG prev_pin = 0;
6701 struct params params;
6702
6703 if(!(apIndex==0 || apIndex==1))
6704 return RETURN_ERR;
6705 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6706 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6707 params.name = "ap_pin";
6708 params.value = ap_pin;
6709 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6710 wifi_hostapdWrite(config_file, &params, 1);
6711 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6712 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6713
6714 return RETURN_OK;
6715}
6716
6717// Output string is either Not configured or Configured, max 32 characters
6718INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6719{
6720 char cmd[MAX_CMD_SIZE];
6721 char buf[MAX_BUF_SIZE]={0};
6722
6723 if(!output_string || !(apIndex==0 || apIndex==1))
6724 return RETURN_ERR;
6725 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6726 snprintf(output_string, 32, "Not configured");
6727 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6728 _syscmd(cmd, buf, sizeof(buf));
6729
developer348e3d92022-09-13 14:48:41 +08006730 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006731 snprintf(output_string, 32, "Configured");
6732 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6733
6734 return RETURN_OK;
6735}
6736
6737// sets the WPS pin for this AP
6738INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6739{
6740 char cmd[MAX_CMD_SIZE];
6741 char buf[MAX_BUF_SIZE]={0};
6742 BOOL enable;
6743
6744 if(!(apIndex==0 || apIndex==1))
6745 return RETURN_ERR;
6746 wifi_getApEnable(apIndex, &enable);
6747 if (!enable)
6748 return RETURN_ERR;
6749 wifi_getApWpsEnable(apIndex, &enable);
6750 if (!enable)
6751 return RETURN_ERR;
6752
6753 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6754 _syscmd(cmd, buf, sizeof(buf));
6755 if((strstr(buf, "OK"))!=NULL)
6756 return RETURN_OK;
6757
6758 return RETURN_ERR;
6759}
6760
6761// This function is called when the WPS push button has been pressed for this AP
6762INT wifi_setApWpsButtonPush(INT apIndex)
6763{
6764 char cmd[MAX_CMD_SIZE];
6765 char buf[MAX_BUF_SIZE]={0};
6766 BOOL enable=FALSE;
6767
6768 if(!(apIndex==0 || apIndex==1))
6769 return RETURN_ERR;
6770 wifi_getApEnable(apIndex, &enable);
6771 if (!enable)
6772 return RETURN_ERR;
6773
6774 wifi_getApWpsEnable(apIndex, &enable);
6775 if (!enable)
6776 return RETURN_ERR;
6777
6778 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6779 _syscmd(cmd, buf, sizeof(buf));
6780
6781 if((strstr(buf, "OK"))!=NULL)
6782 return RETURN_OK;
6783 return RETURN_ERR;
6784}
6785
6786// cancels WPS mode for this AP
6787INT wifi_cancelApWPS(INT apIndex)
6788{
6789 char cmd[MAX_CMD_SIZE];
6790 char buf[MAX_BUF_SIZE]={0};
6791
6792 if(!(apIndex==0 || apIndex==1))
6793 return RETURN_ERR;
6794 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6795 _syscmd(cmd,buf, sizeof(buf));
6796
6797 if((strstr(buf, "OK"))!=NULL)
6798 return RETURN_OK;
6799 return RETURN_ERR;
6800}
6801
6802//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6803//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6804INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6805{
6806 FILE *f;
6807 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6808 char cmd[256], buf[2048];
6809 char *param , *value, *line=NULL;
6810 size_t len = 0;
6811 ssize_t nread;
6812 wifi_associated_dev_t *dev=NULL;
6813
6814 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6815 *associated_dev_array = NULL;
6816 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6817 _syscmd(cmd,buf,sizeof(buf));
6818 *output_array_size = atoi(buf);
6819
6820 if (*output_array_size <= 0)
6821 return RETURN_OK;
6822
6823 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6824 *associated_dev_array = dev;
6825 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6826 _syscmd(cmd,buf,sizeof(buf));
6827 f = fopen("/tmp/connected_devices.txt", "r");
6828 if (f==NULL)
6829 {
6830 *output_array_size=0;
6831 return RETURN_ERR;
6832 }
6833 while ((nread = getline(&line, &len, f)) != -1)
6834 {
6835 param = strtok(line,"=");
6836 value = strtok(NULL,"=");
6837
6838 if( strcmp("flags",param) == 0 )
6839 {
6840 value[strlen(value)-1]='\0';
6841 if(strstr (value,"AUTHORIZED") != NULL )
6842 {
6843 dev[auth_temp].cli_AuthenticationState = 1;
6844 dev[auth_temp].cli_Active = 1;
6845 auth_temp++;
6846 read_flag=1;
6847 }
6848 }
6849 if(read_flag==1)
6850 {
6851 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6852 {
6853 value[strlen(value)-1]='\0';
6854 sscanf(value, "%x:%x:%x:%x:%x:%x",
6855 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6856 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6857 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6858 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6859 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6860 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6861 mac_temp++;
6862 read_flag=0;
6863 }
6864 }
6865 }
6866 *output_array_size = auth_temp;
6867 auth_temp=0;
6868 mac_temp=0;
6869 free(line);
6870 fclose(f);
6871 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6872 return RETURN_OK;
6873}
6874
6875#define MACADDRESS_SIZE 6
6876
6877INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6878{
6879 FILE *fp = NULL;
6880 char str[MAX_BUF_SIZE] = {0};
6881 int wificlientindex = 0 ;
6882 int count = 0;
6883 int signalstrength = 0;
6884 int arr[MACADDRESS_SIZE] = {0};
6885 unsigned char mac[MACADDRESS_SIZE] = {0};
6886 UINT wifi_count = 0;
6887 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6888 char pipeCmd[MAX_CMD_SIZE] = {0};
6889
6890 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6891 *output_array_size = 0;
6892 *associated_dev_array = NULL;
6893
6894 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6895 fp = popen(pipeCmd, "r");
6896 if (fp == NULL)
6897 {
6898 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6899 return RETURN_ERR;
6900 }
6901
6902 /* Read the output a line at a time - output it. */
6903 fgets(str, sizeof(str)-1, fp);
6904 wifi_count = (unsigned int) atoi ( str );
6905 *output_array_size = wifi_count;
6906 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6907 pclose(fp);
6908
6909 if(wifi_count == 0)
6910 {
6911 return RETURN_OK;
6912 }
6913 else
6914 {
6915 wifi_associated_dev3_t* temp = NULL;
6916 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6917 if(temp == NULL)
6918 {
6919 printf("Error Statement. Insufficient memory \n");
6920 return RETURN_ERR;
6921 }
6922
6923 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6924 system(pipeCmd);
6925 memset(pipeCmd,0,sizeof(pipeCmd));
6926 if(apIndex == 0)
6927 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6928 else if(apIndex == 1)
6929 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6930 system(pipeCmd);
6931
6932 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6933 if(fp == NULL)
6934 {
6935 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6936 return RETURN_ERR;
6937 }
6938 fclose(fp);
6939
6940 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6941 fp = popen(pipeCmd, "r");
6942 if(fp)
6943 {
6944 for(count =0 ; count < wifi_count; count++)
6945 {
6946 fgets(str, MAX_BUF_SIZE, fp);
6947 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6948 {
6949 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6950 {
6951 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6952
6953 }
6954 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6955 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]);
6956 }
6957 temp[count].cli_AuthenticationState = 1; //TODO
6958 temp[count].cli_Active = 1; //TODO
6959 }
6960 pclose(fp);
6961 }
6962
6963 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6964 fp = popen(pipeCmd, "r");
6965 if(fp)
6966 {
6967 pclose(fp);
6968 }
6969 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6970 if(fp)
6971 {
6972 for(count =0 ; count < wifi_count ;count++)
6973 {
6974 fgets(str, MAX_BUF_SIZE, fp);
6975 signalstrength = atoi(str);
6976 temp[count].cli_SignalStrength = signalstrength;
6977 temp[count].cli_RSSI = signalstrength;
6978 temp[count].cli_SNR = signalstrength + 95;
6979 }
6980 pclose(fp);
6981 }
6982
6983
6984 if((apIndex == 0) || (apIndex == 4))
6985 {
6986 for(count =0 ; count < wifi_count ;count++)
6987 {
6988 strcpy(temp[count].cli_OperatingStandard,"g");
6989 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6990 }
6991
6992 //BytesSent
6993 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6994 fp = popen(pipeCmd, "r");
6995 if(fp)
6996 {
6997 pclose(fp);
6998 }
6999 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7000 if(fp)
7001 {
7002 for (count = 0; count < wifi_count; count++)
7003 {
7004 fgets(str, MAX_BUF_SIZE, fp);
7005 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7006 }
7007 pclose(fp);
7008 }
7009
7010 //BytesReceived
7011 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
7012 fp = popen(pipeCmd, "r");
7013 if (fp)
7014 {
7015 pclose(fp);
7016 }
7017 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7018 if (fp)
7019 {
7020 for (count = 0; count < wifi_count; count++)
7021 {
7022 fgets(str, MAX_BUF_SIZE, fp);
7023 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7024 }
7025 pclose(fp);
7026 }
7027
7028 //PacketsSent
7029 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7030 fp = popen(pipeCmd, "r");
7031 if (fp)
7032 {
7033 pclose(fp);
7034 }
7035
7036 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7037 if (fp)
7038 {
7039 for (count = 0; count < wifi_count; count++)
7040 {
7041 fgets(str, MAX_BUF_SIZE, fp);
7042 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7043 }
7044 pclose(fp);
7045 }
7046
7047 //PacketsReceived
7048 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7049 fp = popen(pipeCmd, "r");
7050 if (fp)
7051 {
7052 pclose(fp);
7053 }
7054 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7055 if (fp)
7056 {
7057 for (count = 0; count < wifi_count; count++)
7058 {
7059 fgets(str, MAX_BUF_SIZE, fp);
7060 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7061 }
7062 pclose(fp);
7063 }
7064
7065 //ErrorsSent
7066 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7067 fp = popen(pipeCmd, "r");
7068 if (fp)
7069 {
7070 pclose(fp);
7071 }
7072 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7073 if (fp)
7074 {
7075 for (count = 0; count < wifi_count; count++)
7076 {
7077 fgets(str, MAX_BUF_SIZE, fp);
7078 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7079 }
7080 pclose(fp);
7081 }
7082
7083 //ErrorsSent
7084 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7085 fp = popen(pipeCmd, "r");
7086 if (fp)
7087 {
7088 pclose(fp);
7089 }
7090 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7091 if (fp)
7092 {
7093 for (count = 0; count < wifi_count; count++)
7094 {
7095 fgets(str, MAX_BUF_SIZE, fp);
7096 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7097 }
7098 pclose(fp);
7099 }
7100
7101 //LastDataDownlinkRate
7102 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7103 fp = popen(pipeCmd, "r");
7104 if (fp)
7105 {
7106 pclose(fp);
7107 }
7108 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7109 if (fp)
7110 {
7111 for (count = 0; count < wifi_count; count++)
7112 {
7113 fgets(str, MAX_BUF_SIZE, fp);
7114 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7115 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7116 }
7117 pclose(fp);
7118 }
7119
7120 //LastDataUplinkRate
7121 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7122 fp = popen(pipeCmd, "r");
7123 if (fp)
7124 {
7125 pclose(fp);
7126 }
7127 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7128 if (fp)
7129 {
7130 for (count = 0; count < wifi_count; count++)
7131 {
7132 fgets(str, MAX_BUF_SIZE, fp);
7133 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7134 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7135 }
7136 pclose(fp);
7137 }
7138
7139 }
7140 else if ((apIndex == 1) || (apIndex == 5))
7141 {
7142 for (count = 0; count < wifi_count; count++)
7143 {
7144 strcpy(temp[count].cli_OperatingStandard, "a");
7145 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7146 temp[count].cli_BytesSent = 0;
7147 temp[count].cli_BytesReceived = 0;
7148 temp[count].cli_LastDataUplinkRate = 0;
7149 temp[count].cli_LastDataDownlinkRate = 0;
7150 temp[count].cli_PacketsSent = 0;
7151 temp[count].cli_PacketsReceived = 0;
7152 temp[count].cli_ErrorsSent = 0;
7153 }
7154 }
7155
7156 for (count = 0; count < wifi_count; count++)
7157 {
7158 temp[count].cli_Retransmissions = 0;
7159 temp[count].cli_DataFramesSentAck = 0;
7160 temp[count].cli_DataFramesSentNoAck = 0;
7161 temp[count].cli_MinRSSI = 0;
7162 temp[count].cli_MaxRSSI = 0;
7163 strncpy(temp[count].cli_InterferenceSources, "", 64);
7164 memset(temp[count].cli_IPAddress, 0, 64);
7165 temp[count].cli_RetransCount = 0;
7166 temp[count].cli_FailedRetransCount = 0;
7167 temp[count].cli_RetryCount = 0;
7168 temp[count].cli_MultipleRetryCount = 0;
7169 }
7170 *associated_dev_array = temp;
7171 }
7172 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7173 return RETURN_OK;
7174}
7175
7176int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7177{
7178 FILE *fp = NULL;
7179 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7180 char cmd[MAX_CMD_SIZE];
7181 int count = 0;
7182
7183 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7184 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7185 fp = popen(cmd,"r");
7186 if(fp == NULL)
7187 {
7188 printf("Failed to run command in Function %s\n",__FUNCTION__);
7189 return 0;
7190 }
7191 if(fgets(path, sizeof(path)-1, fp) != NULL)
7192 {
7193 for(count=0;path[count]!='\n';count++)
7194 status[count]=path[count];
7195 status[count]='\0';
7196 }
7197 strcpy(wifi_status,status);
7198 pclose(fp);
7199 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7200 return RETURN_OK;
7201}
7202
7203/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7204struct hostapd_sta_param {
7205 char key[50];
7206 char value[100];
7207}
7208
7209static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7210 int i = 0;
7211
7212 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7213 if (strncmp(params[i].key,key,50) == 0){
7214 return &params[i].value;
7215 }
7216 i++;
7217 }
7218 return NULL;
7219
7220} */
7221
7222static unsigned int count_occurences(const char *buf, const char *word)
7223{
7224 unsigned int n = 0;
7225 char *ptr = strstr(buf, word);
7226
7227 while (ptr++) {
7228 n++;
7229 ptr = strstr(ptr, word);
7230 }
7231
7232 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7233 return n;
7234}
7235
7236static const char *get_line_from_str_buf(const char *buf, char *line)
7237{
7238 int i;
7239 int n = strlen(buf);
7240
7241 for (i = 0; i < n; i++) {
7242 line[i] = buf[i];
7243 if (buf[i] == '\n') {
7244 line[i] = '\0';
7245 return &buf[i + 1];
7246 }
7247 }
7248
7249 return NULL;
7250}
7251
7252INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7253{
7254 unsigned int assoc_cnt = 0;
7255 char interface_name[50] = {0};
7256 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7257 char cmd[MAX_CMD_SIZE] = {'\0'};
7258 char line[256] = {'\0'};
7259 int i = 0;
7260 int ret = 0;
7261 const char *ptr = NULL;
7262 char *key = NULL;
7263 char *val = NULL;
7264 wifi_associated_dev3_t *temp = NULL;
7265 int rssi;
7266
7267 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7268
7269 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7270 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7271 return RETURN_ERR;
7272 }
7273
7274 // Example filtered output of 'iw dev' command:
7275 // Station 0a:69:72:10:d2:fa (on wifi0)
7276 // signal avg:-67 [-71, -71] dBm
7277 // Station 28:c2:1f:25:5f:99 (on wifi0)
7278 // signal avg:-67 [-71, -70] dBm
7279 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7280 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7281 return RETURN_ERR;
7282 }
7283
7284 ret = _syscmd(cmd, buf, sizeof(buf));
7285 if (ret == RETURN_ERR) {
7286 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7287 return RETURN_ERR;
7288 }
7289
7290 *output_array_size = count_occurences(buf, "Station");
7291 if (*output_array_size == 0) return RETURN_OK;
7292
7293 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7294 if (temp == NULL) {
7295 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7296 return RETURN_ERR;
7297 }
7298 *associated_dev_array = temp;
7299
7300 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7301 ptr = get_line_from_str_buf(buf, line);
7302 i = -1;
7303 while (ptr) {
7304 if (strstr(line, "Station")) {
7305 i++;
7306 key = strtok(line, " ");
7307 val = strtok(NULL, " ");
7308 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7309 &temp[i].cli_MACAddress[0],
7310 &temp[i].cli_MACAddress[1],
7311 &temp[i].cli_MACAddress[2],
7312 &temp[i].cli_MACAddress[3],
7313 &temp[i].cli_MACAddress[4],
7314 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7315 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7316 free(*associated_dev_array);
7317 return RETURN_ERR;
7318 }
7319 }
7320 else if (i < 0) {
7321 ptr = get_line_from_str_buf(ptr, line);
7322 continue; // We didn't detect 'station' entry yet
7323 }
7324 else if (strstr(line, "signal avg")) {
7325 key = strtok(line, ":");
7326 val = strtok(NULL, " ");
7327 if (sscanf(val, "%d", &rssi) <= 0 ) {
7328 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7329 free(*associated_dev_array);
7330 return RETURN_ERR;
7331 }
7332 temp[i].cli_RSSI = rssi;
7333 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7334 }
7335 // Here other fields can be parsed if added to filter of 'iw dev' command
7336
7337 ptr = get_line_from_str_buf(ptr, line);
7338 };
7339
7340 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7341
7342 return RETURN_OK;
7343}
7344
7345#if 0
7346//To-do
7347INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7348{
7349 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7350
7351 //Using different approach to get required WiFi Parameters from system available commands
7352#if 0
7353 FILE *f;
7354 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7355 char cmd[256], buf[2048];
7356 char *param , *value, *line=NULL;
7357 size_t len = 0;
7358 ssize_t nread;
7359 wifi_associated_dev3_t *dev=NULL;
7360 *associated_dev_array = NULL;
7361 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7362 _syscmd(cmd,buf,sizeof(buf));
7363 *output_array_size = atoi(buf);
7364
7365 if (*output_array_size <= 0)
7366 return RETURN_OK;
7367
7368 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7369 *associated_dev_array = dev;
7370 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7371 _syscmd(cmd,buf,sizeof(buf));
7372 f = fopen("/tmp/connected_devices.txt", "r");
7373 if (f==NULL)
7374 {
7375 *output_array_size=0;
7376 return RETURN_ERR;
7377 }
7378 while ((nread = getline(&line, &len, f)) != -1)
7379 {
7380 param = strtok(line,"=");
7381 value = strtok(NULL,"=");
7382
7383 if( strcmp("flags",param) == 0 )
7384 {
7385 value[strlen(value)-1]='\0';
7386 if(strstr (value,"AUTHORIZED") != NULL )
7387 {
7388 dev[auth_temp].cli_AuthenticationState = 1;
7389 dev[auth_temp].cli_Active = 1;
7390 auth_temp++;
7391 read_flag=1;
7392 }
7393 }
7394 if(read_flag==1)
7395 {
7396 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7397 {
7398 value[strlen(value)-1]='\0';
7399 sscanf(value, "%x:%x:%x:%x:%x:%x",
7400 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7401 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7402 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7403 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7404 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7405 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7406
7407 }
7408 else if( strcmp("rx_packets",param) == 0 )
7409 {
7410 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7411 }
7412
7413 else if( strcmp("tx_packets",param) == 0 )
7414 {
7415 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7416 }
7417
7418 else if( strcmp("rx_bytes",param) == 0 )
7419 {
7420 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7421 }
7422
7423 else if( strcmp("tx_bytes",param) == 0 )
7424 {
7425 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7426 mac_temp++;
7427 read_flag=0;
7428 }
7429 }
7430 }
7431
7432 *output_array_size = auth_temp;
7433 auth_temp=0;
7434 mac_temp=0;
7435 free(line);
7436 fclose(f);
7437#endif
7438 char interface_name[MAX_BUF_SIZE] = {0};
7439 char wifi_status[MAX_BUF_SIZE] = {0};
7440 char hostapdconf[MAX_BUF_SIZE] = {0};
7441
7442 wifi_associated_dev3_t *dev_array = NULL;
7443 ULONG wifi_count = 0;
7444
7445 *associated_dev_array = NULL;
7446 *output_array_size = 0;
7447
7448 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7449 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7450 {
7451 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7452
7453 GetInterfaceName(interface_name, hostapdconf);
7454
7455 if(strlen(interface_name) > 1)
7456 {
7457 wifihal_interfacestatus(wifi_status,interface_name);
7458 if(strcmp(wifi_status,"RUNNING") == 0)
7459 {
7460 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7461
7462 *associated_dev_array = dev_array;
7463 *output_array_size = wifi_count;
7464 }
7465 else
7466 {
7467 *associated_dev_array = NULL;
7468 }
7469 }
7470 }
7471
7472 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7473 return RETURN_OK;
7474}
7475#endif
7476
7477/* getIPAddress function */
7478/**
7479* @description Returning IpAddress of the Matched String
7480*
7481* @param
7482* @str Having MacAddress
7483* @ipaddr Having ipaddr
7484* @return The status of the operation
7485* @retval RETURN_OK if successful
7486* @retval RETURN_ERR if any error is detected
7487*
7488*/
7489
7490INT getIPAddress(char *str,char *ipaddr)
7491{
7492 FILE *fp = NULL;
7493 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7494 int LeaseTime = 0,ret = 0;
7495 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7496 {
7497 return RETURN_ERR;
7498 }
7499
7500 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7501 {
7502 /*
7503 Sample:sss
7504 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7505 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7506 */
7507 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7508 &(LeaseTime),
7509 phyAddr,
7510 ipAddr,
7511 hostName
7512 );
7513 if(ret != 4)
7514 continue;
7515 if(strcmp(str,phyAddr) == 0)
7516 strcpy(ipaddr,ipAddr);
7517 }
7518 return RETURN_OK;
7519}
7520
7521/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7522/**
7523* @description Returning Inactive wireless connected clients informations
7524*
7525* @param
7526* @filename Holding private_wifi 2g/5g content files
7527* @associated_dev_array Having inactiv wireless clients informations
7528* @output_array_size Returning Inactive wireless counts
7529* @return The status of the operation
7530* @retval RETURN_OK if successful
7531* @retval RETURN_ERR if any error is detected
7532*
7533*/
7534
7535INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7536{
7537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7538 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7539 FILE *fp = NULL;
7540 int arr[MACADDRESS_SIZE] = {0};
7541 unsigned char mac[MACADDRESS_SIZE] = {0};
7542 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7543 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7544 fp = popen(buf,"r");
7545 if(fp == NULL)
7546 return RETURN_ERR;
7547 else
7548 {
7549 fgets(path,sizeof(path),fp);
7550 maccount = atoi(path);
7551 }
7552 pclose(fp);
7553 *output_array_size = maccount;
7554 wifi_associated_dev3_t* temp = NULL;
7555 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7556 *associated_dev_array = temp;
7557 if(temp == NULL)
7558 {
7559 printf("Error Statement. Insufficient memory \n");
7560 return RETURN_ERR;
7561 }
7562 memset(buf,0,sizeof(buf));
7563 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7564 fp = popen(buf,"r");
7565 for(count = 0; count < maccount ; count++)
7566 {
7567 fgets(path,sizeof(path),fp);
7568 for(i = 0; path[i]!='\n';i++)
7569 str[i]=path[i];
7570 str[i]='\0';
7571 getIPAddress(str,ipaddr);
7572 memset(buf,0,sizeof(buf));
7573 if(strlen(ipaddr) > 0)
7574 {
7575 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7576 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7577 {
7578 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7579 {
7580 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7581 {
7582 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7583
7584 }
7585 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7586 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]);
7587 }
7588 temp[count].cli_AuthenticationState = 0; //TODO
7589 temp[count].cli_Active = 0; //TODO
7590 temp[count].cli_SignalStrength = 0;
7591 }
7592 else //Active wireless clients info
7593 {
7594 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7595 {
7596 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7597 {
7598 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7599
7600 }
7601 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7602 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]);
7603 }
7604 temp[count].cli_Active = 1;
7605 }
7606 }
7607 memset(ipaddr,0,sizeof(ipaddr));
7608 }
7609 pclose(fp);
7610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7611 return RETURN_OK;
7612}
7613//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7614//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7615//To get Band Steering Capability
7616INT wifi_getBandSteeringCapability(BOOL *support)
7617{
7618 *support = FALSE;
7619 return RETURN_OK;
7620}
7621
7622
7623//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7624//To get Band Steering enable status
7625INT wifi_getBandSteeringEnable(BOOL *enable)
7626{
7627 *enable = FALSE;
7628 return RETURN_OK;
7629}
7630
7631//To turn on/off Band steering
7632INT wifi_setBandSteeringEnable(BOOL enable)
7633{
7634 return RETURN_OK;
7635}
7636
7637//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7638//To get Band Steering AP group
7639INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7640{
7641 if (NULL == output_ApGroup)
7642 return RETURN_ERR;
7643
7644 strcpy(output_ApGroup, "1,2");
7645 return RETURN_OK;
7646}
7647
7648//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7649//to set and read the band steering BandUtilizationThreshold parameters
7650INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7651{
7652 return RETURN_ERR;
7653}
7654
7655INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7656{
7657 return RETURN_ERR;
7658}
7659
7660//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7661//to set and read the band steering RSSIThreshold parameters
7662INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7663{
7664 return RETURN_ERR;
7665}
7666
7667INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7668{
7669 return RETURN_ERR;
7670}
7671
7672
7673//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7674//to set and read the band steering physical modulation rate threshold parameters
7675INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7676{
7677 //If chip is not support, return -1
7678 return RETURN_ERR;
7679}
7680
7681INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7682{
7683 //If chip is not support, return -1
7684 return RETURN_ERR;
7685}
7686
7687//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7688//to set and read the inactivity time (in seconds) for steering under overload condition
7689INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7690{
7691 return RETURN_ERR;
7692}
7693
7694INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7695{
7696 return RETURN_ERR;
7697}
7698
7699//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7700//to set and read the inactivity time (in seconds) for steering under Idle condition
7701INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7702{
7703 return RETURN_ERR;
7704}
7705
7706INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7707{
7708 return RETURN_ERR;
7709}
7710
7711//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7712//pClientMAC[64]
7713//pSourceSSIDIndex[64]
7714//pDestSSIDIndex[64]
7715//pSteeringReason[256]
7716INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7717{
7718 //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
7719 *pSteeringTime=time(NULL);
7720 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7721 return RETURN_OK;
7722}
7723
7724INT wifi_ifConfigDown(INT apIndex)
7725{
7726 INT status = RETURN_OK;
7727 char cmd[64];
7728
7729 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7730 printf("%s: %s\n", __func__, cmd);
7731 system(cmd);
7732
7733 return status;
7734}
7735
7736INT wifi_ifConfigUp(INT apIndex)
7737{
7738 char cmd[128];
7739 char buf[1024];
7740
7741 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7742 _syscmd(cmd, buf, sizeof(buf));
7743 return 0;
7744}
7745
7746//>> Deprecated. Replace with wifi_applyRadioSettings
7747INT wifi_pushBridgeInfo(INT apIndex)
7748{
7749 char ip[32];
7750 char subnet[32];
7751 char bridge[32];
7752 int vlanId;
7753 char cmd[128];
7754 char buf[1024];
7755
7756 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7757 wifi_getApVlanID(apIndex,&vlanId);
7758
7759 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7760 _syscmd(cmd,buf, sizeof(buf));
7761
7762 return 0;
7763}
7764
7765INT wifi_pushChannel(INT radioIndex, UINT channel)
7766{
7767 char cmd[128];
7768 char buf[1024];
7769 int apIndex;
7770
7771 apIndex=(radioIndex==0)?0:1;
7772 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7773 _syscmd(cmd,buf, sizeof(buf));
7774
7775 return 0;
7776}
7777
7778INT wifi_pushChannelMode(INT radioIndex)
7779{
7780 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7781 return RETURN_ERR;
7782}
7783
7784INT wifi_pushDefaultValues(INT radioIndex)
7785{
7786 //Apply Comcast specified default radio settings instantly
7787 //AMPDU=1
7788 //AMPDUFrames=32
7789 //AMPDULim=50000
7790 //txqueuelen=1000
7791
7792 return RETURN_ERR;
7793}
7794
7795INT wifi_pushTxChainMask(INT radioIndex)
7796{
7797 //Apply default TxChainMask instantly
7798 return RETURN_ERR;
7799}
7800
7801INT wifi_pushRxChainMask(INT radioIndex)
7802{
7803 //Apply default RxChainMask instantly
7804 return RETURN_ERR;
7805}
7806
7807INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7808{
7809 INT status;
7810
7811 status = wifi_setSSIDName(apIndex,ssid);
7812 wifi_setApEnable(apIndex,FALSE);
7813 wifi_setApEnable(apIndex,TRUE);
7814
7815 return status;
7816}
7817
7818INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7819{
7820 //Apply default Ssid Advertisement instantly
7821 return RETURN_ERR;
7822}
7823
7824INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7825{
7826 INT status = RETURN_ERR;
7827 *output = 0;
7828 return RETURN_ERR;
7829}
7830
7831INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7832{
7833 return RETURN_OK;
7834}
7835
7836INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7837{
7838 return RETURN_OK;
7839}
7840
7841//To-do
7842INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7843{
developereb199ae2022-09-13 14:04:27 +08007844 char output[16]={'\0'};
7845 char config_file[MAX_BUF_SIZE] = {0};
7846
7847 if (!output_string)
7848 return RETURN_ERR;
7849
7850 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7851 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7852
7853 if (strlen(output) == 0)
7854 snprintf(output_string, 64, "Disabled");
7855 else if (strncmp(output, "0", 1) == 0)
7856 snprintf(output_string, 64, "Disabled");
7857 else if (strncmp(output, "1", 1) == 0)
7858 snprintf(output_string, 64, "Optional");
7859 else if (strncmp(output, "2", 1) == 0)
7860 snprintf(output_string, 64, "Required");
7861 else {
7862 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7863 return RETURN_ERR;
7864 }
7865
7866 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007867 return RETURN_OK;
7868}
7869INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7870{
developereb199ae2022-09-13 14:04:27 +08007871 char str[MAX_BUF_SIZE]={'\0'};
7872 char cmd[MAX_CMD_SIZE]={'\0'};
7873 struct params params;
7874 char config_file[MAX_BUF_SIZE] = {0};
7875
7876 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7877 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7878 return RETURN_ERR;
7879
7880 params.name = "ieee80211w";
7881 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7882 params.value = "0";
7883 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7884 params.value = "1";
7885 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7886 params.value = "2";
7887 else{
7888 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7889 return RETURN_ERR;
7890 }
7891 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7892 wifi_hostapdWrite(config_file, &params, 1);
7893 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007894 return RETURN_OK;
7895}
7896INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7897{
7898 char output[16]={'\0'};
7899 char config_file[MAX_BUF_SIZE] = {0};
7900
7901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7902 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7903 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7904
7905 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7906 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7907
7908 return RETURN_OK;
7909}
7910
7911INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7912{
7913 return RETURN_OK;
7914}
7915
7916INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7917{
7918 return RETURN_OK;
7919}
7920
7921INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7922{
7923 return RETURN_OK;
7924}
7925
7926INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7927{
7928 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7929 char config_file[MAX_BUF_SIZE] = {0};
7930
7931 if (NULL == output)
7932 return RETURN_ERR;
7933 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7934 wifi_hostapdRead(config_file,"hw_mode",output,64);
7935
7936 if(strcmp(output,"b")==0)
7937 sprintf(output, "%s", "1,2,5.5,11");
7938 else if (strcmp(output,"a")==0)
7939 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7940 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7941 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7942
7943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7944 return RETURN_OK;
7945}
7946
7947INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7948{
7949 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7950 char *temp;
7951 char temp_output[128];
7952 char temp_TransmitRates[128];
7953 char config_file[MAX_BUF_SIZE] = {0};
7954
7955 if (NULL == output)
7956 return RETURN_ERR;
7957
7958 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7959 wifi_hostapdRead(config_file,"supported_rates",output,64);
7960
7961 strcpy(temp_TransmitRates,output);
7962 strcpy(temp_output,"");
7963 temp = strtok(temp_TransmitRates," ");
7964 while(temp!=NULL)
7965 {
7966 temp[strlen(temp)-1]=0;
7967 if((temp[0]=='5') && (temp[1]=='\0'))
7968 {
7969 temp="5.5";
7970 }
7971 strcat(temp_output,temp);
7972 temp = strtok(NULL," ");
7973 if(temp!=NULL)
7974 {
7975 strcat(temp_output,",");
7976 }
7977 }
7978 strcpy(output,temp_output);
7979 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7980
7981 return RETURN_OK;
7982}
7983
7984INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7985{
7986 return RETURN_OK;
7987}
7988
7989
7990INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7991{
7992 int i=0;
7993 char *temp;
7994 char temp1[128];
7995 char temp_output[128];
7996 char temp_TransmitRates[128];
7997 struct params params={'\0'};
7998 char config_file[MAX_BUF_SIZE] = {0};
7999
8000 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8001 if(NULL == output)
8002 return RETURN_ERR;
8003
8004 strcpy(temp_TransmitRates,output);
8005
8006 for(i=0;i<strlen(temp_TransmitRates);i++)
8007 {
8008 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
8009 {
8010 continue;
8011 }
8012 else
8013 {
8014 return RETURN_ERR;
8015 }
8016 }
8017 strcpy(temp_output,"");
8018 temp = strtok(temp_TransmitRates," ");
8019 while(temp!=NULL)
8020 {
8021 strcpy(temp1,temp);
8022 if(wlanIndex==1)
8023 {
8024 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
8025 {
8026 return RETURN_ERR;
8027 }
8028 }
8029
8030 if(strcmp(temp,"5.5")==0)
8031 {
8032 strcpy(temp1,"55");
8033 }
8034 else
8035 {
8036 strcat(temp1,"0");
8037 }
8038 strcat(temp_output,temp1);
8039 temp = strtok(NULL," ");
8040 if(temp!=NULL)
8041 {
8042 strcat(temp_output," ");
8043 }
8044 }
8045 strcpy(output,temp_output);
8046
8047
8048 params.name = "supported_rates";
8049 params.value = output;
8050
8051 wifi_dbg_printf("\n%s:",__func__);
8052 wifi_dbg_printf("params.value=%s\n",params.value);
8053 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8054 wifi_hostapdWrite(config_file,&params,1);
8055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8056
8057 return RETURN_OK;
8058}
8059
8060
8061static char *sncopy(char *dst, int dst_sz, const char *src)
8062{
8063 if (src && dst && dst_sz > 0) {
8064 strncpy(dst, src, dst_sz);
8065 dst[dst_sz - 1] = '\0';
8066 }
8067 return dst;
8068}
8069
8070static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8071{
8072 if (0 == strcmp(ht_mode, "HT40") ||
8073 0 == strcmp(ht_mode, "HT80") ||
8074 0 == strcmp(ht_mode, "HT160")) {
8075 switch (channel) {
8076 case 1 ... 7:
8077 case 36:
8078 case 44:
8079 case 52:
8080 case 60:
8081 case 100:
8082 case 108:
8083 case 116:
8084 case 124:
8085 case 132:
8086 case 140:
8087 case 149:
8088 case 157:
8089 return 1;
8090 case 8 ... 13:
8091 case 40:
8092 case 48:
8093 case 56:
8094 case 64:
8095 case 104:
8096 case 112:
8097 case 120:
8098 case 128:
8099 case 136:
8100 case 144:
8101 case 153:
8102 case 161:
8103 return -1;
8104 default:
8105 return -EINVAL;
8106 }
8107 }
8108
8109 return -EINVAL;
8110}
8111
8112static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8113{
8114 if (NULL == hw_mode) return;
8115
8116 if (0 == strcmp(hw_mode, "ac"))
8117 sncopy(bw_mode, bw_mode_len, "ht vht");
8118
8119 if (0 == strcmp(hw_mode, "n"))
8120 sncopy(bw_mode, bw_mode_len, "ht");
8121
8122 return;
8123}
8124
8125static int util_chan_to_freq(int chan)
8126{
8127 if (chan == 14)
8128 return 2484;
8129 else if (chan < 14)
8130 return 2407 + chan * 5;
8131 else if (chan >= 182 && chan <= 196)
8132 return 4000 + chan * 5;
8133 else
8134 return 5000 + chan * 5;
8135 return 0;
8136}
8137
8138const int *util_unii_5g_chan2list(int chan, int width)
8139{
8140 static const int lists[] = {
8141 // <width>, <chan1>, <chan2>..., 0,
8142 20, 36, 0,
8143 20, 40, 0,
8144 20, 44, 0,
8145 20, 48, 0,
8146 20, 52, 0,
8147 20, 56, 0,
8148 20, 60, 0,
8149 20, 64, 0,
8150 20, 100, 0,
8151 20, 104, 0,
8152 20, 108, 0,
8153 20, 112, 0,
8154 20, 116, 0,
8155 20, 120, 0,
8156 20, 124, 0,
8157 20, 128, 0,
8158 20, 132, 0,
8159 20, 136, 0,
8160 20, 140, 0,
8161 20, 144, 0,
8162 20, 149, 0,
8163 20, 153, 0,
8164 20, 157, 0,
8165 20, 161, 0,
8166 20, 165, 0,
8167 40, 36, 40, 0,
8168 40, 44, 48, 0,
8169 40, 52, 56, 0,
8170 40, 60, 64, 0,
8171 40, 100, 104, 0,
8172 40, 108, 112, 0,
8173 40, 116, 120, 0,
8174 40, 124, 128, 0,
8175 40, 132, 136, 0,
8176 40, 140, 144, 0,
8177 40, 149, 153, 0,
8178 40, 157, 161, 0,
8179 80, 36, 40, 44, 48, 0,
8180 80, 52, 56, 60, 64, 0,
8181 80, 100, 104, 108, 112, 0,
8182 80, 116, 120, 124, 128, 0,
8183 80, 132, 136, 140, 144, 0,
8184 80, 149, 153, 157, 161, 0,
8185 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8186 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8187 -1 // final delimiter
8188 };
8189 const int *start;
8190 const int *p;
8191
8192 for (p = lists; *p != -1; p++) {
8193 if (*p == width) {
8194 for (start = ++p; *p != 0; p++) {
8195 if (*p == chan)
8196 return start;
8197 }
8198 }
8199 // move to the end of channel list of given width
8200 while (*p != 0) {
8201 p++;
8202 }
8203 }
8204
8205 return NULL;
8206}
8207
8208static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8209{
8210 if (NULL == ht_mode)
8211 return 0;
8212
8213 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8214 const int *chans = util_unii_5g_chan2list(channel, width);
8215 int sum = 0;
8216 int cnt = 0;
8217
8218 if (NULL == chans)
8219 return 0;
8220
8221 while (*chans) {
8222 sum += *chans;
8223 cnt++;
8224 chans++;
8225 }
8226 return sum / cnt;
8227}
8228
8229static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8230{
8231 BOOL onlyG, onlyN, onlyA;
8232 CHAR tmp[64];
8233 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8234 if (ret == RETURN_OK) {
8235 sncopy(hw_mode, hw_mode_size, tmp);
8236 }
8237 return ret;
8238}
8239
8240INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8241{
8242 // Sample commands:
8243 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8244 // hostapd_cli -i wifi0 chan_switch 30 2437
8245 char cmd[MAX_CMD_SIZE] = {0};
8246 char buf[MAX_BUF_SIZE] = {0};
8247 int freq = 0, ret = 0;
8248 char center_freq1_str[32] = ""; // center_freq1=%d
8249 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8250 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8251 char hw_mode[16] = ""; // n|ac
8252 char bw_mode[16] = ""; // ht|ht vht
8253 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8254 int sec_chan_offset;
8255 int width;
developer4fb0b922022-09-30 14:29:09 +08008256 char config_file[64] = {0};
8257 BOOL stbcEnable = FALSE;
8258 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008259
8260 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8261
8262 freq = util_chan_to_freq(channel);
8263
8264 // Get radio mode HT20|HT40|HT80 etc.
8265 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
8266 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8267 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8268 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8269 if (sec_chan_offset != -EINVAL)
8270 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
8271
8272
8273 // Provide bandwith if specified
8274 if (channel_width_MHz > 20) {
8275 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8276 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8277 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
8278
8279 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8280 }
8281
8282 int center_chan = 0;
8283 if (channel_width_MHz > 20) {
8284 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8285 if (center_chan > 0) {
8286 int center_freq1 = util_chan_to_freq(center_chan);
8287 if (center_freq1)
8288 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8289 }
8290 }
8291
developer06a01d92022-09-07 16:32:39 +08008292 // Only the first AP, other are hanging on the same radio
8293 int apIndex = radioIndex;
developer76989232022-10-04 14:13:19 +08008294 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8295 AP_PREFIX, apIndex, csa_beacon_count, freq,
8296 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8297 wifi_dbg_printf("execute: '%s'\n", cmd);
8298 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008299
developer76989232022-10-04 14:13:19 +08008300 ret = wifi_setRadioChannel(radioIndex, channel);
8301 if (ret != RETURN_OK) {
8302 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8303 return RETURN_ERR;
8304 }
developer06a01d92022-09-07 16:32:39 +08008305
developer4fb0b922022-09-30 14:29:09 +08008306 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8307 _syscmd(cmd, buf, sizeof(buf));
8308 if (strlen(buf) != 0)
8309 stbcEnable = TRUE;
8310
developer06a01d92022-09-07 16:32:39 +08008311 char *ext_str = "None";
8312 if (sec_chan_offset == 1) ext_str = "Above";
8313 else if (sec_chan_offset == -1) ext_str = "Below";
8314 wifi_setRadioExtChannel(radioIndex, ext_str);
8315
8316 wifi_setRadioCenterChannel(radioIndex, center_chan);
8317
developer4fb0b922022-09-30 14:29:09 +08008318 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8319
developer06a01d92022-09-07 16:32:39 +08008320 char mhz_str[16];
8321 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8322 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8323
8324 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8325
8326 return RETURN_OK;
8327}
8328
8329INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8330{
developer615510b2022-09-27 10:14:35 +08008331 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008332 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008333 char cmd[256]={0};
8334 char buf[128]={0};
8335 char file_name[32] = {0};
8336 char filter_SSID[32] = {0};
8337 char line[256] = {0};
8338 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008339 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008340 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008341 size_t len=0;
8342 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008343 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008344 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008345 bool filter_enable = false;
8346 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008347
developer615510b2022-09-27 10:14:35 +08008348 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008349
developer615510b2022-09-27 10:14:35 +08008350 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8351 f = fopen(file_name, "r");
8352 if (f != NULL) {
8353 fgets(filter_SSID, sizeof(file_name), f);
8354 if (strlen(filter_SSID) != 0)
8355 filter_enable = true;
8356 fclose(f);
8357 }
8358
8359 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8360 _syscmd(cmd, buf, sizeof(buf));
8361 channels_num = strtol(buf, NULL, 10);
8362
developer615510b2022-09-27 10:14:35 +08008363 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8364 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", AP_PREFIX, radio_index, AP_PREFIX, radio_index);
8365 fprintf(stderr, "cmd: %s\n", cmd);
8366 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008367 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8368 return RETURN_ERR;
8369 }
developer5550e242022-09-30 09:59:32 +08008370
8371 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8372 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8373
developer615510b2022-09-27 10:14:35 +08008374 ret = fgets(line, sizeof(line), f);
8375 while (ret != NULL) {
8376 if(strstr(line, "BSS") != NULL) { // new neighbor info
8377 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8378 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8379 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8380
8381 if (!filter_BSS) {
8382 index++;
8383 wifi_neighbor_ap2_t *tmp;
8384 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8385 if (tmp == NULL) { // no more memory to use
8386 index--;
8387 wifi_dbg_printf("%s: realloc failed\n", __func__);
8388 break;
8389 }
8390 scan_array = tmp;
8391 }
8392 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008393
developer615510b2022-09-27 10:14:35 +08008394 filter_BSS = false;
8395 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8396 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8397 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8398 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8399 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008400 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008401 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008402
developer615510b2022-09-27 10:14:35 +08008403 if (freq >= 2412 && freq <= 2484) {
8404 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8405 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8406 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8407 }
8408 else if (freq >= 5160 && freq <= 5805) {
8409 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8410 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8411 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8412 }
developer06a01d92022-09-07 16:32:39 +08008413
developer615510b2022-09-27 10:14:35 +08008414 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008415 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008416 for (int i = 0; i < channels_num; i++) {
8417 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8418 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8419 break;
8420 }
8421 }
developer06a01d92022-09-07 16:32:39 +08008422 }
developer615510b2022-09-27 10:14:35 +08008423 } else if (strstr(line, "beacon interval") != NULL) {
8424 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8425 } else if (strstr(line, "signal") != NULL) {
8426 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8427 } else if (strstr(line,"SSID") != NULL) {
8428 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8429 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8430 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008431 }
developer615510b2022-09-27 10:14:35 +08008432 } else if (strstr(line, "Supported rates") != NULL) {
8433 char SRate[80] = {0}, *tmp = NULL;
8434 memset(buf, 0, sizeof(buf));
8435 strcpy(SRate, line);
8436 tmp = strtok(SRate, ":");
8437 tmp = strtok(NULL, ":");
8438 strcpy(buf, tmp);
8439 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008440
developer615510b2022-09-27 10:14:35 +08008441 tmp = strtok(buf, " \n");
8442 while (tmp != NULL) {
8443 strcat(SRate, tmp);
8444 if (SRate[strlen(SRate) - 1] == '*') {
8445 SRate[strlen(SRate) - 1] = '\0';
8446 }
8447 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008448
developer615510b2022-09-27 10:14:35 +08008449 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008450 }
developer615510b2022-09-27 10:14:35 +08008451 SRate[strlen(SRate) - 1] = '\0';
8452 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8453 } else if (strstr(line, "DTIM") != NULL) {
8454 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8455 } else if (strstr(line, "VHT capabilities") != NULL) {
8456 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8457 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8458 } else if (strstr(line, "HT capabilities") != NULL) {
8459 strcat(scan_array[index].ap_SupportedStandards, ",n");
8460 strcpy(scan_array[index].ap_OperatingStandards, "n");
8461 } else if (strstr(line, "VHT operation") != NULL) {
8462 ret = fgets(line, sizeof(line), f);
8463 sscanf(line," * channel width: %d", &vht_channel_width);
8464 if(vht_channel_width == 1) {
8465 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8466 } else {
8467 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8468 }
8469 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8470 continue;
8471 } else if (strstr(line, "HT operation") != NULL) {
8472 ret = fgets(line, sizeof(line), f);
8473 sscanf(line," * secondary channel offset: %s", &buf);
8474 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008475 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008476 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
developer06a01d92022-09-07 16:32:39 +08008477 }
developer615510b2022-09-27 10:14:35 +08008478 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008479 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008480 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8481 } else {
8482 //20Mhz
8483 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
developer06a01d92022-09-07 16:32:39 +08008484 }
developer615510b2022-09-27 10:14:35 +08008485 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008486 continue;
developer615510b2022-09-27 10:14:35 +08008487 } else if (strstr(line, "HE capabilities") != NULL) {
8488 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8489 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8490 ret = fgets(line, sizeof(line), f);
8491 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8492 if (strstr(line, "HE40/2.4GHz") != NULL)
8493 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8494 else
8495 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8496 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8497 if (strstr(line, "HE80/5GHz") != NULL) {
8498 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8499 ret = fgets(line, sizeof(line), f);
8500 } else
8501 continue;
8502 if (strstr(line, "HE160/5GHz") != NULL)
8503 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008504 }
developer615510b2022-09-27 10:14:35 +08008505 continue;
8506 } else if (strstr(line, "WPA") != NULL) {
8507 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8508 } else if (strstr(line, "RSN") != NULL) {
8509 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8510 } else if (strstr(line, "Group cipher") != NULL) {
8511 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8512 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8513 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008514 }
developer06a01d92022-09-07 16:32:39 +08008515 }
developer615510b2022-09-27 10:14:35 +08008516 ret = fgets(line, sizeof(line), f);
8517 }
8518
8519 if (!filter_BSS) {
8520 *output_array_size = index + 1;
8521 } else {
8522 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8523 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008524 }
developer06a01d92022-09-07 16:32:39 +08008525 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008526 pclose(f);
developer5550e242022-09-30 09:59:32 +08008527 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008528 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008529 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008530}
developer615510b2022-09-27 10:14:35 +08008531
developer06a01d92022-09-07 16:32:39 +08008532INT wifi_getApAssociatedDeviceStats(
8533 INT apIndex,
8534 mac_address_t *clientMacAddress,
8535 wifi_associated_dev_stats_t *associated_dev_stats,
8536 u64 *handle)
8537{
8538 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8539 char interface_name[50] = {0};
8540 char cmd[1024] = {0};
8541 char mac_str[18] = {0};
8542 char *key = NULL;
8543 char *val = NULL;
8544 FILE *f = NULL;
8545 char *line = NULL;
8546 size_t len = 0;
8547 ssize_t read = 0;
8548
8549 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8550 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8551 return RETURN_ERR;
8552 }
8553
8554 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8555 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8556 if((f = popen(cmd, "r")) == NULL) {
8557 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8558 return RETURN_ERR;
8559 }
8560
8561 while ((read = getline(&line, &len, f)) != -1) {
8562 key = strtok(line,":");
8563 val = strtok(NULL,":");
8564
8565 if(!strncmp(key,"rx bytes",8))
8566 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8567 if(!strncmp(key,"tx bytes",8))
8568 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8569 if(!strncmp(key,"rx packets",10))
8570 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8571 if(!strncmp(key,"tx packets",10))
8572 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8573 if(!strncmp(key,"tx retries",10))
8574 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8575 if(!strncmp(key,"tx failed",9))
8576 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8577 if(!strncmp(key,"rx drop misc",13))
8578 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8579 if(!strncmp(key,"rx bitrate",10)) {
8580 val = strtok(val, " ");
8581 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8582 }
8583 if(!strncmp(key,"tx bitrate",10)) {
8584 val = strtok(val, " ");
8585 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8586 }
8587 }
8588 free(line);
8589 pclose(f);
8590 return RETURN_OK;
8591}
8592
8593INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8594{
8595 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8596
8597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8598 if (NULL == output_string)
8599 return RETURN_ERR;
8600
8601 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8602 _syscmd(cmd, buf, sizeof(buf));
8603
8604 //size of SSID name restricted to value less than 32 bytes
8605 snprintf(output_string, 32, "%s", buf);
8606 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8607
8608 return RETURN_OK;
8609}
8610
8611INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8612{
8613 //char cmd[MAX_CMD_SIZE] = {0};
8614 char config_file[MAX_BUF_SIZE] = {0};
8615 char buf[32] = {0};
8616
8617 if (!output_filterMode)
8618 return RETURN_ERR;
8619
8620 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8621 //_syscmd(cmd, buf, sizeof(buf));
8622 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8623 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008624 if(strlen(buf) == 0) {
8625 *output_filterMode = 0;
8626 }
8627 else {
8628 int macaddr_acl_mode = strtol(buf, NULL, 10);
8629 if (macaddr_acl_mode == 1) {
8630 *output_filterMode = 1;
8631 } else if (macaddr_acl_mode == 0) {
8632 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8633 if (strlen(buf) == 0) {
8634 *output_filterMode = 0;
8635 } else {
8636 *output_filterMode = 2;
8637 }
8638 } else {
8639 return RETURN_ERR;
8640 }
8641 }
developer06a01d92022-09-07 16:32:39 +08008642
8643 return RETURN_OK;
8644}
8645
8646INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8647{
8648 FILE *fp = NULL;
8649 char str[MAX_BUF_SIZE] = {0};
8650 int wificlientindex = 0 ;
8651 int count = 0;
8652 int signalstrength = 0;
8653 int arr[MACADDRESS_SIZE] = {0};
8654 unsigned char mac[MACADDRESS_SIZE] = {0};
8655 UINT wifi_count = 0;
8656 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8657 char pipeCmd[MAX_CMD_SIZE] = {0};
8658
8659 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8660 *output_array_size = 0;
8661 *associated_dev_array = NULL;
8662 char interface_name[50] = {0};
8663
8664 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8665 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8666 return RETURN_ERR;
8667 }
8668
8669 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8670 fp = popen(pipeCmd, "r");
8671 if (fp == NULL)
8672 {
8673 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8674 return RETURN_ERR;
8675 }
8676
8677 /* Read the output a line at a time - output it. */
8678 fgets(str, sizeof(str)-1, fp);
8679 wifi_count = (unsigned int) atoi ( str );
8680 *output_array_size = wifi_count;
8681 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8682 pclose(fp);
8683
8684 if(wifi_count == 0)
8685 {
8686 return RETURN_OK;
8687 }
8688 else
8689 {
8690 wifi_associated_dev2_t* temp = NULL;
8691 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8692 *associated_dev_array = temp;
8693 if(temp == NULL)
8694 {
8695 printf("Error Statement. Insufficient memory \n");
8696 return RETURN_ERR;
8697 }
8698
8699 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8700 system(pipeCmd);
8701
8702 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8703 if(fp == NULL)
8704 {
8705 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8706 return RETURN_ERR;
8707 }
8708 fclose(fp);
8709
8710 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8711 fp = popen(pipeCmd, "r");
8712 if(fp)
8713 {
8714 for(count =0 ; count < wifi_count; count++)
8715 {
8716 fgets(str, MAX_BUF_SIZE, fp);
8717 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8718 {
8719 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8720 {
8721 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8722
8723 }
8724 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8725 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]);
8726 }
8727 temp[count].cli_AuthenticationState = 1; //TODO
8728 temp[count].cli_Active = 1; //TODO
8729 }
8730 pclose(fp);
8731 }
8732
8733 //Updating RSSI per client
8734 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8735 fp = popen(pipeCmd, "r");
8736 if(fp)
8737 {
8738 pclose(fp);
8739 }
8740 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8741 if(fp)
8742 {
8743 for(count =0 ; count < wifi_count ;count++)
8744 {
8745 fgets(str, MAX_BUF_SIZE, fp);
8746 signalstrength = atoi(str);
8747 temp[count].cli_RSSI = signalstrength;
8748 }
8749 pclose(fp);
8750 }
8751
8752
8753 //LastDataDownlinkRate
8754 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8755 fp = popen(pipeCmd, "r");
8756 if (fp)
8757 {
8758 pclose(fp);
8759 }
8760 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8761 if (fp)
8762 {
8763 for (count = 0; count < wifi_count; count++)
8764 {
8765 fgets(str, MAX_BUF_SIZE, fp);
8766 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8767 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8768 }
8769 pclose(fp);
8770 }
8771
8772 //LastDataUplinkRate
8773 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8774 fp = popen(pipeCmd, "r");
8775 if (fp)
8776 {
8777 pclose(fp);
8778 }
8779 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8780 if (fp)
8781 {
8782 for (count = 0; count < wifi_count; count++)
8783 {
8784 fgets(str, MAX_BUF_SIZE, fp);
8785 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8786 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8787 }
8788 pclose(fp);
8789 }
8790 }
8791 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8792 return RETURN_OK;
8793
8794}
8795
8796INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8797{
8798#if 0
8799 /*char buf[1024] = {0};
8800 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8801 _syscmd(cmd, buf, sizeof(buf));*/
8802
8803 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8804 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8805 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8806 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8807
8808 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.
8809 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].
8810 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].
8811 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].
8812 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8813 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8814
8815 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8816 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8817 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8818 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.
8819 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.
8820 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.
8821 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.
8822 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.
8823 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.
8824 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.
8825 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8826#endif
8827
8828 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008829 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008830 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008831 char pipeCmd[128] = {0};
8832 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008833 wifi_ssidTrafficStats2_t *out = output_struct;
8834
developerce736392022-09-13 15:24:34 +08008835 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008836 if (!output_struct)
8837 return RETURN_ERR;
8838
developerce736392022-09-13 15:24:34 +08008839 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8840 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8841 GetInterfaceName(interface_name, HConf_file);
8842 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008843
developer06a01d92022-09-07 16:32:39 +08008844 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008845 if (fp == NULL) {
8846 fprintf(stderr, "%s: popen failed\n", __func__);
8847 return RETURN_ERR;
8848 }
8849 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008850
developerce736392022-09-13 15:24:34 +08008851 if (strlen(str) == 0) // interface not exist
8852 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008853
developerce736392022-09-13 15:24:34 +08008854 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8855 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008856 pclose(fp);
8857
developerce736392022-09-13 15:24:34 +08008858 memset(str, 0, sizeof(str));
8859 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008860 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008861 if (fp == NULL) {
8862 fprintf(stderr, "%s: popen failed\n", __func__);
8863 return RETURN_ERR;
8864 }
8865 fgets(str, sizeof(str), fp);
8866
8867 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8868 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008869 pclose(fp);
developerce736392022-09-13 15:24:34 +08008870
8871 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8872 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8873
8874 // Not supported
8875 output_struct->ssid_RetransCount = 0;
8876 output_struct->ssid_FailedRetransCount = 0;
8877 output_struct->ssid_RetryCount = 0;
8878 output_struct->ssid_MultipleRetryCount = 0;
8879 output_struct->ssid_ACKFailureCount = 0;
8880 output_struct->ssid_AggregatedPacketCount = 0;
8881
developer06a01d92022-09-07 16:32:39 +08008882 return RETURN_OK;
8883}
8884
8885//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).
8886INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8887{
8888 char output_val[16]={'\0'};
8889 char config_file[MAX_BUF_SIZE] = {0};
8890
8891 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8892 if (!output)
8893 return RETURN_ERR;
8894 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8895 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8896
8897 if( strcmp(output_val,"1") == 0 )
8898 *output = TRUE;
8899 else
8900 *output = FALSE;
8901 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8902
8903 return RETURN_OK;
8904}
8905
8906INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8907{
8908 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8909 char str[MAX_BUF_SIZE]={'\0'};
8910 char string[MAX_BUF_SIZE]={'\0'};
8911 char cmd[MAX_CMD_SIZE]={'\0'};
8912 char *ch;
8913 char config_file[MAX_BUF_SIZE] = {0};
8914 struct params params;
8915
8916 if(enable == TRUE)
8917 strcpy(string,"1");
8918 else
8919 strcpy(string,"0");
8920
8921 params.name = "ap_isolate";
8922 params.value = string;
8923
8924 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8925 wifi_hostapdWrite(config_file,&params,1);
8926 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8927
8928 return RETURN_OK;
8929}
8930
8931INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8932{
8933 if (NULL == output_dBm)
8934 return RETURN_ERR;
8935
8936 *output_dBm = 0;
8937 return RETURN_OK;
8938}
8939
8940INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8941{
8942 return RETURN_OK;
8943}
8944INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8945{
8946 return RETURN_OK;
8947}
8948INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8949{
8950 return RETURN_OK;
8951}
8952INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8953{
8954 return RETURN_OK;
8955}
8956INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8957{
8958 return RETURN_OK;
8959}
8960INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8961{
8962 char config_file[MAX_BUF_SIZE] = {0};
8963 struct params list;
8964
8965 list.name = "bss_transition";
8966 list.value = activate?"1":"0";
8967 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8968 wifi_hostapdWrite(config_file, &list, 1);
8969
8970 return RETURN_OK;
8971}
8972wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8973
8974void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8975{
8976 return;
8977}
8978
8979INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8980{
8981 // TODO Implement me!
8982 return RETURN_OK;
8983}
8984
8985INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8986{
developera3c68b92022-09-13 15:27:29 +08008987 char file_name[128] = {0};
8988 char buf[128] = {0};
8989 FILE *f = NULL;
8990
8991 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8992
8993 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8994 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8995 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8996 f = fopen(file_name, "w");
8997 if (f == NULL)
8998 return RETURN_ERR;
8999 // For mode == 0 is to disable filter, just don't write to the file.
9000 if (mode)
9001 fprintf(f, "%s", essid);
9002
9003 fclose(f);
9004 }
9005 } else { // special case, need to set AP's SSID as filter for each radio.
9006 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9007 f = fopen(file_name, "w");
9008 if (f == NULL)
9009 return RETURN_ERR;
9010
9011 // For mode == 0 is to disable filter, just don't write to the file.
9012 if (mode)
9013 fprintf(f, "%s", essid);
9014
9015 fclose(f);
9016 }
9017
9018 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009019 return RETURN_OK;
9020}
9021
9022INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9023{
9024 // TODO Implement me!
9025 //Apply wifi_pushRadioChannel() instantly
9026 return RETURN_ERR;
9027}
9028
9029INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9030{
9031 // TODO Implement me!
9032 return RETURN_OK;
9033}
9034
9035#ifdef HAL_NETLINK_IMPL
9036static int tidStats_callback(struct nl_msg *msg, void *arg) {
9037 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9038 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9039 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9040 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9041 int rem , tid_index = 0;
9042
9043 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9044 wifi_associated_dev_tid_entry_t *stats_entry;
9045
9046 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9047 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9048 };
9049 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9050 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9051 };
9052
9053 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9054 genlmsg_attrlen(gnlh, 0), NULL);
9055
9056
9057 if (!tb[NL80211_ATTR_STA_INFO]) {
9058 fprintf(stderr, "station stats missing!\n");
9059 return NL_SKIP;
9060 }
9061
9062 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9063 tb[NL80211_ATTR_STA_INFO],
9064 stats_policy)) {
9065 fprintf(stderr, "failed to parse nested attributes!\n");
9066 return NL_SKIP;
9067 }
9068
9069 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9070 {
9071 stats_entry = &out->tid_array[tid_index];
9072
9073 stats_entry->tid = tid_index;
9074 stats_entry->ac = _tid_ac_index_get[tid_index];
9075
9076 if(sinfo[NL80211_STA_INFO_TID_STATS])
9077 {
9078 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9079 printf("failed to parse nested stats attributes!");
9080 return NL_SKIP;
9081 }
9082 }
9083 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9084 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9085
9086 if(tid_index < (PS_MAX_TID - 1))
9087 tid_index++;
9088 }
9089 //ToDo: sum_time_ms, ewma_time_ms
9090 return NL_SKIP;
9091}
9092#endif
9093
9094INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9095{
9096#ifdef HAL_NETLINK_IMPL
9097 Netlink nl;
9098 char if_name[10];
9099
9100 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9101
9102 nl.id = initSock80211(&nl);
9103
9104 if (nl.id < 0) {
9105 fprintf(stderr, "Error initializing netlink \n");
9106 return -1;
9107 }
9108
9109 struct nl_msg* msg = nlmsg_alloc();
9110
9111 if (!msg) {
9112 fprintf(stderr, "Failed to allocate netlink message.\n");
9113 nlfree(&nl);
9114 return -2;
9115 }
9116
9117 genlmsg_put(msg,
9118 NL_AUTO_PORT,
9119 NL_AUTO_SEQ,
9120 nl.id,
9121 0,
9122 0,
9123 NL80211_CMD_GET_STATION,
9124 0);
9125
9126 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9127 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9128 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9129 nl_send_auto(nl.socket, msg);
9130 nl_recvmsgs(nl.socket, nl.cb);
9131 nlmsg_free(msg);
9132 nlfree(&nl);
9133 return RETURN_OK;
9134#else
9135//iw implementation
9136#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9137#define TOTAL_MAX_LINES 50
9138
9139 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9140 char if_name[10];
9141 FILE *fp=NULL;
9142 char pipeCmd[1024]= {'\0'};
9143 int lines,tid_index=0;
9144 char mac_addr[20] = {'\0'};
9145
9146 wifi_associated_dev_tid_entry_t *stats_entry;
9147
9148 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9149 strcpy(mac_addr,clientMacAddress);
9150
9151 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9152 fp= popen(pipeCmd,"r");
9153 if(fp == NULL)
9154 {
9155 perror("popen for station dump failed\n");
9156 return RETURN_ERR;
9157 }
9158 pclose(fp);
9159
9160 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9161 fp=popen(pipeCmd,"r");
9162 if(fp == NULL)
9163 {
9164 perror("popen for grep station failed\n");
9165 return RETURN_ERR;
9166 }
9167 else if(fgets(buf,sizeof(buf),fp) != NULL)
9168 lines=atoi(buf);
9169 else
9170 {
9171 pclose(fp);
9172 fprintf(stderr,"No devices are connected \n");
9173 return RETURN_ERR;
9174 }
9175 pclose(fp);
9176
9177 if(lines == 1)
9178 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9179
9180 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9181 {
9182 stats_entry = &tid_stats->tid_array[tid_index];
9183 stats_entry->tid = tid_index;
9184
9185 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);
9186
9187 fp=popen(pipeCmd,"r");
9188 if(fp ==NULL)
9189 {
9190 perror("Failed to read from tid file \n");
9191 return RETURN_ERR;
9192 }
9193 else if(fgets(buf,sizeof(buf),fp) != NULL)
9194 stats_entry->num_msdus = atol(buf);
9195
9196 pclose(fp);
9197 stats_entry->ac = _tid_ac_index_get[tid_index];
9198// TODO:
9199// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9200// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9201 }
9202 return RETURN_OK;
9203#endif
9204}
9205
9206
9207INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9208{
developer615510b2022-09-27 10:14:35 +08009209 char cmd[128]={0};
9210 char buf[128]={0};
9211 int freq = 0;
9212
9213 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9214
9215 // full mode is used to scan all channels.
9216 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9217 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9218 ieee80211_channel_to_frequency(chan_list[0], &freq);
9219
9220 if (freq)
9221 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9222 else
9223 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9224
9225 _syscmd(cmd, buf, sizeof(buf));
9226 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9227
developer06a01d92022-09-07 16:32:39 +08009228 return RETURN_OK;
9229}
9230
9231
9232INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9233{
9234 // TODO Implement me!
9235 return RETURN_ERR;
9236}
9237
9238INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9239{
9240 // TODO Implement me!
9241 return RETURN_ERR;
9242}
9243
9244INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9245{
9246 // TODO Implement me!
9247 return RETURN_ERR;
9248}
9249
9250INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9251{
9252 // TODO Implement me!
9253 return RETURN_ERR;
9254}
9255
9256INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9257{
9258 // TODO Implement me!
9259 return RETURN_ERR;
9260}
9261
9262INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9263{
9264 // TODO Implement me!
9265 return RETURN_ERR;
9266}
9267
9268INT wifi_steering_eventUnregister(void)
9269{
9270 // TODO Implement me!
9271 return RETURN_ERR;
9272}
9273
9274INT wifi_delApAclDevices(INT apIndex)
9275{
9276#if 0
9277 char cmd[MAX_BUF_SIZE] = {0};
9278 char buf[MAX_BUF_SIZE] = {0};
9279
9280 /* Not reset proof solution */
9281 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9282 if(_syscmd(cmd,buf,sizeof(buf)))
9283 return RETURN_ERR;
9284#endif
developere6aafda2022-09-13 14:59:28 +08009285 char cmd[MAX_CMD_SIZE]={0};
9286 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009287
developere6aafda2022-09-13 14:59:28 +08009288 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9289 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9290 if(_syscmd(cmd, buf, sizeof(buf)))
9291 return RETURN_ERR;
9292 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009293
9294 return RETURN_OK;
9295}
9296
9297#ifdef HAL_NETLINK_IMPL
9298static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9299 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9300 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9301 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9302 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9303 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9304 char mac_addr[20],dev[20];
9305
9306 nla_parse(tb,
9307 NL80211_ATTR_MAX,
9308 genlmsg_attrdata(gnlh, 0),
9309 genlmsg_attrlen(gnlh, 0),
9310 NULL);
9311
9312 if(!tb[NL80211_ATTR_STA_INFO]) {
9313 fprintf(stderr, "sta stats missing!\n");
9314 return NL_SKIP;
9315 }
9316
9317 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9318 fprintf(stderr, "failed to parse nested attributes!\n");
9319 return NL_SKIP;
9320 }
9321 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9322
9323 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9324
9325 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9326 fprintf(stderr, "failed to parse nested rate attributes!");
9327 return NL_SKIP;
9328 }
9329
9330 if(sinfo[NL80211_STA_INFO_TID_STATS])
9331 {
9332 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9333 printf("failed to parse nested stats attributes!");
9334 return NL_SKIP;
9335 }
9336 }
9337
9338 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9339 {
9340 printf("Type is VHT\n");
9341 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9342 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9343
9344 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9345 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9346 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9347 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9348 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9349 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9350 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9351 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9352 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9353 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9354 }
9355 else
9356 {
9357 printf(" OFDM or CCK \n");
9358 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9359 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9360 }
9361
9362 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9363 if(rinfo[NL80211_RATE_INFO_MCS])
9364 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9365 }
9366 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9367 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9368 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9369 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9370
9371 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9372 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9373
9374 if (sinfo[NL80211_STA_INFO_SIGNAL])
9375 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9376 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9377 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9378 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9379 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9380 //rssi_array need to be filled
9381 return NL_SKIP;
9382}
9383#endif
9384
9385INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9386{
9387#ifdef HAL_NETLINK_IMPL
9388 Netlink nl;
9389 char if_name[10];
9390
9391 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9392
9393 if (*output_array_size <= 0)
9394 return RETURN_OK;
9395
9396 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9397 nl.id = initSock80211(&nl);
9398
9399 if (nl.id < 0) {
9400 fprintf(stderr, "Error initializing netlink \n");
9401 return 0;
9402 }
9403
9404 struct nl_msg* msg = nlmsg_alloc();
9405
9406 if (!msg) {
9407 fprintf(stderr, "Failed to allocate netlink message.\n");
9408 nlfree(&nl);
9409 return 0;
9410 }
9411
9412 genlmsg_put(msg,
9413 NL_AUTO_PORT,
9414 NL_AUTO_SEQ,
9415 nl.id,
9416 0,
9417 0,
9418 NL80211_CMD_GET_STATION,
9419 0);
9420
9421 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9422 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9423 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9424 nl_send_auto(nl.socket, msg);
9425 nl_recvmsgs(nl.socket, nl.cb);
9426 nlmsg_free(msg);
9427 nlfree(&nl);
9428 return RETURN_OK;
9429#else
9430 //TODO Implement me
9431 return RETURN_OK;
9432#endif
9433}
9434
9435#ifdef HAL_NETLINK_IMPL
9436static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9437 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9438 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9439 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9440 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9441 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9442 char mac_addr[20],dev[20];
9443
9444 nla_parse(tb,
9445 NL80211_ATTR_MAX,
9446 genlmsg_attrdata(gnlh, 0),
9447 genlmsg_attrlen(gnlh, 0),
9448 NULL);
9449
9450 if(!tb[NL80211_ATTR_STA_INFO]) {
9451 fprintf(stderr, "sta stats missing!\n");
9452 return NL_SKIP;
9453 }
9454
9455 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9456 fprintf(stderr, "failed to parse nested attributes!\n");
9457 return NL_SKIP;
9458 }
9459
9460 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9461
9462 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9463
9464 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9465 fprintf(stderr, "failed to parse nested rate attributes!");
9466 return NL_SKIP;
9467 }
9468
9469 if(sinfo[NL80211_STA_INFO_TID_STATS])
9470 {
9471 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9472 printf("failed to parse nested stats attributes!");
9473 return NL_SKIP;
9474 }
9475 }
9476 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9477 {
9478 printf("Type is VHT\n");
9479 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9480 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9481
9482 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9483 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9484 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9485 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9486 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9487 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9488 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9489 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9490 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9491 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9492 }
9493 else
9494 {
9495 printf(" OFDM or CCK \n");
9496 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9497 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9498 }
9499
9500 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9501 if(rinfo[NL80211_RATE_INFO_MCS])
9502 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9503 }
9504
9505 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9506 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9507 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9508 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9509
9510 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9511 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9512 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9513
9514 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9515 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9516
9517 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9518 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9519
9520 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9521 ((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]);
9522
9523 return NL_SKIP;
9524}
9525#endif
9526
9527INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9528{
9529#ifdef HAL_NETLINK_IMPL
9530 Netlink nl;
9531 char if_name[10];
9532
9533 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9534
9535 if (*output_array_size <= 0)
9536 return RETURN_OK;
9537
9538 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9539
9540 nl.id = initSock80211(&nl);
9541
9542 if(nl.id < 0) {
9543 fprintf(stderr, "Error initializing netlink \n");
9544 return 0;
9545 }
9546
9547 struct nl_msg* msg = nlmsg_alloc();
9548
9549 if(!msg) {
9550 fprintf(stderr, "Failed to allocate netlink message.\n");
9551 nlfree(&nl);
9552 return 0;
9553 }
9554
9555 genlmsg_put(msg,
9556 NL_AUTO_PORT,
9557 NL_AUTO_SEQ,
9558 nl.id,
9559 0,
9560 0,
9561 NL80211_CMD_GET_STATION,
9562 0);
9563
9564 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9565 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9566 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9567 nl_send_auto(nl.socket, msg);
9568 nl_recvmsgs(nl.socket, nl.cb);
9569 nlmsg_free(msg);
9570 nlfree(&nl);
9571 return RETURN_OK;
9572#else
9573 //TODO Implement me
9574 return RETURN_OK;
9575#endif
9576}
9577
9578INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9579{
9580 // TODO Implement me!
9581 char buf[MAX_BUF_SIZE] = {0};
9582 char config_file[MAX_BUF_SIZE] = {0};
9583
9584 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9585 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9586 *activate = (strncmp("1",buf,1) == 0);
9587
9588 return RETURN_OK;
9589}
9590
9591INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9592{
9593 char config_file[MAX_BUF_SIZE] = {0};
9594 struct params list;
9595
9596 list.name = "rrm_neighbor_report";
9597 list.value = activate?"1":"0";
9598 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9599 wifi_hostapdWrite(config_file, &list, 1);
9600
9601 return RETURN_OK;
9602}
9603
9604INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9605{
9606 char buf[32] = {0};
9607 char config_file[MAX_BUF_SIZE] = {0};
9608
9609 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9610 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9611 *activate = (strncmp("1",buf,1) == 0);
9612
9613 return RETURN_OK;
9614}
9615#undef HAL_NETLINK_IMPL
9616#ifdef HAL_NETLINK_IMPL
9617static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9618 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9619 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9620 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9621 char dev[20];
9622 int freq =0 ;
9623 static int i=0;
9624
9625 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9626
9627 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9628 };
9629
9630 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9631
9632 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9633
9634 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9635 fprintf(stderr, "survey data missing!\n");
9636 return NL_SKIP;
9637 }
9638
9639 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9640 {
9641 fprintf(stderr, "failed to parse nested attributes!\n");
9642 return NL_SKIP;
9643 }
9644
9645
9646 if(out[0].array_size == 1 )
9647 {
9648 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9649 {
9650 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9651 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9652 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9653
9654 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9655 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9656 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9657 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9658 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9659 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9660 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9661 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9662 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9663 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9664 if (sinfo[NL80211_SURVEY_INFO_TIME])
9665 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9666 return NL_STOP;
9667 }
9668 }
9669 else
9670 {
9671 if ( i <= out[0].array_size )
9672 {
9673 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9674 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9675 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9676
9677 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9678 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9679 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9680 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9681 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9682 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9683 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9684 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9685 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9686 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9687 if (sinfo[NL80211_SURVEY_INFO_TIME])
9688 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9689 }
9690 }
9691
9692 i++;
9693 return NL_SKIP;
9694}
9695#endif
9696
9697static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9698{
9699 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9700 FILE *fp;
9701
9702 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9703 {
9704 printf("Creating Frequency-Channel Map\n");
9705 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9706 }
9707 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9708 if((fp = popen(command, "r")))
9709 {
9710 fgets(output, sizeof(output), fp);
9711 *freqMHz = atoi(output);
9712 fclose(fp);
9713 }
9714
9715 return 0;
9716}
9717
9718static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9719{
9720 int freqMHz = -1;
9721 char cmd[MAX_CMD_SIZE] = {'\0'};
9722
9723 ieee80211_channel_to_frequency(channel, &freqMHz);
9724 if (freqMHz == -1) {
9725 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9726 return -1;
9727 }
9728
9729 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9730 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9731 radioIndex, freqMHz);
9732 return -1;
9733 }
9734
9735 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9736 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9737 return -1;
9738 }
9739
9740 return 0;
9741}
9742
9743static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9744{
9745 const char *ptr = buf;
9746 char *key = NULL;
9747 char *val = NULL;
9748 char line[256] = { '\0' };
9749
9750 while (ptr = get_line_from_str_buf(ptr, line)) {
9751 if (strstr(line, "Frequency")) continue;
9752
9753 key = strtok(line, ":");
9754 val = strtok(NULL, " ");
9755 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9756
9757 if (!strcmp(key, "noise")) {
9758 sscanf(val, "%d", &stats->ch_noise);
9759 if (stats->ch_noise == 0) {
9760 // Workaround for missing noise information.
9761 // Assume -95 for 2.4G and -103 for 5G
9762 if (radioIndex == 0) stats->ch_noise = -95;
9763 if (radioIndex == 1) stats->ch_noise = -103;
9764 }
9765 }
9766 else if (!strcmp(key, "channel active time")) {
9767 sscanf(val, "%llu", &stats->ch_utilization_total);
9768 }
9769 else if (!strcmp(key, "channel busy time")) {
9770 sscanf(val, "%llu", &stats->ch_utilization_busy);
9771 }
9772 else if (!strcmp(key, "channel receive time")) {
9773 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9774 }
9775 else if (!strcmp(key, "channel transmit time")) {
9776 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9777 }
9778 };
9779
9780 return 0;
9781}
9782
9783INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9784{
9785 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9786#ifdef HAL_NETLINK_IMPL
9787 Netlink nl;
9788 wifi_channelStats_t_loc local[array_size];
9789 char if_name[10];
9790
9791 local[0].array_size = array_size;
9792
9793 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9794
9795 nl.id = initSock80211(&nl);
9796
9797 if (nl.id < 0) {
9798 fprintf(stderr, "Error initializing netlink \n");
9799 return -1;
9800 }
9801
9802 struct nl_msg* msg = nlmsg_alloc();
9803
9804 if (!msg) {
9805 fprintf(stderr, "Failed to allocate netlink message.\n");
9806 nlfree(&nl);
9807 return -2;
9808 }
9809
9810 genlmsg_put(msg,
9811 NL_AUTO_PORT,
9812 NL_AUTO_SEQ,
9813 nl.id,
9814 0,
9815 NLM_F_DUMP,
9816 NL80211_CMD_GET_SURVEY,
9817 0);
9818
9819 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9820 nl_send_auto(nl.socket, msg);
9821 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9822 nl_recvmsgs(nl.socket, nl.cb);
9823 nlmsg_free(msg);
9824 nlfree(&nl);
9825 //Copying the Values
9826 for(int i=0;i<array_size;i++)
9827 {
9828 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9829 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9830 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9831 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9832 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9833 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9834 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9835 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9836 }
9837#else
9838 ULONG channel = 0;
9839 int i;
9840 int number_of_channels = array_size;
9841 char buf[512];
9842 INT ret;
9843 wifi_channelStats_t tmp_stats;
9844
9845 if (number_of_channels == 0) {
9846 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9847 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9848 return RETURN_ERR;
9849 }
9850 number_of_channels = 1;
9851 input_output_channelStats_array[0].ch_number = channel;
9852 }
9853
9854 for (i = 0; i < number_of_channels; i++) {
9855
9856 input_output_channelStats_array[i].ch_noise = 0;
9857 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9858 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9859 input_output_channelStats_array[i].ch_utilization_busy = 0;
9860 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9861 input_output_channelStats_array[i].ch_utilization_total = 0;
9862
9863 memset(buf, 0, sizeof(buf));
9864 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9865 return RETURN_ERR;
9866 }
9867 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9868 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9869 return RETURN_ERR;
9870 }
9871
9872 // XXX: fake missing 'self' counter which is not available in iw survey output
9873 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9874 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9875
9876 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9877 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9878 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9879 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9880 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9881
9882 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",
9883 __func__,
9884 input_output_channelStats_array[i].ch_number,
9885 input_output_channelStats_array[i].ch_noise,
9886 input_output_channelStats_array[i].ch_utilization_total,
9887 input_output_channelStats_array[i].ch_utilization_busy,
9888 input_output_channelStats_array[i].ch_utilization_busy_rx,
9889 input_output_channelStats_array[i].ch_utilization_busy_tx,
9890 input_output_channelStats_array[i].ch_utilization_busy_self,
9891 input_output_channelStats_array[i].ch_utilization_busy_ext);
9892 }
9893#endif
9894 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9895 return RETURN_OK;
9896}
9897#define HAL_NETLINK_IMPL
9898
9899/* Hostapd events */
9900
9901#ifndef container_of
9902#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9903#define container_of(ptr, type, member) \
9904 ((type *)((char *)ptr - offset_of(type, member)))
9905#endif /* container_of */
9906
9907struct ctrl {
9908 char sockpath[128];
9909 char sockdir[128];
9910 char bss[IFNAMSIZ];
9911 char reply[4096];
9912 int ssid_index;
9913 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9914 void (*overrun)(struct ctrl *ctrl);
9915 struct wpa_ctrl *wpa;
9916 unsigned int ovfl;
9917 size_t reply_len;
9918 int initialized;
9919 ev_timer retry;
9920 ev_timer watchdog;
9921 ev_stat stat;
9922 ev_io io;
9923};
9924static wifi_newApAssociatedDevice_callback clients_connect_cb;
9925static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9926static struct ctrl wpa_ctrl[MAX_APS];
9927static int initialized;
9928
9929static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9930{
9931 char cbuf[256] = {};
9932 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9933 struct cmsghdr *cmsg;
9934 unsigned int ovfl = ctrl->ovfl;
9935 unsigned int drop;
9936
9937 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9938 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9939 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9940 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9941
9942 drop = ovfl - ctrl->ovfl;
9943 ctrl->ovfl = ovfl;
9944
9945 return drop;
9946}
9947
9948static void ctrl_close(struct ctrl *ctrl)
9949{
9950 if (ctrl->io.cb)
9951 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9952 if (ctrl->retry.cb)
9953 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9954 if (!ctrl->wpa)
9955 return;
9956
9957 wpa_ctrl_detach(ctrl->wpa);
9958 wpa_ctrl_close(ctrl->wpa);
9959 ctrl->wpa = NULL;
9960 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9961}
9962
9963static void ctrl_process(struct ctrl *ctrl)
9964{
9965 const char *str;
9966 int drops;
9967 int level;
9968 int err;
9969
9970 /* Example events:
9971 *
9972 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9973 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9974 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9975 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9976 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9977 */
9978 if (!(str = index(ctrl->reply, '>')))
9979 return;
9980 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9981 return;
9982
9983 str++;
9984
9985 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9986 if (!(str = index(ctrl->reply, ' ')))
9987 return;
9988 wifi_associated_dev_t sta;
9989 memset(&sta, 0, sizeof(sta));
9990
9991 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9992 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9993 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9994
9995 sta.cli_Active=true;
9996
9997 (clients_connect_cb)(ctrl->ssid_index, &sta);
9998 goto handled;
9999 }
10000
10001 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10002 if (!(str = index(ctrl->reply, ' ')))
10003 return;
10004
10005 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10006 goto handled;
10007 }
10008
10009 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10010 printf("CTRL_WPA: handle TERMINATING event\n");
10011 goto retry;
10012 }
10013
10014 if (strncmp("AP-DISABLED", str, 11) == 0) {
10015 printf("CTRL_WPA: handle AP-DISABLED\n");
10016 goto retry;
10017 }
10018
10019 printf("Event not supported!!\n");
10020
10021handled:
10022
10023 if ((drops = ctrl_get_drops(ctrl))) {
10024 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10025 if (ctrl->overrun)
10026 ctrl->overrun(ctrl);
10027 }
10028
10029 return;
10030
10031retry:
10032 printf("WPA_CTRL: closing\n");
10033 ctrl_close(ctrl);
10034 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10035 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10036}
10037
10038static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10039{
10040 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10041 int err;
10042
10043 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10044 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10045 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10046 ctrl->reply[ctrl->reply_len] = 0;
10047 if (err < 0) {
10048 if (errno == EAGAIN || errno == EWOULDBLOCK)
10049 return;
10050 ctrl_close(ctrl);
10051 ev_timer_again(EV_A_ &ctrl->retry);
10052 return;
10053 }
10054
10055 ctrl_process(ctrl);
10056}
10057
10058static int ctrl_open(struct ctrl *ctrl)
10059{
10060 int fd;
10061
10062 if (ctrl->wpa)
10063 return 0;
10064
10065 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10066 if (!ctrl->wpa)
10067 goto err;
10068
10069 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10070 goto err_close;
10071
10072 fd = wpa_ctrl_get_fd(ctrl->wpa);
10073 if (fd < 0)
10074 goto err_detach;
10075
10076 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10077 goto err_detach;
10078
10079 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10080 ev_io_start(EV_DEFAULT_ &ctrl->io);
10081
10082 return 0;
10083
10084err_detach:
10085 wpa_ctrl_detach(ctrl->wpa);
10086err_close:
10087 wpa_ctrl_close(ctrl->wpa);
10088err:
10089 ctrl->wpa = NULL;
10090 return -1;
10091}
10092
10093static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10094{
10095 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10096
10097 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10098 ctrl_open(ctrl);
10099}
10100
10101static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10102{
10103 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10104
10105 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10106 if (ctrl_open(ctrl) == 0) {
10107 printf("WPA_CTRL: retry successful\n");
10108 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10109 }
10110}
10111
10112int ctrl_enable(struct ctrl *ctrl)
10113{
10114 if (ctrl->wpa)
10115 return 0;
10116
10117 if (!ctrl->stat.cb) {
10118 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10119 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10120 }
10121
10122 if (!ctrl->retry.cb) {
10123 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10124 }
10125
10126 return ctrl_open(ctrl);
10127}
10128
10129static void
10130ctrl_msg_cb(char *buf, size_t len)
10131{
10132 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10133
10134 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10135 ctrl_process(ctrl);
10136}
10137
10138static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10139{
10140 int err;
10141
10142 if (!ctrl->wpa)
10143 return -1;
10144 if (*reply_len < 2)
10145 return -1;
10146
10147 (*reply_len)--;
10148 ctrl->reply_len = sizeof(ctrl->reply);
10149 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10150 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10151 if (err < 0)
10152 return err;
10153
10154 if (ctrl->reply_len > *reply_len)
10155 ctrl->reply_len = *reply_len;
10156
10157 *reply_len = ctrl->reply_len;
10158 memcpy(reply, ctrl->reply, *reply_len);
10159 reply[*reply_len - 1] = 0;
10160 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10161 return 0;
10162}
10163
10164static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10165{
10166 const char *pong = "PONG";
10167 const char *ping = "PING";
10168 char reply[1024];
10169 size_t len = sizeof(reply);
10170 int err;
10171 ULONG s, snum;
10172 INT ret;
10173 BOOL status;
10174
10175 printf("WPA_CTRL: watchdog cb\n");
10176
10177 ret = wifi_getSSIDNumberOfEntries(&snum);
10178 if (ret != RETURN_OK) {
10179 printf("%s: failed to get SSID count", __func__);
10180 return;
10181 }
10182
10183 if (snum > MAX_APS) {
10184 printf("more ssid than supported! %lu\n", snum);
10185 return;
10186 }
10187
10188 for (s = 0; s < snum; s++) {
10189 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10190 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10191 continue;
10192 }
10193 if (status == false) continue;
10194
10195 memset(reply, 0, sizeof(reply));
10196 len = sizeof(reply);
10197 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10198 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10199 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10200 continue;
10201
10202 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10203 ctrl_close(&wpa_ctrl[s]);
10204 printf("WPA_CTRL: ev_timer_again %d\n", s);
10205 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10206 }
10207}
10208
10209static int init_wpa()
10210{
10211 int ret = 0, i = 0;
10212 ULONG s, snum;
10213
10214 ret = wifi_getSSIDNumberOfEntries(&snum);
10215 if (ret != RETURN_OK) {
10216 printf("%s: failed to get SSID count", __func__);
10217 return RETURN_ERR;
10218 }
10219
10220 if (snum > MAX_APS) {
10221 printf("more ssid than supported! %lu\n", snum);
10222 return RETURN_ERR;
10223 }
10224
10225 for (s = 0; s < snum; s++) {
10226 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10227 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10228 wpa_ctrl[s].ssid_index = s;
10229 ctrl_enable(&wpa_ctrl[s]);
10230 }
10231
10232 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10233 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10234
10235 initialized = 1;
10236 printf("WPA_CTRL: initialized\n");
10237
10238 return RETURN_OK;
10239}
10240
10241void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10242{
10243 clients_connect_cb = callback_proc;
10244 if (!initialized)
10245 init_wpa();
10246}
10247
10248void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10249{
10250 clients_disconnect_cb = callback_proc;
10251 if (!initialized)
10252 init_wpa();
10253}
10254
10255INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10256{
10257 // TODO Implement me!
10258 return RETURN_ERR;
10259}
10260
10261INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10262{
10263 // TODO Implement me!
10264 return RETURN_ERR;
10265}
10266
10267INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10268{
10269 int i;
10270 char cmd[256];
10271 char channel_numbers_buf[256];
10272 char dfs_state_buf[256];
10273 char line[256];
10274 const char *ptr;
10275
10276 memset(cmd, 0, sizeof(cmd));
10277 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10278 memset(line, 0, sizeof(line));
10279 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10280 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10281
10282 if (radioIndex == 0) { // 2.4G - all allowed
10283 if (outputMapSize < 11) {
10284 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10285 return RETURN_ERR;
10286 }
10287
10288 for (i = 0; i < 11; i++) {
10289 outputMap[i].ch_number = i + 1;
10290 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10291 }
10292
10293 return RETURN_OK;
10294 }
10295
10296 if (radioIndex == 1) { // 5G
10297// Example output of iw list:
10298//
10299// Frequencies:
10300// * 5180 MHz [36] (17.0 dBm)
10301// * 5200 MHz [40] (17.0 dBm)
10302// * 5220 MHz [44] (17.0 dBm)
10303// * 5240 MHz [48] (17.0 dBm)
10304// * 5260 MHz [52] (23.0 dBm) (radar detection)
10305// DFS state: usable (for 78930 sec)
10306// DFS CAC time: 60000 ms
10307// * 5280 MHz [56] (23.0 dBm) (radar detection)
10308// DFS state: usable (for 78930 sec)
10309// DFS CAC time: 60000 ms
10310// * 5300 MHz [60] (23.0 dBm) (radar detection)
10311// DFS state: usable (for 78930 sec)
10312// DFS CAC time: 60000 ms
10313// * 5320 MHz [64] (23.0 dBm) (radar detection)
10314// DFS state: usable (for 78930 sec)
10315// DFS CAC time: 60000 ms
10316// * 5500 MHz [100] (disabled)
10317// * 5520 MHz [104] (disabled)
10318// * 5540 MHz [108] (disabled)
10319// * 5560 MHz [112] (disabled)
10320//
10321// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10322 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10323 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10324 return RETURN_ERR;
10325 }
10326
10327 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10328 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10329 return RETURN_ERR;
10330 }
10331
10332 ptr = channel_numbers_buf;
10333 i = 0;
10334 while (ptr = get_line_from_str_buf(ptr, line)) {
10335 if (i >= outputMapSize) {
10336 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10337 return RETURN_ERR;
10338 }
10339 sscanf(line, "%d", &outputMap[i].ch_number);
10340
10341 memset(cmd, 0, sizeof(cmd));
10342 // Below command should fetch string for DFS state (usable, available or unavailable)
10343 // Example line: "DFS state: usable (for 78930 sec)"
10344 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) {
10345 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10346 return RETURN_ERR;
10347 }
10348
10349 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10350 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10351 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10352 return RETURN_ERR;
10353 }
10354
10355 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10356
10357 if (!strcmp(dfs_state_buf, "usable")) {
10358 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10359 } else if (!strcmp(dfs_state_buf, "available")) {
10360 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10361 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10362 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10363 } else {
10364 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10365 }
10366 i++;
10367 }
10368
10369 return RETURN_OK;
10370 }
10371
10372 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10373 return RETURN_ERR;
10374}
10375
10376INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10377{
10378 // TODO Implement me!
10379 return RETURN_ERR;
10380}
10381
10382INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10383{
10384 return RETURN_OK;
10385}
10386
10387INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10388{
10389 // TODO Implement me!
10390 return RETURN_ERR;
10391}
10392
10393INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10394{
10395 // TODO API refrence Implementaion is present on RPI hal
10396 return RETURN_ERR;
10397}
10398
10399INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10400{
developera5005b62022-09-13 15:43:35 +080010401 char cmd[128]={'\0'};
10402 char buf[128]={'\0'};
10403 char *support;
10404 int maximum_tx = 0, current_tx = 0;
10405
10406 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10407 if(txpwr_pcntg == NULL)
10408 return RETURN_ERR;
10409
10410 // Get the maximum tx power of the device
10411 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10412 _syscmd(cmd, buf, sizeof(buf));
10413 maximum_tx = strtol(buf, NULL, 10);
10414
10415 // Get the current tx power
10416 memset(cmd, 0, sizeof(cmd));
10417 memset(buf, 0, sizeof(buf));
10418 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10419 _syscmd(cmd, buf, sizeof(buf));
10420 current_tx = strtol(buf, NULL, 10);
10421
10422 // Get the power supported list and find the current power percentage in supported list
10423 memset(buf, 0, sizeof(buf));
10424 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10425 support = strtok(buf, ",");
10426 while(true)
10427 {
10428 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10429 *txpwr_pcntg = 0;
10430 wifi_dbg_printf("current power is not in supported list\n");
10431 return RETURN_ERR;
10432 }
10433 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10434 if (tmp == current_tx) {
10435 *txpwr_pcntg = strtol(support, NULL, 10);
10436 break;
10437 }
10438 support = strtok(NULL, ",");
10439 }
10440 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010441 return RETURN_OK;
10442}
10443
10444INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10445{
developer58599c22022-09-13 16:40:34 +080010446 // TODO precac feature.
10447 struct params params = {0};
10448 char config_file[128] = {0};
10449
10450 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10451
10452 params.name = "enable_background_radar";
10453 params.value = enable?"1":"0";
10454 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10455 wifi_hostapdWrite(config_file, &params, 1);
10456 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10457
10458 /* TODO precac feature */
10459
10460 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10461 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010462}
10463
10464INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10465{
developer58599c22022-09-13 16:40:34 +080010466 char config_file[128] = {0};
10467 char buf[64] = {0};
10468
10469 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10470 if (NULL == enable || NULL == precac)
10471 return RETURN_ERR;
10472
10473 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10474 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10475 if (strncmp(enable, "1", 1) == 0)
10476 *enable = true;
10477 else
10478 *enable = false;
10479
10480 /* TODO precac feature */
10481
10482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10483 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010484}
10485
10486INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10487{
developer58599c22022-09-13 16:40:34 +080010488 *supported = TRUE;
10489 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010490}
10491
developer3e6b1692022-09-30 18:04:05 +080010492INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10493{
10494 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10495 struct params params = {0};
10496 char config_file[64] = {0};
10497 char buf[64] = {0};
10498 unsigned int set_mu_type = 0;
10499 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10500
10501 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10502 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10503
10504 if (strlen(buf) > 0)
10505 set_mu_type = strtol(buf, NULL, 10);
10506
10507 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10508 set_mu_type &= ~0x05; // unset bit 0, 2
10509 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10510 set_mu_type |= 0x01;
10511 set_mu_type &= ~0x04;
10512 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10513 set_mu_type &= ~0x01;
10514 set_mu_type |= 0x04;
10515 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10516 set_mu_type |= 0x05; // set bit 0, 2
10517 }
10518
10519 params.name = "hemu_onoff";
10520 sprintf(buf, "%u", set_mu_type);
10521 params.value = buf;
10522 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10523 wifi_hostapdWrite(config_file, &params, 1);
10524 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10525
10526 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10527 return RETURN_OK;
10528}
10529
10530INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10531{
10532 struct params params={0};
10533 char config_file[64] = {0};
10534 char buf[64] = {0};
10535 unsigned int get_mu_type = 0;
10536
10537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10538
10539 if (mu_type == NULL)
10540 return RETURN_ERR;
10541
10542 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10543 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10544 get_mu_type = strtol(buf, NULL, 10);
10545
10546 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10547 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10548 else if (get_mu_type & 0x04)
10549 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10550 else if (get_mu_type & 0x01)
10551 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10552 else
10553 *mu_type = WIFI_DL_MU_TYPE_NONE;
10554
10555 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10556 return RETURN_OK;
10557}
10558
10559INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10560{
10561 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10562 struct params params={0};
10563 char config_file[64] = {0};
10564 char buf[64] = {0};
10565 unsigned int set_mu_type = 0;
10566 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10567
10568 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10569 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10570
10571 if (strlen(buf) > 0)
10572 set_mu_type = strtol(buf, NULL, 10);
10573
10574 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10575 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10576 set_mu_type &= ~0x0a;
10577 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10578 set_mu_type |= 0x02;
10579 set_mu_type &= ~0x08;
10580 }
10581
10582 params.name = "hemu_onoff";
10583 sprintf(buf, "%u", set_mu_type);
10584 params.value = buf;
10585 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10586 wifi_hostapdWrite(config_file, &params, 1);
10587 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10588
10589 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10590 return RETURN_OK;
10591}
10592
10593INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10594{
10595 struct params params={0};
10596 char config_file[64] = {0};
10597 char buf[64] = {0};
10598 unsigned int get_mu_type = 0;
10599
10600 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10601
10602 if (mu_type == NULL)
10603 return RETURN_ERR;
10604
10605 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10606 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10607
10608 get_mu_type = strtol(buf, NULL, 10);
10609 if (get_mu_type & 0x02)
10610 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10611 else
10612 *mu_type = WIFI_DL_MU_TYPE_NONE;
10613
10614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10615 return RETURN_OK;
10616}
10617
10618
developer454b9462022-09-13 15:29:16 +080010619INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10620{
10621 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010622 char buf[256] = {0};
10623 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010624 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010625 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010626 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010627 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010628
10629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10630
developer254882b2022-09-30 17:12:31 +080010631 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010632 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10633 return RETURN_ERR;
10634 }
developer454b9462022-09-13 15:29:16 +080010635
developer254882b2022-09-30 17:12:31 +080010636 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010637 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010638
developer254882b2022-09-30 17:12:31 +080010639 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10640 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
10641 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
10642 _syscmd(cmd, buf, sizeof(buf));
10643 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10644 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10645 if (strstr(buf, "[SHORT-GI-") == NULL) {
10646 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
10647 _syscmd(cmd, buf, sizeof(buf));
10648 }
10649 if (band == band_5) {
10650 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10651 if (strstr(buf, "[SHORT-GI-") == NULL) {
10652 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
10653 _syscmd(cmd, buf, sizeof(buf));
10654 }
10655 }
10656 }
10657 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010658
developer254882b2022-09-30 17:12:31 +080010659 if (guard_interval == wifi_guard_interval_400)
10660 strcpy(GI, "0.4");
10661 else if (guard_interval == wifi_guard_interval_800)
10662 strcpy(GI, "0.8");
10663 else if (guard_interval == wifi_guard_interval_1600)
10664 strcpy(GI, "1.6");
10665 else if (guard_interval == wifi_guard_interval_3200)
10666 strcpy(GI, "3.2");
10667 else if (guard_interval == wifi_guard_interval_auto)
10668 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010669 // Record GI for get GI function
10670 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10671 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010672 if (f == NULL)
10673 return RETURN_ERR;
10674 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010675 fclose(f);
10676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10677 return RETURN_OK;
10678}
10679
10680INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10681{
10682 char buf[32] = {0};
10683 char cmd[64] = {0};
10684
10685 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10686
10687 if (guard_interval == NULL)
10688 return RETURN_ERR;
10689
10690 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10691 _syscmd(cmd, buf, sizeof(buf));
10692
10693 if (strncmp(buf, "0.4", 3) == 0)
10694 *guard_interval = wifi_guard_interval_400;
10695 else if (strncmp(buf, "0.8", 3) == 0)
10696 *guard_interval = wifi_guard_interval_800;
10697 else if (strncmp(buf, "1.6", 3) == 0)
10698 *guard_interval = wifi_guard_interval_1600;
10699 else if (strncmp(buf, "3.2", 3) == 0)
10700 *guard_interval = wifi_guard_interval_3200;
10701 else
10702 *guard_interval = wifi_guard_interval_auto;
10703
10704 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10705 return RETURN_OK;
10706}
10707
developer3cc61d12022-09-13 16:36:05 +080010708INT wifi_setBSSColor(INT radio_index, UCHAR color)
10709{
10710 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10711 struct params params = {0};
10712 char config_file[128] = {0};
10713 char bss_color[4] ={0};
10714
10715 params.name = "he_bss_color";
10716 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10717 params.value = bss_color;
10718 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10719 wifi_hostapdWrite(config_file, &params, 1);
10720 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10721
10722 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10723 return RETURN_OK;
10724}
10725
10726INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10727{
10728 char config_file[128] = {0};
10729 char buf[64] = {0};
10730 char temp_output[128] = {'\0'};
10731
10732 wifi_dbg_printf("\nFunc=%s\n", __func__);
10733 if (NULL == color)
10734 return RETURN_ERR;
10735
10736 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10737 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10738
10739 if(strlen(buf) > 0) {
10740 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10741 } else {
10742 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10743 }
10744
10745 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10746 wifi_dbg_printf("\noutput_string=%s\n", color);
10747
10748 return RETURN_OK;
10749}
10750
developer06a01d92022-09-07 16:32:39 +080010751/* multi-psk support */
10752INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10753{
10754 char cmd[256];
10755
10756 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10757 AP_PREFIX,
10758 apIndex,
10759 mac[0],
10760 mac[1],
10761 mac[2],
10762 mac[3],
10763 mac[4],
10764 mac[5]
10765 );
10766 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10767 _syscmd(cmd, key->wifi_keyId, 64);
10768
10769
10770 return RETURN_OK;
10771}
10772
10773INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10774{
10775 FILE *fd = NULL;
10776 char fname[100];
10777 char cmd[128] = {0};
10778 char out[64] = {0};
10779 wifi_key_multi_psk_t * key = NULL;
10780 if(keysNumber < 0)
10781 return RETURN_ERR;
10782
10783 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10784 fd = fopen(fname, "w");
10785 if (!fd) {
10786 return RETURN_ERR;
10787 }
10788 key= (wifi_key_multi_psk_t *) keys;
10789 for(int i=0; i<keysNumber; ++i, key++) {
10790 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10791 }
10792 fclose(fd);
10793
10794 //reload file
10795 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10796 _syscmd(cmd, out, 64);
10797 return RETURN_OK;
10798}
10799
10800INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10801{
10802 FILE *fd = NULL;
10803 char fname[100];
10804 char * line = NULL;
10805 char * pos = NULL;
10806 size_t len = 0;
10807 ssize_t read = 0;
10808 INT ret = RETURN_OK;
10809 wifi_key_multi_psk_t *keys_it = NULL;
10810
10811 if (keysNumber < 1) {
10812 return RETURN_ERR;
10813 }
10814
10815 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10816 fd = fopen(fname, "r");
10817 if (!fd) {
10818 return RETURN_ERR;
10819 }
10820
10821 if (keys == NULL) {
10822 ret = RETURN_ERR;
10823 goto close;
10824 }
10825
10826 keys_it = keys;
10827 while ((read = getline(&line, &len, fd)) != -1) {
10828 //Strip trailing new line if present
10829 if (read > 0 && line[read-1] == '\n') {
10830 line[read-1] = '\0';
10831 }
10832
10833 if(strcmp(line,"keyid=")) {
10834 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10835 if (!(pos = index(line, ' '))) {
10836 ret = RETURN_ERR;
10837 goto close;
10838 }
10839 pos++;
10840 //Here should be 00:00:00:00:00:00
10841 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10842 printf("Not supported MAC: %s\n", pos);
10843 }
10844 if (!(pos = index(pos, ' '))) {
10845 ret = RETURN_ERR;
10846 goto close;
10847 }
10848 pos++;
10849
10850 //The rest is PSK
10851 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10852 keys_it++;
10853
10854 if(--keysNumber <= 0)
10855 break;
10856 }
10857 }
10858
10859close:
10860 free(line);
10861 fclose(fd);
10862 return ret;
10863}
10864/* end of multi-psk support */
10865
10866INT wifi_setNeighborReports(UINT apIndex,
10867 UINT numNeighborReports,
10868 wifi_NeighborReport_t *neighborReports)
10869{
10870 char cmd[256] = { 0 };
10871 char hex_bssid[13] = { 0 };
10872 char bssid[18] = { 0 };
10873 char nr[256] = { 0 };
10874 char ssid[256];
10875 char hex_ssid[256];
10876 INT ret;
10877
10878 /*rmeove all neighbors*/
10879 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10880 sprintf(cmd, "hostapd_cli show_neighbor -i %s%d | awk '{print $1 \" \" $2}' | xargs -n2 -r hostapd_cli remove_neighbor -i %s%d",AP_PREFIX,apIndex,AP_PREFIX,apIndex);
10881 system(cmd);
10882
10883 for(unsigned int i = 0; i < numNeighborReports; i++)
10884 {
10885 memset(ssid, 0, sizeof(ssid));
10886 ret = wifi_getSSIDName(apIndex, ssid);
10887 if (ret != RETURN_OK)
10888 return RETURN_ERR;
10889
10890 memset(hex_ssid, 0, sizeof(hex_ssid));
10891 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10892 sprintf(hex_ssid + k,"%02x", ssid[j]);
10893
10894 snprintf(hex_bssid, sizeof(hex_bssid),
10895 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10896 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10897 snprintf(bssid, sizeof(bssid),
10898 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10899 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10900
10901 snprintf(nr, sizeof(nr),
10902 "%s" // bssid
10903 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10904 "%02hhx" // operclass
10905 "%02hhx" // channel
10906 "%02hhx", // phy_mode
10907 hex_bssid,
10908 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10909 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10910 neighborReports[i].opClass,
10911 neighborReports[i].channel,
10912 neighborReports[i].phyTable);
10913
10914 snprintf(cmd, sizeof(cmd),
10915 "hostapd_cli set_neighbor "
10916 "%s " // bssid
10917 "ssid=%s " // ssid
10918 "nr=%s " // nr
10919 "-i %s%d",
10920 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10921
10922 if (WEXITSTATUS(system(cmd)) != 0)
10923 {
10924 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10925 }
10926 }
10927
10928 return RETURN_OK;
10929}
10930
10931INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10932{
10933 return RETURN_OK;
10934}
10935
10936#ifdef _WIFI_HAL_TEST_
10937int main(int argc,char **argv)
10938{
10939 int index;
10940 INT ret=0;
10941 char buf[1024]="";
10942
10943 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10944 if(argc<3)
10945 {
10946 if(argc==2)
10947 {
10948 if(!strcmp(argv[1], "init"))
10949 return wifi_init();
10950 if(!strcmp(argv[1], "reset"))
10951 return wifi_reset();
10952 if(!strcmp(argv[1], "wifi_getHalVersion"))
10953 {
10954 char buffer[64];
10955 if(wifi_getHalVersion(buffer)==RETURN_OK)
10956 printf("Version: %s\n", buffer);
10957 else
10958 printf("Error in wifi_getHalVersion\n");
10959 return RETURN_OK;
10960 }
10961 }
10962 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10963 exit(-1);
10964 }
10965
10966 index = atoi(argv[2]);
10967 if(strstr(argv[1], "wifi_getApName")!=NULL)
10968 {
10969 wifi_getApName(index,buf);
10970 printf("Ap name is %s \n",buf);
10971 return 0;
10972 }
10973 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
10974 {
10975 BOOL b = FALSE;
10976 BOOL *output_bool = &b;
10977 wifi_getRadioAutoChannelEnable(index,output_bool);
10978 printf("Channel enabled = %d \n",b);
10979 return 0;
10980 }
10981 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
10982 {
10983 wifi_getApWpaEncryptionMode(index,buf);
10984 printf("encryption enabled = %s\n",buf);
10985 return 0;
10986 }
10987 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
10988 {
10989 BOOL b = FALSE;
10990 BOOL *output_bool = &b;
10991 wifi_getApSsidAdvertisementEnable(index,output_bool);
10992 printf("advertisment enabled = %d\n",b);
10993 return 0;
10994 }
10995 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
10996 {
10997 if(argc <= 3 )
10998 {
10999 printf("Insufficient arguments \n");
11000 exit(-1);
11001 }
11002
11003 char sta[20] = {'\0'};
11004 ULLONG handle= 0;
11005 strcpy(sta,argv[3]);
11006 mac_address_t st;
11007 mac_addr_aton(st,sta);
11008
11009 wifi_associated_dev_tid_stats_t tid_stats;
11010 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11011 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11012 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);
11013 }
11014
11015 if(strstr(argv[1], "getApEnable")!=NULL) {
11016 BOOL enable;
11017 ret=wifi_getApEnable(index, &enable);
11018 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11019 }
11020 else if(strstr(argv[1], "setApEnable")!=NULL) {
11021 BOOL enable = atoi(argv[3]);
11022 ret=wifi_setApEnable(index, enable);
11023 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11024 }
11025 else if(strstr(argv[1], "getApStatus")!=NULL) {
11026 char status[64];
11027 ret=wifi_getApStatus(index, status);
11028 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11029 }
11030 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11031 {
11032 wifi_getSSIDNameStatus(index,buf);
11033 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11034 return 0;
11035 }
11036 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11037 wifi_ssidTrafficStats2_t stats={0};
11038 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11039 printf("%s %d: returns %d\n", argv[1], index, ret);
11040 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11041 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11042 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11043 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11044 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11045 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11046 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11047 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11048 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11049 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11050 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11051 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11052 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11053 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11054 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11055 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11056 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11057 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11058 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11059 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11060 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11061 }
11062 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11063 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11064 UINT array_size=0;
11065 UINT i=0;
11066 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11067 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11068 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11069 printf(" neighbor %d:\n", i);
11070 printf(" ap_SSID =%s\n", pt->ap_SSID);
11071 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11072 printf(" ap_Mode =%s\n", pt->ap_Mode);
11073 printf(" ap_Channel =%d\n", pt->ap_Channel);
11074 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11075 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11076 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11077 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11078 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11079 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11080 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11081 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11082 printf(" ap_Noise =%d\n", pt->ap_Noise);
11083 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11084 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11085 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11086 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11087 }
11088 if(neighbor_ap_array)
11089 free(neighbor_ap_array); //make sure to free the list
11090 }
11091 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11092 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11093 UINT array_size=0;
11094 UINT i=0;
11095 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11096 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11097 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11098 printf(" associated_dev %d:\n", i);
11099 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11100 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11101 printf(" cli_SNR =%d\n", pt->cli_SNR);
11102 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11103 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11104 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11105 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11106 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11107 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11108 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11109 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11110 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11111 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11112 }
11113 if(associated_dev_array)
11114 free(associated_dev_array); //make sure to free the list
11115 }
11116
11117 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11118 {
11119#define MAX_ARRAY_SIZE 64
11120 int i, array_size;
11121 char *p, *ch_str;
11122 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11123
11124 if(argc != 5)
11125 {
11126 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11127 exit(-1);
11128 }
11129 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11130
11131 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11132 {
11133 strtok_r(ch_str, ",", &p);
11134 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11135 }
11136 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11137 if(!array_size)
11138 array_size=1;//Need to print current channel statistics
11139 for(i=0; i<array_size; i++)
11140 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11141 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11142 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11143 input_output_channelStats_array[i].ch_number,\
11144 input_output_channelStats_array[i].ch_noise,\
11145 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11146 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11147 input_output_channelStats_array[i].ch_utilization_busy,\
11148 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11149 input_output_channelStats_array[i].ch_utilization_total);
11150 }
11151
11152 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11153 {
11154 if(argc <= 3 )
11155 {
11156 printf("Insufficient arguments \n");
11157 exit(-1);
11158 }
11159 char mac_addr[20] = {'\0'};
11160 wifi_device_t output_struct;
11161 int dev_index = atoi(argv[3]);
11162
11163 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11164 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11165 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);
11166 }
11167
11168 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11169 {
11170 if (argc <= 3)
11171 {
11172 printf("Insufficient arguments\n");
11173 exit(-1);
11174 }
11175 char args[256];
11176 wifi_NeighborReport_t *neighborReports;
11177
11178 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11179 if (!neighborReports)
11180 {
11181 printf("Failed to allocate memory");
11182 exit(-1);
11183 }
11184
11185 for (int i = 3; i < argc; ++i)
11186 {
11187 char *val;
11188 int j = 0;
11189 memset(args, 0, sizeof(args));
11190 strncpy(args, argv[i], sizeof(args));
11191 val = strtok(args, ";");
11192 while (val != NULL)
11193 {
11194 if (j == 0)
11195 {
11196 mac_addr_aton(neighborReports[i - 3].bssid, val);
11197 } else if (j == 1)
11198 {
11199 neighborReports[i - 3].info = strtol(val, NULL, 16);
11200 } else if (j == 2)
11201 {
11202 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11203 } else if (j == 3)
11204 {
11205 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11206 } else if (j == 4)
11207 {
11208 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11209 } else {
11210 printf("Insufficient arguments]n\n");
11211 exit(-1);
11212 }
11213 val = strtok(NULL, ";");
11214 j++;
11215 }
11216 }
11217
11218 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11219 if (ret != RETURN_OK)
11220 {
11221 printf("wifi_setNeighborReports ret = %d", ret);
11222 exit(-1);
11223 }
11224 }
11225 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11226 {
11227 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11228 printf("%s.\n", buf);
11229 else
11230 printf("Error returned\n");
11231 }
11232 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11233 {
11234 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11235 printf("%s.\n", buf);
11236 else
11237 printf("Error returned\n");
11238 }
11239 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11240 {
11241 if (argc <= 2)
11242 {
11243 printf("Insufficient arguments\n");
11244 exit(-1);
11245 }
11246 char buf[64]= {'\0'};
11247 wifi_getRadioOperatingChannelBandwidth(index,buf);
11248 printf("Current bandwidth is %s \n",buf);
11249 return 0;
11250 }
11251 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11252 {
11253 if (argc <= 5)
11254 {
11255 printf("Insufficient arguments\n");
11256 exit(-1);
11257 }
11258 UINT channel = atoi(argv[3]);
11259 UINT width = atoi(argv[4]);
11260 UINT beacon = atoi(argv[5]);
11261 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11262 printf("Result = %d", ret);
11263 }
11264
11265 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11266 return 0;
11267}
11268
11269#endif
11270
11271#ifdef WIFI_HAL_VERSION_3
11272
developer1e5aa162022-09-13 16:06:24 +080011273INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11274{
11275 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11276 if (bitMap & WIFI_BITRATE_1MBPS)
11277 strcat(BasicRate, "1,");
11278 if (bitMap & WIFI_BITRATE_2MBPS)
11279 strcat(BasicRate, "2,");
11280 if (bitMap & WIFI_BITRATE_5_5MBPS)
11281 strcat(BasicRate, "5.5,");
11282 if (bitMap & WIFI_BITRATE_6MBPS)
11283 strcat(BasicRate, "6,");
11284 if (bitMap & WIFI_BITRATE_9MBPS)
11285 strcat(BasicRate, "9,");
11286 if (bitMap & WIFI_BITRATE_11MBPS)
11287 strcat(BasicRate, "11,");
11288 if (bitMap & WIFI_BITRATE_12MBPS)
11289 strcat(BasicRate, "12,");
11290 if (bitMap & WIFI_BITRATE_18MBPS)
11291 strcat(BasicRate, "18,");
11292 if (bitMap & WIFI_BITRATE_24MBPS)
11293 strcat(BasicRate, "24,");
11294 if (bitMap & WIFI_BITRATE_36MBPS)
11295 strcat(BasicRate, "36,");
11296 if (bitMap & WIFI_BITRATE_48MBPS)
11297 strcat(BasicRate, "48,");
11298 if (bitMap & WIFI_BITRATE_54MBPS)
11299 strcat(BasicRate, "54,");
11300 if (strlen(BasicRate) != 0) // remove last comma
11301 BasicRate[strlen(BasicRate) - 1] = '\0';
11302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11303 return RETURN_OK;
11304}
11305
11306INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11307{
11308 UINT BitMap = 0;
11309 char *rate;
11310
11311 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11312 rate = strtok(BasicRatesList, ",");
11313 while(rate != NULL)
11314 {
11315 if (strcmp(rate, "1") == 0)
11316 BitMap |= WIFI_BITRATE_1MBPS;
11317 else if (strcmp(rate, "2") == 0)
11318 BitMap |= WIFI_BITRATE_2MBPS;
11319 else if (strcmp(rate, "5.5") == 0)
11320 BitMap |= WIFI_BITRATE_5_5MBPS;
11321 else if (strcmp(rate, "6") == 0)
11322 BitMap |= WIFI_BITRATE_6MBPS;
11323 else if (strcmp(rate, "9") == 0)
11324 BitMap |= WIFI_BITRATE_9MBPS;
11325 else if (strcmp(rate, "11") == 0)
11326 BitMap |= WIFI_BITRATE_11MBPS;
11327 else if (strcmp(rate, "12") == 0)
11328 BitMap |= WIFI_BITRATE_12MBPS;
11329 else if (strcmp(rate, "18") == 0)
11330 BitMap |= WIFI_BITRATE_18MBPS;
11331 else if (strcmp(rate, "24") == 0)
11332 BitMap |= WIFI_BITRATE_24MBPS;
11333 else if (strcmp(rate, "36") == 0)
11334 BitMap |= WIFI_BITRATE_36MBPS;
11335 else if (strcmp(rate, "48") == 0)
11336 BitMap |= WIFI_BITRATE_48MBPS;
11337 else if (strcmp(rate, "54") == 0)
11338 BitMap |= WIFI_BITRATE_54MBPS;
11339 rate = strtok(NULL, ",");
11340 }
11341 *basicRateBitMap = BitMap;
11342 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11343 return RETURN_OK;
11344}
11345
11346// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
developer06a01d92022-09-07 16:32:39 +080011347INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11348{
developer1e5aa162022-09-13 16:06:24 +080011349 char buf[128] = {0};
11350 char cmd[128] = {0};
11351 char config_file[64] = {0};
11352 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011353 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011354 wifi_radio_operationParam_t current_param;
11355
11356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11357
11358 multiple_set = TRUE;
11359 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11360 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11361 return RETURN_ERR;
11362 }
11363 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11364 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11365 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11366 return RETURN_ERR;
11367 }
11368 }
11369 if (current_param.channelWidth != operationParam->channelWidth || (current_param.channel != operationParam->channel && !operationParam->autoChannelEnabled)) {
11370 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11371 bandwidth = 20;
11372 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11373 bandwidth = 40;
11374 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11375 bandwidth = 80;
11376 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11377 bandwidth = 160;
11378 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11379 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11380 return RETURN_ERR;
11381 }
11382 }
11383 if (current_param.variant != operationParam->variant) {
11384 // Two different definition bit map, so need to check every bit.
11385 if (operationParam->variant & WIFI_80211_VARIANT_A)
11386 set_mode |= WIFI_MODE_A;
11387 if (operationParam->variant & WIFI_80211_VARIANT_B)
11388 set_mode |= WIFI_MODE_B;
11389 if (operationParam->variant & WIFI_80211_VARIANT_G)
11390 set_mode |= WIFI_MODE_G;
11391 if (operationParam->variant & WIFI_80211_VARIANT_N)
11392 set_mode |= WIFI_MODE_N;
11393 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11394 set_mode |= WIFI_MODE_AC;
11395 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11396 set_mode |= WIFI_MODE_AX;
11397 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11398 memset(buf, 0, sizeof(buf));
11399 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11400 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11401 return RETURN_ERR;
11402 }
11403 }
11404 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11405 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11406 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11407 return RETURN_ERR;
11408 }
11409 }
11410 if (current_param.beaconInterval != operationParam->beaconInterval) {
11411 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11412 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11413 return RETURN_ERR;
11414 }
11415 }
11416 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11417 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11418 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11419 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11420 return RETURN_ERR;
11421 }
11422 }
11423 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11424 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11425 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11426 return RETURN_ERR;
11427 }
11428 }
11429 if (current_param.guardInterval != operationParam->guardInterval) {
11430 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11431 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11432 return RETURN_ERR;
11433 }
11434 }
11435 if (current_param.transmitPower != operationParam->transmitPower) {
11436 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11437 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11438 return RETURN_ERR;
11439 }
11440 }
11441 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11442 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11443 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11444 return RETURN_ERR;
11445 }
11446 }
11447 if (current_param.obssCoex != operationParam->obssCoex) {
11448 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11449 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11450 return RETURN_ERR;
11451 }
11452 }
11453 if (current_param.stbcEnable != operationParam->stbcEnable) {
11454 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11455 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11456 return RETURN_ERR;
11457 }
11458 }
11459 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11460 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11461 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11462 return RETURN_ERR;
11463 }
11464 }
11465
11466 // if enable is true, then restart the radio
11467 wifi_setRadioEnable(index, FALSE);
11468 if (operationParam->enable == TRUE)
11469 wifi_setRadioEnable(index, TRUE);
11470 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11471
developer06a01d92022-09-07 16:32:39 +080011472 return RETURN_OK;
11473}
11474
11475INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11476{
developer1e5aa162022-09-13 16:06:24 +080011477 char band[64] = {0};
11478 char buf[256] = {0};
11479 char config_file[64] = {0};
11480 char cmd[128] = {0};
11481 int ret = RETURN_ERR;
11482 int mode = 0;
11483 ULONG channel = 0;
11484 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011485
11486 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11487 printf("Entering %s index = %d\n", __func__, (int)index);
11488
developer1e5aa162022-09-13 16:06:24 +080011489 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11490 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11491 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011492 {
developer1e5aa162022-09-13 16:06:24 +080011493 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011494 return RETURN_ERR;
11495 }
11496 operationParam->enable = enabled;
11497
11498 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011499 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011500 {
developer1e5aa162022-09-13 16:06:24 +080011501 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011502 return RETURN_ERR;
11503 }
11504
11505 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011506 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011507 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011508 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011509 else if (!strcmp(band, "6GHz"))
11510 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011511 else
11512 {
developer1e5aa162022-09-13 16:06:24 +080011513 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011514 band);
11515 }
11516
developer1e5aa162022-09-13 16:06:24 +080011517 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11518 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11519 operationParam->channel = 0;
11520 operationParam->autoChannelEnabled = TRUE;
11521 } else {
11522 operationParam->channel = strtol(buf, NULL, 10);
11523 operationParam->autoChannelEnabled = FALSE;
11524 }
11525
developer06a01d92022-09-07 16:32:39 +080011526 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011527 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11528 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11529 return RETURN_ERR;
11530 }
developer06a01d92022-09-07 16:32:39 +080011531 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11532 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11533 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer1e5aa162022-09-13 16:06:24 +080011534 else if (!strcmp(buf, "160")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11535 else if (!strcmp(buf, "80+80")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011536 else
11537 {
developer1e5aa162022-09-13 16:06:24 +080011538 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11539 return false;
developer06a01d92022-09-07 16:32:39 +080011540 }
11541
developer1e5aa162022-09-13 16:06:24 +080011542 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11543 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11544 return RETURN_ERR;
11545 }
11546 // Two different definition bit map, so need to check every bit.
11547 if (mode & WIFI_MODE_A)
11548 operationParam->variant |= WIFI_80211_VARIANT_A;
11549 if (mode & WIFI_MODE_B)
11550 operationParam->variant |= WIFI_80211_VARIANT_B;
11551 if (mode & WIFI_MODE_G)
11552 operationParam->variant |= WIFI_80211_VARIANT_G;
11553 if (mode & WIFI_MODE_N)
11554 operationParam->variant |= WIFI_80211_VARIANT_N;
11555 if (mode & WIFI_MODE_AC)
11556 operationParam->variant |= WIFI_80211_VARIANT_AC;
11557 if (mode & WIFI_MODE_AX)
11558 operationParam->variant |= WIFI_80211_VARIANT_AX;
11559 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11560 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11561 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011562 }
developer1e5aa162022-09-13 16:06:24 +080011563 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11564 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11565 return RETURN_ERR;
11566 }
11567 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11568 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11569 return RETURN_ERR;
11570 }
developer06a01d92022-09-07 16:32:39 +080011571
developer1e5aa162022-09-13 16:06:24 +080011572 memset(buf, 0, sizeof(buf));
11573 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11574 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11575 return RETURN_ERR;
11576 }
11577 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11578
11579 memset(buf, 0, sizeof(buf));
11580 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11581 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11582 return RETURN_ERR;
11583 }
11584 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11585
11586 memset(buf, 0, sizeof(buf));
11587 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11588 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11589
11590 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11591 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11592 return RETURN_ERR;
11593 }
11594 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11595 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11596 return RETURN_ERR;
11597 }
11598
11599 memset(buf, 0, sizeof(buf));
11600 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11601 if (strcmp(buf, "-1") == 0) {
11602 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11603 operationParam->ctsProtection = FALSE;
11604 } else {
11605 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11606 operationParam->ctsProtection = TRUE;
11607 }
11608
11609 memset(buf, 0, sizeof(buf));
11610 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11611 if (strcmp(buf, "0") == 0)
11612 operationParam->obssCoex = FALSE;
11613 else
11614 operationParam->obssCoex = TRUE;
11615
11616 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11617 _syscmd(cmd, buf, sizeof(buf));
11618 if (strlen(buf) != 0)
11619 operationParam->stbcEnable = TRUE;
11620 else
11621 operationParam->stbcEnable = FALSE;
11622
11623 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11624 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11625 return RETURN_ERR;
11626 }
11627
11628 // Below value is hardcoded
11629
11630 operationParam->numSecondaryChannels = 0;
11631 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11632 operationParam->channelSecondary[i] = 0;
11633 }
11634 operationParam->csa_beacon_count = 15;
11635 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011636
11637 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11638 return RETURN_OK;
11639}
11640
11641static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11642{
developerc086fb72022-10-04 10:18:22 +080011643 int max_radio_num = 0;
11644
11645 wifi_getMaxRadioNumber(&max_radio_num);
11646 if (radioIndex >= max_radio_num || radioIndex < 0) {
11647 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11648 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011649 }
11650
developerc086fb72022-10-04 10:18:22 +080011651 return (arrayIndex * max_radio_num) + radioIndex;
11652}
developer06a01d92022-09-07 16:32:39 +080011653
developerc086fb72022-10-04 10:18:22 +080011654wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11655 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11656 return WIFI_BITRATE_1MBPS;
11657 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11658 return WIFI_BITRATE_2MBPS;
11659 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11660 return WIFI_BITRATE_5_5MBPS;
11661 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11662 return WIFI_BITRATE_6MBPS;
11663 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11664 return WIFI_BITRATE_9MBPS;
11665 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11666 return WIFI_BITRATE_11MBPS;
11667 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11668 return WIFI_BITRATE_12MBPS;
11669 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11670 return WIFI_BITRATE_18MBPS;
11671 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11672 return WIFI_BITRATE_24MBPS;
11673 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11674 return WIFI_BITRATE_36MBPS;
11675 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11676 return WIFI_BITRATE_48MBPS;
11677 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11678 return WIFI_BITRATE_54MBPS;
11679 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011680}
11681
11682INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11683{
developerc086fb72022-10-04 10:18:22 +080011684 INT mode = 0;
11685 INT ret = -1;
11686 INT output = 0;
11687 int i = 0;
11688 int vap_index = 0;
11689 BOOL enabled = FALSE;
11690 char buf[256] = {0};
11691 wifi_vap_security_t security;
11692 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080011693
11694 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11695 printf("Entering %s index = %d\n", __func__, (int)index);
11696
developer06a01d92022-09-07 16:32:39 +080011697 for (i = 0; i < 5; i++)
11698 {
developerc086fb72022-10-04 10:18:22 +080011699 map->vap_array[i].radio_index = index;
11700
developer06a01d92022-09-07 16:32:39 +080011701 vap_index = array_index_to_vap_index(index, i);
11702 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080011703 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011704
developerc086fb72022-10-04 10:18:22 +080011705 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080011706
11707 map->vap_array[i].vap_index = vap_index;
11708
11709 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011710 ret = wifi_getApName(vap_index, buf);
11711 if (ret != RETURN_OK) {
11712 printf("%s: wifi_getApName return error\n", __func__);
11713 return RETURN_ERR;
11714 }
11715 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
11716
11717 memset(buf, 0, sizeof(buf));
11718 ret = wifi_getSSIDNameStatus(vap_index, buf);
11719 if (ret != RETURN_OK) {
11720 printf("%s: wifi_getSSIDNameStatus return error\n", __func__);
11721 return RETURN_ERR;
11722 }
11723 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
developer06a01d92022-09-07 16:32:39 +080011724
11725 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080011726 if (ret != RETURN_OK) {
11727 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011728 return RETURN_ERR;
11729 }
11730 map->vap_array[i].u.bss_info.enabled = enabled;
11731
developerc086fb72022-10-04 10:18:22 +080011732 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
11733 if (ret != RETURN_OK) {
11734 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
11735 return RETURN_ERR;
11736 }
developer06a01d92022-09-07 16:32:39 +080011737 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080011738
11739 ret = wifi_getApIsolationEnable(vap_index, &enabled);
11740 if (ret != RETURN_OK) {
11741 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
11742 return RETURN_ERR;
11743 }
11744 map->vap_array[i].u.bss_info.isolation = enabled;
11745
11746 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
11747 if (ret != RETURN_OK) {
11748 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
11749 return RETURN_ERR;
11750 }
11751 map->vap_array[i].u.bss_info.bssMaxSta = output;
11752
11753 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
11754 if (ret != RETURN_OK) {
11755 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
11756 return RETURN_ERR;
11757 }
11758 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011759
developerc086fb72022-10-04 10:18:22 +080011760 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
11761 if (ret != RETURN_OK) {
11762 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
11763 return RETURN_ERR;
11764 }
11765 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080011766
developerc086fb72022-10-04 10:18:22 +080011767 ret = wifi_getApSecurity(vap_index, &security);
11768 if (ret != RETURN_OK) {
11769 printf("%s: wifi_getApSecurity return error\n", __func__);
11770 return RETURN_ERR;
11771 }
11772 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080011773
developerc086fb72022-10-04 10:18:22 +080011774 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
11775 if (ret != RETURN_OK) {
11776 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
11777 return RETURN_ERR;
11778 }
11779 if (mode == 0)
11780 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
11781 else
11782 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
11783 if (mode == 1)
11784 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11785 else if (mode == 2)
11786 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080011787
developerc086fb72022-10-04 10:18:22 +080011788 ret = wifi_getApWmmEnable(vap_index, &enabled);
11789 if (ret != RETURN_OK) {
11790 printf("%s: wifi_getApWmmEnable return error\n", __func__);
11791 return RETURN_ERR;
11792 }
11793 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080011794
developerc086fb72022-10-04 10:18:22 +080011795 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
11796 if (ret != RETURN_OK) {
11797 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011798 return RETURN_ERR;
11799 }
developerc086fb72022-10-04 10:18:22 +080011800 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080011801
11802 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080011803 ret = wifi_getApBeaconRate(vap_index, buf);
11804 if (ret != RETURN_OK) {
11805 printf("%s: wifi_getApBeaconRate return error\n", __func__);
11806 return RETURN_ERR;
11807 }
11808 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080011809
developerc086fb72022-10-04 10:18:22 +080011810 memset(buf, 0, sizeof(buf));
11811 ret = wifi_getBaseBSSID(vap_index, buf);
11812 if (ret != RETURN_OK) {
11813 printf("%s: wifi_getBaseBSSID return error\n", __func__);
11814 return RETURN_ERR;
11815 }
11816 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11817 &map->vap_array[i].u.bss_info.bssid[0],
11818 &map->vap_array[i].u.bss_info.bssid[1],
11819 &map->vap_array[i].u.bss_info.bssid[2],
11820 &map->vap_array[i].u.bss_info.bssid[3],
11821 &map->vap_array[i].u.bss_info.bssid[4],
11822 &map->vap_array[i].u.bss_info.bssid[5]);
developer06a01d92022-09-07 16:32:39 +080011823
developerc086fb72022-10-04 10:18:22 +080011824 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080011825 }
11826 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11827 return RETURN_OK;
11828}
11829
11830INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11831{
11832 unsigned int i;
11833 wifi_vap_info_t *vap_info = NULL;
11834 int acl_mode;
11835 char *sec_str = NULL;
11836
11837 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11838 printf("Entering %s index = %d\n", __func__, (int)index);
11839 for (i = 0; i < map->num_vaps; i++)
11840 {
11841 vap_info = &map->vap_array[i];
11842 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11843
11844 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11845 else
11846 {
11847 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11848 else acl_mode = 1;
11849 }
11850 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11851 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11852 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11853
11854 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11855 if (sec_str)
11856 {
11857 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11858 }
11859 else
11860 {
11861 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11862 }
11863
11864 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11865 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11866
11867 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11868 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11869
11870 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11871
11872 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11873 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11874 }
11875 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11876 return RETURN_OK;
11877}
11878
11879int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11880{
11881 char *token, *next;
11882 const char s[2] = ",";
11883 int count =0;
11884
11885 /* get the first token */
11886 token = strtok_r(pchannels, s, &next);
11887
11888 /* walk through other tokens */
11889 while( token != NULL && count < MAX_CHANNELS) {
11890 chlistptr->channels_list[count++] = atoi(token);
11891 token = strtok_r(NULL, s, &next);
11892 }
11893
11894 return count;
11895}
11896
11897static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11898{
11899 INT status;
11900 wifi_channels_list_t *chlistp;
11901 CHAR output_string[64];
11902 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011903 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011904
11905 if(rcap == NULL)
11906 {
11907 return RETURN_ERR;
11908 }
11909
11910 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011911 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011912
developer1e5aa162022-09-13 16:06:24 +080011913 if (band == band_2_4)
11914 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11915 else if (band == band_5)
11916 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11917 else if (band == band_6)
11918 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011919
11920 chlistp = &(rcap->channel_list[0]);
11921 memset(pchannels, 0, sizeof(pchannels));
11922
11923 /* possible number of radio channels */
11924 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11925 {
11926 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11927 }
11928 /* Number of channels and list*/
11929 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11930
11931 /* autoChannelSupported */
11932 /* always ON with wifi_getRadioAutoChannelSupported */
11933 rcap->autoChannelSupported = TRUE;
11934
11935 /* DCSSupported */
11936 /* always ON with wifi_getRadioDCSSupported */
11937 rcap->DCSSupported = TRUE;
11938
11939 /* zeroDFSSupported - TBD */
11940 rcap->zeroDFSSupported = FALSE;
11941
11942 /* Supported Country List*/
11943 memset(output_string, 0, sizeof(output_string));
11944 status = wifi_getRadioCountryCode(radioIndex, output_string);
11945 if( status != 0 ) {
11946 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11947 return RETURN_ERR;
11948 } else {
11949 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11950 }
11951 if(!strcmp(output_string,"US")){
11952 rcap->countrySupported[0] = wifi_countrycode_US;
11953 rcap->countrySupported[1] = wifi_countrycode_CA;
11954 } else if (!strcmp(output_string,"CA")) {
11955 rcap->countrySupported[0] = wifi_countrycode_CA;
11956 rcap->countrySupported[1] = wifi_countrycode_US;
11957 } else {
11958 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
11959 }
11960
11961 rcap->numcountrySupported = 2;
11962
11963 /* csi */
11964 rcap->csi.maxDevices = 8;
11965 rcap->csi.soudingFrameSupported = TRUE;
11966
11967 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
11968
11969 /* channelWidth - all supported bandwidths */
11970 int i=0;
11971 rcap->channelWidth[i] = 0;
11972 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11973 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11974 WIFI_CHANNELBANDWIDTH_40MHZ);
11975
11976 }
developer1e5aa162022-09-13 16:06:24 +080011977 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080011978 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11979 WIFI_CHANNELBANDWIDTH_40MHZ |
11980 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
11981 }
11982
11983
11984 /* mode - all supported variants */
11985 // rcap->mode[i] = WIFI_80211_VARIANT_H;
11986 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011987 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080011988 }
11989 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011990 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
11991 }
11992 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
11993 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080011994 }
11995 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
11996 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
11997
11998 /* supportedBitRate - all supported bitrates */
11999 rcap->supportedBitRate[i] = 0;
12000 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12001 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12002 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12003 }
developer1e5aa162022-09-13 16:06:24 +080012004 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012005 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12006 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12007 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12008 }
12009
12010
12011 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12012 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12013 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12014 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12015 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12016 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12017 rcap->cipherSupported = 0;
12018 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12019 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12020
12021 return RETURN_OK;
12022}
12023
12024INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12025{
12026 INT status, radioIndex;
12027 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
12028 int iter = 0;
12029 unsigned int j;
12030 wifi_interface_name_idex_map_t *iface_info;
12031
12032 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12033
12034 memset(cap, 0, sizeof(wifi_hal_capability_t));
12035
12036 /* version */
12037 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12038 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12039
12040 /* number of radios platform property */
12041 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12042 _syscmd(cmd, output, sizeof(output));
12043 cap->wifi_prop.numRadios = atoi(output);
12044
12045 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12046 {
12047 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12048 if (status != 0) {
12049 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12050 return RETURN_ERR;
12051 }
12052
12053 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12054 {
12055 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
12056 {
12057 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12058 return RETURN_ERR;
12059 }
12060 iface_info = &cap->wifi_prop.interface_map[iter];
12061 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12062 iface_info->rdk_radio_index = radioIndex;
12063 memset(output, 0, sizeof(output));
12064 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12065 {
12066 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12067 }
12068 // TODO: bridge name
12069 // TODO: vlan id
12070 // TODO: primary
12071 iface_info->index = array_index_to_vap_index(radioIndex, j);
12072 memset(output, 0, sizeof(output));
12073 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
12074 {
12075 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12076 }
12077 iter++;
12078 }
12079 }
12080
12081 cap->BandSteeringSupported = FALSE;
12082 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12083 return RETURN_OK;
12084}
12085
12086INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12087{
developer587c1b62022-09-27 15:58:59 +080012088 char buf[128] = {0};
12089 char config_file[128] = {0};
12090 char password[64] = {0};
12091 char mfp[32] = {0};
12092 char wpa_mode[32] = {0};
12093 struct params params = {0};
12094
12095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12096
12097 multiple_set = TRUE;
12098 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12099 if (security->mode == wifi_security_mode_none) {
12100 strcpy(wpa_mode, "None");
12101 } else if (security->mode == wifi_security_mode_wpa_personal)
12102 strcpy(wpa_mode, "WPA-Personal");
12103 else if (security->mode == wifi_security_mode_wpa2_personal)
12104 strcpy(wpa_mode, "WPA2-Personal");
12105 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12106 strcpy(wpa_mode, "WPA-WPA2-Personal");
12107 else if (security->mode == wifi_security_mode_wpa_enterprise)
12108 strcpy(wpa_mode, "WPA-Enterprise");
12109 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12110 strcpy(wpa_mode, "WPA2-Enterprise");
12111 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12112 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
12113 else if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
12114 strcpy(wpa_mode, "WPA3-Personal");
12115 else if (security->mode == wifi_security_mode_wpa3_enterprise)
12116 strcpy(wpa_mode, "WPA3-Enterprise");
12117
12118 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
12119
12120 strncpy(password, security->u.key.key, 63);
12121 password[63] = '\0';
12122 wifi_setApSecurityKeyPassphrase(ap_index, password);
12123
12124 if (security->mode != wifi_security_mode_none) {
12125 memset(&params, 0, sizeof(params));
12126 params.name = "wpa_pairwise";
12127 if (security->encr == wifi_encryption_tkip)
12128 params.value = "TKIP";
12129 else if (security->encr == wifi_encryption_aes)
12130 params.value = "CCMP";
12131 else if (security->encr == wifi_encryption_aes_tkip)
12132 params.value = "TKIP CCMP";
12133 wifi_hostapdWrite(config_file, &params, 1);
12134 }
12135
12136 if (security->mfp == wifi_mfp_cfg_disabled)
12137 strcpy(mfp, "Disable");
12138 else if (security->mfp == wifi_mfp_cfg_optional)
12139 strcpy(mfp, "Optional");
12140 else if (security->mfp == wifi_mfp_cfg_required)
12141 strcpy(mfp, "Required");
12142 wifi_setApSecurityMFPConfig(ap_index, mfp);
12143
12144 memset(&params, 0, sizeof(params));
12145 params.name = "transition_disable";
12146 if (security->wpa3_transition_disable == TRUE)
12147 params.value = "0x01";
12148 else
12149 params.value = "0x00";
12150 wifi_hostapdWrite(config_file, &params, 1);
12151
12152 memset(&params, 0, sizeof(params));
12153 params.name = "wpa_group_rekey";
12154 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12155 params.value = buf;
12156 wifi_hostapdWrite(config_file, &params, 1);
12157
12158 memset(&params, 0, sizeof(params));
12159 params.name = "wpa_strict_rekey";
12160 params.value = security->strict_rekey?"1":"0";
12161 wifi_hostapdWrite(config_file, &params, 1);
12162
12163 memset(&params, 0, sizeof(params));
12164 params.name = "wpa_pairwise_update_count";
12165 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12166 params.value = buf;
12167 wifi_hostapdWrite(config_file, &params, 1);
12168
12169 memset(&params, 0, sizeof(params));
12170 params.name = "disable_pmksa_caching";
12171 params.value = security->disable_pmksa_caching?"1":"0";
12172 wifi_hostapdWrite(config_file, &params, 1);
12173
12174 wifi_setApEnable(ap_index, FALSE);
12175 wifi_setApEnable(ap_index, TRUE);
12176
12177 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12178
developer06a01d92022-09-07 16:32:39 +080012179 return RETURN_OK;
12180}
12181
12182INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12183{
developer587c1b62022-09-27 15:58:59 +080012184 char buf[128] = {0};
12185 char config_file[128] = {0};
12186 int disable = 0;
12187 // struct params params = {0};
12188
12189 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12190 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12191 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12192 security->mode = wifi_security_mode_none;
12193 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012194 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012195 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012196 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012197 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012198 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012199 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012200 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012201 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012202 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012203 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012204 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012205 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012206 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012207 security->mode = wifi_security_mode_wpa3_personal;
developer517a9792022-10-05 19:37:42 +080012208 else if (!strcmp(buf, "WPA3-Transition"))
developer587c1b62022-09-27 15:58:59 +080012209 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012210 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012211 security->mode = wifi_security_mode_wpa3_enterprise;
12212 }
12213
12214 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12215 if (security->mode == wifi_security_mode_none)
12216 security->encr = wifi_encryption_none;
12217 else {
12218 if (strcmp(buf, "TKIP") == 0)
12219 security->encr = wifi_encryption_tkip;
12220 else if (strcmp(buf, "CCMP") == 0)
12221 security->encr = wifi_encryption_aes;
12222 else
12223 security->encr = wifi_encryption_aes_tkip;
12224 }
12225
12226 memset(buf, 0, sizeof(buf));
12227 wifi_getApSecurityMFPConfig(ap_index, buf);
12228 if (strcmp(buf, "Disabled") == 0)
12229 security->mfp = wifi_mfp_cfg_disabled;
12230 else if (strcmp(buf, "Optional") == 0)
12231 security->mfp = wifi_mfp_cfg_optional;
12232 else if (strcmp(buf, "Required") == 0)
12233 security->mfp = wifi_mfp_cfg_required;
12234
12235 memset(buf, 0, sizeof(buf));
12236 security->wpa3_transition_disable = FALSE;
12237 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12238 disable = strtol(buf, NULL, 16);
12239 if (disable != 0)
12240 security->wpa3_transition_disable = TRUE;
12241
12242 memset(buf, 0, sizeof(buf));
12243 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12244 if (strlen(buf) == 0)
12245 security->rekey_interval = 86400;
12246 else
12247 security->rekey_interval = strtol(buf, NULL, 10);
12248
12249 memset(buf, 0, sizeof(buf));
12250 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12251 if (strlen(buf) == 0)
12252 security->strict_rekey = 1;
12253 else
12254 security->strict_rekey = strtol(buf, NULL, 10);
12255
12256 memset(buf, 0, sizeof(buf));
12257 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12258 if (strlen(buf) == 0)
12259 security->eapol_key_retries = 4;
12260 else
12261 security->eapol_key_retries = strtol(buf, NULL, 10);
12262
12263 memset(buf, 0, sizeof(buf));
12264 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12265 if (strlen(buf) == 0)
12266 security->disable_pmksa_caching = FALSE;
12267 else
12268 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12269
12270 /* TODO
12271 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12272 */
12273 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12274 security->eap_identity_req_timeout = 0;
12275 security->eap_identity_req_retries = 0;
12276 security->eap_req_timeout = 0;
12277 security->eap_req_retries = 0;
12278 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012279 return RETURN_OK;
12280}
12281
12282#endif /* WIFI_HAL_VERSION_3 */
12283
12284#ifdef WIFI_HAL_VERSION_3_PHASE2
12285INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12286{
developer13df9332022-09-27 16:53:22 +080012287 char cmd[128] = {0};
12288 char buf[128] = {0};
12289 char *mac_addr = NULL;
12290 BOOL status = FALSE;
12291 size_t len = 0;
12292
12293 if(ap_index > MAX_APS)
12294 return RETURN_ERR;
12295
12296 *output_numDevices = 0;
12297 wifi_getApEnable(ap_index, &status);
12298 if (status == FALSE)
12299 return RETURN_OK;
12300
12301 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12302 _syscmd(cmd, buf, sizeof(buf));
12303
12304 mac_addr = strtok(buf, "\n");
12305 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12306 *output_numDevices = i + 1;
12307 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12308 addr_ptr = output_deviceMacAddressArray[i];
12309 mac_addr_aton(addr_ptr, mac_addr);
12310 mac_addr = strtok(NULL, "\n");
12311 }
12312
12313 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012314}
12315#else
12316INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12317{
12318 char cmd[128];
12319 BOOL status = false;
12320
12321 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12322 return RETURN_ERR;
12323
12324 output_buf[0] = '\0';
12325
12326 wifi_getApEnable(ap_index,&status);
12327 if (!status)
12328 return RETURN_OK;
12329
12330 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12331 _syscmd(cmd, output_buf, output_buf_size);
12332
12333 return RETURN_OK;
12334}
12335#endif
developer2f513ab2022-09-13 14:26:06 +080012336
12337INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12338{
12339 char output[16]={'\0'};
12340 char config_file[MAX_BUF_SIZE] = {0};
12341
12342 if (!enable)
12343 return RETURN_ERR;
12344
12345 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12346 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12347
12348 if (strlen(output) == 0)
12349 *enable = FALSE;
12350 else if (strncmp(output, "1", 1) == 0)
12351 *enable = TRUE;
12352 else
12353 *enable = FALSE;
12354
12355 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12356 return RETURN_OK;
12357}
developer2d9c30f2022-09-13 15:06:14 +080012358
12359INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12360{
12361 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
12362 return RETURN_ERR;
12363 *output_enable=TRUE;
12364 return RETURN_OK;
12365}
developerfd7d2892022-09-13 16:44:53 +080012366
12367INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12368{
12369 char cmd[128] = {0};
12370 char buf[128] = {0};
12371 char line[128] = {0};
12372 size_t len = 0;
12373 ssize_t read = 0;
12374 FILE *f = NULL;
12375 int index = 0;
12376 int exp = 0;
12377 int mantissa = 0;
12378 int duration = 0;
12379 int radio_index = 0;
12380 int max_radio_num = 0;
12381 uint twt_wake_interval = 0;
12382
12383 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12384
12385 wifi_getMaxRadioNumber(&max_radio_num);
12386 radio_index = ap_index % max_radio_num;
12387 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12388 _syscmd(cmd, buf, sizeof(buf));
12389 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12390 if (*numSessionReturned > maxNumberSessions)
12391 *numSessionReturned = maxNumberSessions;
12392 else if (*numSessionReturned < 1) {
12393 *numSessionReturned = 0;
12394 return RETURN_OK;
12395 }
12396
12397 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12398 if ((f = popen(cmd, "r")) == NULL) {
12399 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12400 return RETURN_ERR;
12401 }
12402
12403 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12404 while((read = fgets(line, sizeof(line), f)) != NULL) {
12405 char *tmp = NULL;
12406 strcpy(buf, line);
12407 tmp = strtok(buf, " ");
12408 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12409 tmp = strtok(NULL, " ");
12410 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12411 tmp = strtok(NULL, " ");
12412 if (strstr(tmp, "t")) {
12413 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12414 }
12415 if (strstr(tmp, "a")) {
12416 twtSessions[index].twtParameters.operation.announced = TRUE;
12417 }
12418 tmp = strtok(NULL, " ");
12419 exp = strtol(tmp, NULL, 10);
12420 tmp = strtok(NULL, " ");
12421 mantissa = strtol(tmp, NULL, 10);
12422 tmp = strtok(NULL, " ");
12423 duration = strtol(tmp, NULL, 10);
12424
12425 // only implicit supported
12426 twtSessions[index].twtParameters.operation.implicit = TRUE;
12427 // only individual agreement supported
12428 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12429
12430 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12431 twt_wake_interval = mantissa * (1 << exp);
12432 if (twt_wake_interval/mantissa != (1 << exp)) {
12433 // Overflow handling
12434 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12435 } else {
12436 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12437 }
12438 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12439 index++;
12440 }
12441
12442 pclose(f);
12443 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12444 return RETURN_OK;
12445}