blob: 06d2c40f27fa295970bbdb38cfacdffdc932d54f [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"
developer454b9462022-09-13 15:29:16 +080084
developer06a01d92022-09-07 16:32:39 +080085#define DRIVER_2GHZ "ath9k"
86#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080087#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080088
89/*
90 MAX_APS - Number of all AP available in system
91 2x Home AP
92 2x Backhaul AP
93 2x Guest AP
94 2x Secure Onboard AP
95 2x Service AP
96
97*/
98#define MAX_APS 10
99#define NUMBER_OF_RADIOS 2
100
101#ifndef AP_PREFIX
102#define AP_PREFIX "wifi"
103#endif
104
105#ifndef RADIO_PREFIX
106#define RADIO_PREFIX "wlan"
107#endif
108
109#define MAX_BUF_SIZE 128
110#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800111#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800112
113//Uncomment to enable debug logs
114//#define WIFI_DEBUG
115
116#ifdef WIFI_DEBUG
117#define wifi_dbg_printf printf
118#define WIFI_ENTRY_EXIT_DEBUG printf
119#else
120#define wifi_dbg_printf(format, args...) printf("")
121#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
122#endif
123
124#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
125#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
126#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
127#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
128#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
129#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
130#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
131#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
132#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
133#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
134
135#define HOSTAPD_HT_CAPAB_20 "[SHORT-GI-20]"
136#define HOSTAPD_HT_CAPAB_40 "[SHORT-GI-20][SHORT-GI-40]"
developer3cc0f2e2022-09-15 18:25:39 +0800137#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][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
1955 wifi_ieee80211_Mode mode = (wifi_ieee80211_Mode)pureMode;
1956
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
1965 if (mode & WIFI_MODE_N)
1966 list[0].value = "1";
1967 else
1968 list[0].value = "0";
1969 if (mode & WIFI_MODE_AC)
1970 list[1].value = "1";
1971 else
1972 list[1].value = "0";
1973 if (mode & WIFI_MODE_AX)
1974 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
developer06a01d92022-09-07 16:32:39 +08002000//Get the list of supported channel. eg: "1-11"
2001//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.
2002INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2003{
developer6318ed52022-09-13 15:17:58 +08002004 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002005 if (NULL == output_string)
2006 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002007 char cmd[256] = {0};
2008 char buf[128] = {0};
2009 BOOL dfs_enable = false;
2010 // Parse possible channel number and separate them with commas.
2011 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2012 if (dfs_enable)
2013 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
2014 else
2015 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
2016
2017 _syscmd(cmd,buf,sizeof(buf));
2018 strncpy(output_string, buf, sizeof(buf));
2019
2020 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2021 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002022#if 0
2023 char IFName[50] ={0};
2024 char buf[MAX_BUF_SIZE] = {0};
2025 char cmd[MAX_CMD_SIZE] = {0};
2026 int count = 0;
2027 if (NULL == output_string)
2028 return RETURN_ERR;
2029
2030 //snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2031 if(radioIndex == 0)
2032 {
2033 GetInterfaceName(IFName,"/nvram/hostapd0.conf");
2034 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'");
2035 }
2036 else if(radioIndex == 1)
2037 {
2038 GetInterfaceName(IFName,"/nvram/hostapd1.conf");
2039 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'");
2040 }
2041 _syscmd(cmd, buf, sizeof(buf));
2042 if(strlen(buf) > 0)
2043 strcpy(output_string,buf);
2044 else
2045 strcpy(output_string,"0");
2046#endif
2047 return RETURN_OK;
2048}
2049
2050//Get the list for used channel. eg: "1,6,9,11"
2051//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.
2052INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2053{
2054 if (NULL == output_string)
2055 return RETURN_ERR;
2056 snprintf(output_string, 256, (radioIndex == 0)?"1,6,11":"36,40");
2057#if 0
2058 char IFName[50] ={0};
2059 char buf[MAX_BUF_SIZE] = {0};
2060 char cmd[MAX_CMD_SIZE] = {0};
2061 if (NULL == output_string)
2062 return RETURN_ERR;
2063
2064 // snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2065 if(radioIndex == 0)
2066 {
2067 GetInterfaceName(IFName, "/nvram/hostapd0.conf");
2068 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'");
2069 }
2070 else if(radioIndex == 1)
2071 {
2072 GetInterfaceName(IFName, "/nvram/hostapd1.conf");
2073 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'");
2074 }
2075 _syscmd(cmd,buf, sizeof(buf));
2076 if(strlen(buf) > 0)
2077 strcpy(output_string,buf);
2078 else
2079 strcpy(output_string,"0");
2080#endif
2081 return RETURN_OK;
2082}
2083
2084//Get the running channel number
2085INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2086{
developerda1ed692022-09-13 13:59:20 +08002087#ifdef MTK_IMPL
2088 if(!wifi_getApChannel(radioIndex, output_ulong))
2089 return RETURN_OK;
2090 else
2091 return RETURN_ERR;
2092#else
developer06a01d92022-09-07 16:32:39 +08002093 char cmd[1024] = {0}, buf[5] = {0};
2094
2095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2096 if (NULL == output_ulong)
2097 return RETURN_ERR;
2098
2099 snprintf(cmd, sizeof(cmd),
2100 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2101 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2102 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2103 _syscmd(cmd, buf, sizeof(buf));
2104
2105 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2106 if (*output_ulong <= 0) {
2107 *output_ulong = 0;
2108 return RETURN_ERR;
2109 }
2110
2111 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2112 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002113#endif
developer06a01d92022-09-07 16:32:39 +08002114}
2115
2116
2117INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2118{
2119 char cmd[1024] = {0}, buf[5] = {0};
2120 char interface_name[50] = {0};
2121
2122 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2123 if (NULL == output_ulong)
2124 return RETURN_ERR;
2125
2126 wifi_getApName(apIndex,interface_name);
2127 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2128 _syscmd(cmd,buf,sizeof(buf));
2129 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2130 if (*output_ulong == 0) {
2131 return RETURN_ERR;
2132 }
2133
2134 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2135 return RETURN_OK;
2136}
2137
2138//Storing the previous channel value
2139INT wifi_storeprevchanval(INT radioIndex)
2140{
2141 char buf[256] = {0};
2142 char output[4]={'\0'};
2143 char config_file[MAX_BUF_SIZE] = {0};
2144 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2145 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2146 if(radioIndex == 0)
2147 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2148 else if(radioIndex == 1)
2149 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2150 system(buf);
2151 Radio_flag = FALSE;
2152 return RETURN_OK;
2153}
2154
2155//Set the running channel number
2156INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2157{
2158 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2159 struct params params={'\0'};
2160 char str_channel[4]={'\0'};
2161 struct params list;
2162 char config_file[MAX_BUF_SIZE] = {0};
2163
2164 list.name = "channel";
2165
2166 if(Radio_flag == TRUE)
2167 wifi_storeprevchanval(radioIndex); //for autochannel
2168
2169 if(radioIndex == 0)
2170 {
2171 switch(channel)
2172 {
2173 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12:
2174 sprintf(str_channel,"%ld", channel);
2175 list.value = str_channel;
2176 break;
2177 default:
2178 return RETURN_ERR;
2179 }
2180 }
2181 else if(radioIndex == 1)
2182 {
2183 switch(channel)
2184 {
2185 case 36: case 40: case 44: case 48: case 52: case 56: case 60: case 64: case 144: case 149: case 153: case 157: case 161: case 165: case 169:
2186 sprintf(str_channel,"%ld", channel);
2187 list.value = str_channel;
2188 break;
2189 default:
2190 return RETURN_ERR;
2191 }
2192 }
2193
2194 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS;i++)
2195 {
2196 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2197 wifi_hostapdWrite(config_file,&list,1);
2198 }
2199
2200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2201 return RETURN_OK;
2202 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2203 }
2204
2205INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2206{
2207 struct params list;
2208 char str_idx[16];
2209 char config_file[MAX_BUF_SIZE];
2210
2211 list.name = "vht_oper_centr_freq_seg0_idx";
2212 snprintf(str_idx, sizeof(str_idx), "%d", channel);
2213 list.value = str_idx;
2214
2215 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2216 {
2217 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2218 wifi_hostapdWrite(config_file, &list, 1);
2219 }
2220
2221 return RETURN_OK;
2222}
2223
2224//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2225//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2226INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2227{
2228 //Set to wifi config only. Wait for wifi reset to apply.
2229 char buf[256] = {0};
2230 char str_channel[256] = {0};
2231 int count = 0;
2232 ULONG Value = 0;
2233 FILE *fp = NULL;
2234 if(enable == TRUE)
2235 {
2236 if(radioIndex == 0)
2237 {
2238 // _syscmd("cat /var/prevchanval2G_AutoChannelEnable", buf, sizeof(buf));
2239 fp = fopen("/var/prevchanval2G_AutoChannelEnable","r");
2240 }
2241 else if(radioIndex == 1)
2242 {
2243 // _syscmd("cat /var/prevchanval5G_AutoChannelEnable", buf, sizeof(buf));
2244 fp = fopen("/var/prevchanval5G_AutoChannelEnable","r");
2245 }
2246 if(fp == NULL) //first time boot-up
2247 {
2248 if(radioIndex == 0)
2249 Value = 6;
2250 else if(radioIndex == 1)
2251 Value = 36;
2252 }
2253 else
2254 {
2255 if(fgets(buf,sizeof(buf),fp) != NULL)
2256 {
2257 for(count = 0;buf[count]!='\n';count++)
2258 str_channel[count] = buf[count];
2259 str_channel[count] = '\0';
2260 Value = atol(str_channel);
2261 printf("%sValue is %ld \n",__FUNCTION__,Value);
2262 pclose(fp);
2263 }
2264 }
2265 Radio_flag = FALSE;//for storing previous channel value
2266 wifi_setRadioChannel(radioIndex,Value);
2267 return RETURN_OK;
2268 }
2269 return RETURN_ERR;
2270}
2271
2272INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2273{
2274 if (NULL == output_bool)
2275 return RETURN_ERR;
2276 *output_bool=FALSE;
2277 return RETURN_OK;
2278}
2279
2280INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2281{
2282 if (NULL == output_bool)
2283 return RETURN_ERR;
2284 *output_bool=FALSE;
2285 return RETURN_OK;
2286}
2287
2288INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2289{
2290 //Set to wifi config only. Wait for wifi reset to apply.
2291 return RETURN_OK;
2292}
2293
2294INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2295{
2296 return RETURN_OK;
2297}
2298
2299INT wifi_factoryResetAP(int apIndex)
2300{
2301 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2302 //factory reset is not done for now on Turris
2303 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2304 return RETURN_OK;
2305}
2306
2307//To set Band Steering AP group
2308//To-do
2309INT wifi_setBandSteeringApGroup(char *ApGroup)
2310{
2311 return RETURN_OK;
2312}
2313
developer1e5aa162022-09-13 16:06:24 +08002314INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2315{
2316 char config_file[128] = {'\0'};
2317 char buf[128] = {'\0'};
2318
2319 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2320 if (dtimInterval == NULL)
2321 return RETURN_ERR;
2322
2323 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2324 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2325
2326 if (strlen(buf) == 0) {
2327 *dtimInterval = 2;
2328 } else {
2329 *dtimInterval = strtoul(buf, NULL, 10);
2330 }
2331
2332 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2333 return RETURN_OK;
2334}
2335
developer06a01d92022-09-07 16:32:39 +08002336INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2337{
developer5f222492022-09-13 15:21:52 +08002338 struct params params={0};
2339 char config_file[MAX_BUF_SIZE] = {'\0'};
2340 char buf[MAX_BUF_SIZE] = {'\0'};
2341
2342 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2343 if (dtimInterval < 1 || dtimInterval > 255) {
2344 return RETURN_ERR;
2345 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2346 }
2347
2348 params.name = "dtim_period";
2349 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2350 params.value = buf;
2351
2352 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2353 wifi_hostapdWrite(config_file, &params, 1);
2354 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2355
2356 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2357 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002358}
2359
2360//Check if the driver support the Dfs
2361INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2362{
2363 if (NULL == output_bool)
2364 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002365 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002366 return RETURN_OK;
2367}
2368
2369//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.
2370//The value of this parameter is a comma seperated list of channel number
2371INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2372{
2373 if (NULL == output_pool)
2374 return RETURN_ERR;
2375 if (radioIndex==1)
2376 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2377 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2378
2379 return RETURN_OK;
2380}
2381
2382INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2383{
2384 //Set to wifi config. And apply instantly.
2385 return RETURN_OK;
2386}
2387
2388INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2389{
2390 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2391 return RETURN_ERR;
2392 *output_interval_seconds=1800;
2393 *output_dwell_milliseconds=40;
2394
2395 return RETURN_OK;
2396}
2397
2398INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2399{
2400 //Set to wifi config. And apply instantly.
2401 return RETURN_OK;
2402}
2403
2404//Get the Dfs enable status
2405INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2406{
developer9964b5b2022-09-13 15:59:34 +08002407 char buf[16] = {0};
2408 FILE *f = NULL;
2409 wifi_band band;
2410
2411 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2412
2413 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002414 if (NULL == output_bool)
2415 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002416
2417 band = wifi_index_to_band(radioIndex);
2418 if (band != band_5)
2419 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002420
developer9964b5b2022-09-13 15:59:34 +08002421 f = fopen(DFS_ENABLE_FILE, "r");
2422 if (f != NULL) {
2423 fgets(buf, 2, f);
2424 if (strncmp(buf, "0", 0) == 0)
2425 *output_bool = FALSE;
2426 fclose(f);
2427 }
2428 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002429 return RETURN_OK;
2430}
2431
2432//Set the Dfs enable status
2433INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2434{
developer9964b5b2022-09-13 15:59:34 +08002435 char buf[128] = {0};
2436 char config_file[128] = {0};
2437 FILE *f = NULL;
2438 struct params params={0};
2439 wifi_band band;
2440
2441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2442
2443 band = wifi_index_to_band(radioIndex);
2444 if (band != band_5)
2445 return RETURN_OK;
2446
2447 f = fopen(DFS_ENABLE_FILE, "w");
2448 if (f == NULL)
2449 return RETURN_ERR;
2450 fprintf(f, "%d", enable);
2451 fclose(f);
2452
2453 params.name = "acs_exclude_dfs";
2454 sprintf(buf, "%d", enable?"1":"0");
2455 params.value = buf;
2456 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2457 wifi_hostapdWrite(config_file, &params, 1);
2458 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2459
2460 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2461
2462 wifi_reloadAp(radioIndex);
2463
2464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002465}
2466
2467//Check if the driver support the AutoChannelRefreshPeriod
2468INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2469{
2470 if (NULL == output_bool)
2471 return RETURN_ERR;
2472 *output_bool=FALSE; //not support
2473
2474 return RETURN_OK;
2475}
2476
2477//Get the ACS refresh period in seconds
2478INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2479{
2480 if (NULL == output_ulong)
2481 return RETURN_ERR;
2482 *output_ulong=300;
2483
2484 return RETURN_OK;
2485}
2486
2487//Set the ACS refresh period in seconds
2488INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2489{
2490 return RETURN_ERR;
2491}
2492
2493//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2494//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.
2495INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2496{
developer70490032022-09-13 15:45:20 +08002497 char cmd[128] = {0}, buf[64] = {0};
2498 char interface_name[64] = {0};
2499 int ret = 0, len=0;
2500 BOOL radio_enable = FALSE;
2501
2502 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2503
developer06a01d92022-09-07 16:32:39 +08002504 if (NULL == output_string)
2505 return RETURN_ERR;
2506
developer70490032022-09-13 15:45:20 +08002507 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2508 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002509
developer70490032022-09-13 15:45:20 +08002510 if (radio_enable != TRUE)
2511 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002512
developer70490032022-09-13 15:45:20 +08002513 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002514 ret = _syscmd(cmd, buf, sizeof(buf));
2515 len = strlen(buf);
2516 if((ret != 0) || (len == 0))
2517 {
2518 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2519 return RETURN_ERR;
2520 }
2521
2522 buf[len-1] = '\0';
2523 snprintf(output_string, 64, "%sMHz", buf);
2524 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2525
2526#if 0
2527 //TODO: revisit below implementation
2528 char output_buf[8]={0};
2529 char bw_value[10];
2530 char config_file[MAX_BUF_SIZE] = {0};
2531
2532 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2533 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2534 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2535 readBandWidth(radioIndex,bw_value);
2536
2537 if(strstr (output_buf,"0") != NULL )
2538 {
2539 strcpy(output_string,bw_value);
2540 }
2541 else if (strstr (output_buf,"1") != NULL)
2542 {
2543 strcpy(output_string,"80MHz");
2544 }
2545 else if (strstr (output_buf,"2") != NULL)
2546 {
2547 strcpy(output_string,"160MHz");
2548 }
2549 else if (strstr (output_buf,"3") != NULL)
2550 {
2551 strcpy(output_string,"80+80");
2552 }
2553 else
2554 {
2555 strcpy(output_string,"Auto");
2556 }
2557 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2558#endif
2559
2560 return RETURN_OK;
2561}
2562
2563//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002564INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002565{
developerf7a466e2022-09-29 11:55:56 +08002566 char config_file[128];
2567 char set_value[16];
2568 struct params params[2];
2569 int max_radio_num = 0;
2570
developer06a01d92022-09-07 16:32:39 +08002571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002572
developerf7a466e2022-09-29 11:55:56 +08002573 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002574 return RETURN_ERR;
2575
developerf7a466e2022-09-29 11:55:56 +08002576 if(strstr(bandwidth,"80+80") != NULL)
2577 strcpy(set_value, "3");
2578 else if(strstr(bandwidth,"160") != NULL)
2579 strcpy(set_value, "2");
2580 else if(strstr(bandwidth,"80") != NULL)
2581 strcpy(set_value, "1");
2582 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2583 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002584 else
2585 {
developerf7a466e2022-09-29 11:55:56 +08002586 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002587 return RETURN_ERR;
2588 }
2589
developerf7a466e2022-09-29 11:55:56 +08002590 params[0].name = "vht_oper_chwidth";
2591 params[0].value = set_value;
2592 params[1].name = "he_oper_chwidth";
2593 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002594
developerf7a466e2022-09-29 11:55:56 +08002595 wifi_getMaxRadioNumber(&max_radio_num);
2596 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002597 {
developerf7a466e2022-09-29 11:55:56 +08002598 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2599 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002600 }
2601
2602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2603 return RETURN_OK;
2604}
2605
2606//Getting current radio extension channel
2607INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2608{
2609 CHAR buf[150] = {0};
2610 CHAR cmd[150] = {0};
2611 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2612 _syscmd(cmd, buf, sizeof(buf));
2613 if(NULL != strstr(buf,"HT40+"))
2614 strcpy(Value,"AboveControlChannel");
2615 else if(NULL != strstr(buf,"HT40-"))
2616 strcpy(Value,"BelowControlChannel");
2617 return RETURN_OK;
2618}
2619
2620//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2621//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.
2622INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2623{
2624 if (NULL == output_string)
2625 return RETURN_ERR;
2626
2627 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2628#if 0
2629 CHAR Value[100] = {0};
2630 if (NULL == output_string)
2631 return RETURN_ERR;
2632 if(radioIndex == 0)
2633 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2634 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2635 {
2636 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2637 if(strcmp(Value,"40MHz") == 0)
2638 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2639 else
2640 strcpy(Value,"Auto");
2641 }
2642 strcpy(output_string,Value);
2643#endif
2644
2645 return RETURN_OK;
2646}
2647
2648//Set the extension channel.
2649INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2650{
2651 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2652 struct params params={'\0'};
2653 char config_file[MAX_BUF_SIZE] = {0};
2654 char ext_channel[127]={'\0'};
2655
2656 params.name = "ht_capab";
2657
2658 if(radioIndex == 0)
2659 {
2660 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002661 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002662 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002663 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002664 else
developer3cc0f2e2022-09-15 18:25:39 +08002665 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002666 }
2667 else if(radioIndex == 1)
2668 {
2669 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002670 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002671 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002672 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002673 else
developer3cc0f2e2022-09-15 18:25:39 +08002674 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002675 }
2676
2677 params.value = ext_channel;
2678 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2679 {
2680 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2681 wifi_hostapdWrite(config_file, &params, 1);
2682 }
2683
2684 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2685 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2686 return RETURN_OK;
2687}
2688
2689//Get the guard interval value. eg "400nsec" or "800nsec"
2690//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.
2691INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2692{
developer454b9462022-09-13 15:29:16 +08002693 wifi_guard_interval_t GI;
2694
2695 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2696
2697 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002698 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002699
2700 if (GI == wifi_guard_interval_400)
2701 strcpy(output_string, "400nsec");
2702 else if (GI == wifi_guard_interval_800)
2703 strcpy(output_string, "800nsec");
2704 else if (GI == wifi_guard_interval_1600)
2705 strcpy(output_string, "1600nsec");
2706 else if (GI == wifi_guard_interval_3200)
2707 strcpy(output_string, "3200nsec");
2708 else
2709 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002710
developer454b9462022-09-13 15:29:16 +08002711 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002712 return RETURN_OK;
2713}
2714
2715//Set the guard interval value.
2716INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2717{
developer454b9462022-09-13 15:29:16 +08002718 wifi_guard_interval_t GI;
2719 int ret = 0;
2720
2721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2722
2723 if (strcmp(string, "400nsec") == 0)
2724 GI = wifi_guard_interval_400;
2725 else if (strcmp(string , "800nsec") == 0 || strcmp(string, "auto") == 0)
2726 GI = wifi_guard_interval_800;
2727 else if (strcmp(string , "1600nsec") == 0)
2728 GI = wifi_guard_interval_1600;
2729 else if (strcmp(string , "3200nsec") == 0)
2730 GI = wifi_guard_interval_3200;
2731
2732 ret = wifi_setGuardInterval(radioIndex, GI);
2733
2734 if (ret == RETURN_ERR) {
2735 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2736 return RETURN_ERR;
2737 }
2738
2739 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2740 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002741}
2742
2743//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2744INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2745{
2746 if (NULL == output_int)
2747 return RETURN_ERR;
2748 *output_int=(radioIndex==0)?1:3;
2749
2750 return RETURN_OK;
2751}
2752
2753//Set the Modulation Coding Scheme index
2754INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2755{
2756 return RETURN_ERR;
2757}
2758
2759//Get supported Transmit Power list, eg : "0,25,50,75,100"
2760//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.
2761INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2762{
2763 if (NULL == output_list)
2764 return RETURN_ERR;
2765 snprintf(output_list, 64,"0,25,50,75,100");
2766 return RETURN_OK;
2767}
2768
developera5005b62022-09-13 15:43:35 +08002769//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002770//The transmite power level is in units of full power for this radio.
2771INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2772{
2773 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002774 char buf[16]={0};
2775 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002776
developera5005b62022-09-13 15:43:35 +08002777 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002778 return RETURN_ERR;
2779
developera5005b62022-09-13 15:43:35 +08002780 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 +08002781 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002782
developera5005b62022-09-13 15:43:35 +08002783 *output_ulong = strtol(buf, NULL, 10);
2784
2785 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002786 return RETURN_OK;
2787}
2788
2789//Set Transmit Power
2790//The transmite power level is in units of full power for this radio.
2791INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2792{
developera5005b62022-09-13 15:43:35 +08002793 char *support;
developer06a01d92022-09-07 16:32:39 +08002794 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002795 char buf[128]={0};
2796 char txpower_str[64] = {0};
2797 int txpower = 0;
2798 int maximum_tx = 0;
2799
2800 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002801
developera5005b62022-09-13 15:43:35 +08002802 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 +08002803 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002804 maximum_tx = strtol(buf, NULL, 10);
2805
2806 // Get the Tx power supported list and check that is the input in the list
2807 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2808 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2809 support = strtok(buf, ",");
2810 while(true)
2811 {
2812 if(support == NULL) { // input not in the list
2813 wifi_dbg_printf("Input value is invalid.\n");
2814 return RETURN_ERR;
2815 }
2816 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2817 break;
2818 }
2819 support = strtok(NULL, ",");
2820 }
2821 txpower = TransmitPower*maximum_tx/100;
2822 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2823 _syscmd(cmd, buf, sizeof(buf));
2824 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002825
2826 return RETURN_OK;
2827}
2828
2829//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2830INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2831{
2832 if (NULL == Supported)
2833 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002834 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002835
2836 return RETURN_OK;
2837}
2838
2839//Get 80211h feature enable
2840INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2841{
developer3885fec2022-09-13 15:13:47 +08002842 char buf[64]={'\0'};
2843 char config_file[64] = {'\0'};
2844
2845 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2846 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002847 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002848
2849 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2850 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002851
developer3885fec2022-09-13 15:13:47 +08002852 if (strncmp(buf, "1", 1) == 0)
2853 *enable = TRUE;
2854 else
2855 *enable = FALSE;
2856
2857 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002858 return RETURN_OK;
2859}
2860
2861//Set 80211h feature enable
2862INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2863{
developer3885fec2022-09-13 15:13:47 +08002864 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2865 struct params params={'\0'};
2866 char config_file[MAX_BUF_SIZE] = {0};
2867
2868 params.name = "ieee80211h";
2869
2870 if (enable) {
2871 params.value = "1";
2872 } else {
2873 params.value = "0";
2874 }
2875
2876 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2877 wifi_hostapdWrite(config_file, &params, 1);
2878
2879 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2880 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2881 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002882}
2883
2884//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.
2885INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2886{
2887 if (NULL == output)
2888 return RETURN_ERR;
2889 *output=100;
2890
2891 return RETURN_OK;
2892}
2893
2894//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.
2895INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2896{
2897 if (NULL == output)
2898 return RETURN_ERR;
2899 *output = -99;
2900
2901 return RETURN_OK;
2902}
2903
2904INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
2905{
2906 return RETURN_ERR;
2907}
2908
2909
2910//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
2911INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
2912{
developer5f222492022-09-13 15:21:52 +08002913 char cmd[MAX_BUF_SIZE]={'\0'};
2914 char buf[MAX_CMD_SIZE]={'\0'};
2915
2916 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2917 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08002918 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002919
2920 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
2921 _syscmd(cmd, buf, sizeof(buf));
2922 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08002923
developer5f222492022-09-13 15:21:52 +08002924 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002925 return RETURN_OK;
2926}
2927
2928INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
2929{
developer5f222492022-09-13 15:21:52 +08002930 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2931 struct params params={'\0'};
2932 char buf[MAX_BUF_SIZE] = {'\0'};
2933 char config_file[MAX_BUF_SIZE] = {'\0'};
2934
2935 params.name = "beacon_int";
2936 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
2937 params.value = buf;
2938
2939 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2940 wifi_hostapdWrite(config_file, &params, 1);
2941
2942 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2944 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002945}
2946
2947//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.
2948INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
2949{
developer06a01d92022-09-07 16:32:39 +08002950 //TODO: need to revisit below implementation
2951 char *temp;
developere9d0abd2022-09-13 15:40:57 +08002952 char temp_output[128] = {0};
2953 char temp_TransmitRates[64] = {0};
2954 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08002955
2956 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2957 if (NULL == output)
2958 return RETURN_ERR;
2959 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08002960 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
2961
2962 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
2963 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
2964 } else {
2965 temp = strtok(temp_TransmitRates," ");
2966 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08002967 {
developere9d0abd2022-09-13 15:40:57 +08002968 // Convert 100 kbps to Mbps
2969 temp[strlen(temp)-1]=0;
2970 if((temp[0]=='5') && (temp[1]=='\0'))
2971 {
2972 temp="5.5";
2973 }
2974 strcat(temp_output,temp);
2975 temp = strtok(NULL," ");
2976 if(temp!=NULL)
2977 {
2978 strcat(temp_output,",");
2979 }
developer06a01d92022-09-07 16:32:39 +08002980 }
developere9d0abd2022-09-13 15:40:57 +08002981 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08002982 }
developer06a01d92022-09-07 16:32:39 +08002983 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002984 return RETURN_OK;
2985}
2986
2987INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
2988{
2989 char *temp;
2990 char temp1[128];
2991 char temp_output[128];
2992 char temp_TransmitRates[128];
2993 char set[128];
2994 char sub_set[128];
2995 int set_count=0,subset_count=0;
2996 int set_index=0,subset_index=0;
2997 char *token;
2998 int flag=0, i=0;
2999 struct params params={'\0'};
3000 char config_file[MAX_BUF_SIZE] = {0};
3001
3002 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3003 if(NULL == TransmitRates)
3004 return RETURN_ERR;
3005 strcpy(sub_set,TransmitRates);
3006
3007 //Allow only supported Data transmit rate to be set
3008 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3009 token = strtok(sub_set,",");
3010 while( token != NULL ) /* split the basic rate to be set, by comma */
3011 {
3012 sub_set[subset_count]=atoi(token);
3013 subset_count++;
3014 token=strtok(NULL,",");
3015 }
3016 token=strtok(set,",");
3017 while(token!=NULL) /* split the supported rate by comma */
3018 {
3019 set[set_count]=atoi(token);
3020 set_count++;
3021 token=strtok(NULL,",");
3022 }
3023 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3024 {
3025 for(set_index=0;set_index < set_count;set_index++)
3026 {
3027 flag=0;
3028 if(sub_set[subset_index]==set[set_index])
3029 break;
3030 else
3031 flag=1; /* No match found */
3032 }
3033 if(flag==1)
3034 return RETURN_ERR; //If value not found return Error
3035 }
3036 strcpy(temp_TransmitRates,TransmitRates);
3037
3038 for(i=0;i<strlen(temp_TransmitRates);i++)
3039 {
3040 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3041 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3042 {
3043 continue;
3044 }
3045 else
3046 {
3047 return RETURN_ERR;
3048 }
3049 }
3050 strcpy(temp_output,"");
3051 temp = strtok(temp_TransmitRates,",");
3052 while(temp!=NULL)
3053 {
3054 strcpy(temp1,temp);
3055 if(radioIndex==1)
3056 {
3057 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3058 {
3059 return RETURN_ERR;
3060 }
3061 }
3062
3063 if(strcmp(temp,"5.5")==0)
3064 {
3065 strcpy(temp1,"55");
3066 }
3067 else
3068 {
3069 strcat(temp1,"0");
3070 }
3071 strcat(temp_output,temp1);
3072 temp = strtok(NULL,",");
3073 if(temp!=NULL)
3074 {
3075 strcat(temp_output," ");
3076 }
3077 }
3078 strcpy(TransmitRates,temp_output);
3079
3080 params.name= "basic_rates";
3081 params.value =TransmitRates;
3082
3083 wifi_dbg_printf("\n%s:",__func__);
3084 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3085 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3086 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3087 wifi_hostapdWrite(config_file,&params,1);
3088 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3089 return RETURN_OK;
3090}
3091
3092//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3093INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3094{
3095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3096 FILE *fp = NULL;
3097 char path[256] = {0}, output_string[256] = {0};
3098 int count = 0;
3099 char *interface = NULL;
3100
3101 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3102 if (fp == NULL)
3103 {
3104 printf("Failed to run command in Function %s\n", __FUNCTION__);
3105 return RETURN_ERR;
3106 }
3107 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3108 {
3109 interface = strchr(path, '=');
3110
3111 if (interface != NULL)
3112 {
3113 strcpy(output_string, interface + 1);
3114 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3115 interface_name[count] = output_string[count];
3116
3117 interface_name[count] = '\0';
3118 }
3119 }
3120 pclose(fp);
3121 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3122 return RETURN_OK;
3123}
3124
3125INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3126{
3127 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3128 output_struct->radio_BytesSent = 0;
3129 output_struct->radio_BytesReceived = 0;
3130 output_struct->radio_PacketsSent = 0;
3131 output_struct->radio_PacketsReceived = 0;
3132 output_struct->radio_ErrorsSent = 0;
3133 output_struct->radio_ErrorsReceived = 0;
3134 output_struct->radio_DiscardPacketsSent = 0;
3135 output_struct->radio_DiscardPacketsReceived = 0;
3136 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3137 return RETURN_OK;
3138}
3139
3140
3141INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3142{
3143 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3144 CHAR buf[MAX_CMD_SIZE] = {0};
3145 CHAR Value[MAX_BUF_SIZE] = {0};
3146 FILE *fp = NULL;
3147
3148 if (ifname == NULL || strlen(ifname) <= 1)
3149 return RETURN_OK;
3150
3151 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3152 system(buf);
3153
3154 fp = fopen("/tmp/Radio_Stats.txt", "r");
3155 if(fp == NULL)
3156 {
3157 printf("/tmp/Radio_Stats.txt not exists \n");
3158 return RETURN_ERR;
3159 }
3160 fclose(fp);
3161
3162 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3163 File_Reading(buf, Value);
3164 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3165
3166 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3167 File_Reading(buf, Value);
3168 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3169
3170 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3171 File_Reading(buf, Value);
3172 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3173
3174 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3175 File_Reading(buf, Value);
3176 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3177
3178 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3179 File_Reading(buf, Value);
3180 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3181
3182 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3183 File_Reading(buf, Value);
3184 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3185
3186 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3187 File_Reading(buf, Value);
3188 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3189
3190 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3191 File_Reading(buf, Value);
3192 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3193
3194 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3195 return RETURN_OK;
3196}
3197
3198INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3199{
3200 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3201 CHAR buf[MAX_CMD_SIZE] = {0};
3202 FILE *fp = NULL;
3203 INT count = 0;
3204
3205 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3206 {
3207 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3208 File_Reading(buf, status);
3209 }
3210 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3211 return RETURN_OK;
3212}
3213
3214//Get detail radio traffic static info
3215INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3216{
3217
3218#if 0
3219 //ifconfig radio_x
3220 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3221 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3222 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3223 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3224
3225 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3226 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3227 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.
3228 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.
3229
3230 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3231 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].
3232 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3233 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.
3234 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
3235 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
3236 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
3237 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
3238 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
3239
3240 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
3241 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
3242 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
3243 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.
3244
3245 return RETURN_OK;
3246#endif
3247
developera91d99f2022-09-29 15:59:10 +08003248 CHAR interface_name[64] = {0};
3249 CHAR config_path[64] = {0};
3250 BOOL iface_status = FALSE;
3251 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003252
3253 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3254 if (NULL == output_struct)
3255 return RETURN_ERR;
3256
developera91d99f2022-09-29 15:59:10 +08003257 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3258 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003259
developera91d99f2022-09-29 15:59:10 +08003260 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003261
developera91d99f2022-09-29 15:59:10 +08003262 if (iface_status == TRUE)
3263 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3264 else
3265 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003266
developera91d99f2022-09-29 15:59:10 +08003267 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3268 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3269 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3270 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3271 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3272 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3273 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3274 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003275
3276 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3277 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].
3278 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3279 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.
3280 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
3281 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
3282 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
3283 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
3284 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
3285
3286 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
3287 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
3288 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
3289 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.
3290
3291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3292
3293 return RETURN_OK;
3294}
3295
3296//Set radio traffic static Measureing rules
3297INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3298{
3299 //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
3300 // Else, save the MeasuringRate and MeasuringInterval for future usage
3301
3302 return RETURN_OK;
3303}
3304
3305//To start or stop RadioTrafficStats
3306INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3307{
3308 //zqiu: If the RadioTrafficStats process running
3309 // if(enable)
3310 // return RETURN_OK.
3311 // else
3312 // Stop RadioTrafficStats process
3313 // Else
3314 // if(enable)
3315 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3316 // else
3317 // return RETURN_OK.
3318
3319 return RETURN_OK;
3320}
3321
3322//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
3323INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3324{
3325 //zqiu: Please ignor signalIndex.
3326 if (NULL == SignalLevel)
3327 return RETURN_ERR;
3328 *SignalLevel=(radioIndex==0)?-19:-19;
3329
3330 return RETURN_OK;
3331}
3332
3333//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3334INT wifi_applyRadioSettings(INT radioIndex)
3335{
3336 return RETURN_OK;
3337}
3338
3339//Get the radio index assocated with this SSID entry
3340INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3341{
3342 if (NULL == radioIndex)
3343 return RETURN_ERR;
3344 *radioIndex=ssidIndex%2;
3345
3346 return RETURN_OK;
3347}
3348
3349//Device.WiFi.SSID.{i}.Enable
3350//Get SSID enable configuration parameters (not the SSID enable status)
3351INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3352{
3353 if (NULL == output_bool)
3354 return RETURN_ERR;
3355
3356 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3357 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3358 return wifi_getApEnable(ssidIndex, output_bool);
3359}
3360
3361//Device.WiFi.SSID.{i}.Enable
3362//Set SSID enable configuration parameters
3363INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3364{
3365 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3366 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3367 return wifi_setApEnable(ssidIndex, enable);
3368}
3369
3370//Device.WiFi.SSID.{i}.Status
3371//Get the SSID enable status
3372INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3373{
3374 char cmd[MAX_CMD_SIZE]={0};
3375 char buf[MAX_BUF_SIZE]={0};
3376 BOOL output_bool;
3377
3378 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3379 if (NULL == output_string)
3380 return RETURN_ERR;
3381 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3382 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3383
3384 wifi_getApEnable(ssidIndex,&output_bool);
3385 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3386
3387 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3388 return RETURN_OK;
3389}
3390
3391// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3392INT wifi_getSSIDName(INT apIndex, CHAR *output)
3393{
3394 char config_file[MAX_BUF_SIZE] = {0};
3395
3396 if (NULL == output)
3397 return RETURN_ERR;
3398
3399 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3400 wifi_hostapdRead(config_file,"ssid",output,32);
3401
3402 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3403 return RETURN_OK;
3404}
3405
3406// Set a max 32 byte string and sets an internal variable to the SSID name
3407INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3408{
3409 char str[MAX_BUF_SIZE]={'\0'};
3410 char cmd[MAX_CMD_SIZE]={'\0'};
3411 struct params params;
3412 char config_file[MAX_BUF_SIZE] = {0};
3413
3414 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3415 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3416 return RETURN_ERR;
3417
3418 params.name = "ssid";
3419 params.value = ssid_string;
3420 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3421 wifi_hostapdWrite(config_file, &params, 1);
3422 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3423 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3424
3425 return RETURN_OK;
3426}
3427
3428//Get the BSSID
3429INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3430{
3431 char cmd[MAX_CMD_SIZE]="";
3432
3433 if (NULL == output_string)
3434 return RETURN_ERR;
3435
3436 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3437 {
3438 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3439 _syscmd(cmd, output_string, 64);
3440 return RETURN_OK;
3441 }
3442 strncpy(output_string, "\0", 1);
3443
3444 return RETURN_ERR;
3445}
3446
3447//Get the MAC address associated with this Wifi SSID
3448INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3449{
3450 wifi_getBaseBSSID(ssidIndex,output_string);
3451 return RETURN_OK;
3452}
3453
3454//Get the basic SSID traffic static info
3455//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3456//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3457INT wifi_applySSIDSettings(INT ssidIndex)
3458{
3459 BOOL status = false;
3460 char cmd[MAX_CMD_SIZE] = {0};
3461 char buf[MAX_CMD_SIZE] = {0};
3462 int apIndex, ret;
3463 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3464
3465 wifi_getApEnable(ssidIndex,&status);
3466 // Do not apply when ssid index is disabled
3467 if (status == false)
3468 return RETURN_OK;
3469
3470 /* Doing full remove and add for ssid Index
3471 * Not all hostapd options are supported with reload
3472 * for example macaddr_acl
3473 */
3474 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3475 return RETURN_ERR;
3476
3477 ret = wifi_setApEnable(ssidIndex,true);
3478
3479 /* Workaround for hostapd issue with multiple bss definitions
3480 * when first created interface will be removed
3481 * then all vaps other vaps on same phy are removed
3482 * after calling setApEnable to false readd all enabled vaps */
3483 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3484 apIndex = 2*i+radioIndex;
3485 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3486 _syscmd(cmd, buf, sizeof(buf));
3487 if(*buf == '1')
3488 wifi_setApEnable(apIndex, true);
3489 }
3490
3491 return ret;
3492}
3493
developera3c68b92022-09-13 15:27:29 +08003494struct channels_noise {
3495 int channel;
3496 int noise;
3497};
3498
3499// Return noise array for each channel
3500int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3501{
3502 FILE *f = NULL;
3503 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003504 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003505 size_t len = 0;
3506 ssize_t read = 0;
3507 int tmp = 0, arr_index = -1;
3508
3509 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3510
3511 if ((f = popen(cmd, "r")) == NULL) {
3512 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3513 return RETURN_ERR;
3514 }
developer5550e242022-09-30 09:59:32 +08003515
3516 while(fgets(line, sizeof(line), f) != NULL) {
3517 if(arr_index < channels_num){
3518 sscanf(line, "%d", &tmp);
3519 if (tmp > 0) { // channel frequency, the first line must be frequency
3520 arr_index++;
3521 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3522 } else { // noise
3523 channels_noise_arr[arr_index].noise = tmp;
3524 }
3525 }else{
3526 break;
developera3c68b92022-09-13 15:27:29 +08003527 }
3528 }
developera3c68b92022-09-13 15:27:29 +08003529 pclose(f);
3530 return RETURN_OK;
3531}
3532
developer06a01d92022-09-07 16:32:39 +08003533//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3534//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3535INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3536{
developera3c68b92022-09-13 15:27:29 +08003537 int index = -1;
3538 wifi_neighbor_ap2_t *scan_array = NULL;
3539 char cmd[256]={0};
3540 char buf[128]={0};
3541 char file_name[32] = {0};
3542 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003543 char line[256] = {0};
3544 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003545 int freq=0;
3546 FILE *f = NULL;
3547 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003548 int channels_num = 0;
3549 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003550 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003551 bool filter_enable = false;
3552 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003553
developer615510b2022-09-27 10:14:35 +08003554 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003555
3556 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3557 f = fopen(file_name, "r");
3558 if (f != NULL) {
3559 fgets(filter_SSID, sizeof(file_name), f);
3560 if (strlen(filter_SSID) != 0)
3561 filter_enable = true;
3562 fclose(f);
3563 }
3564
3565 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003566 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003567 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003568
developer5550e242022-09-30 09:59:32 +08003569
developer06a01d92022-09-07 16:32:39 +08003570
developera3c68b92022-09-13 15:27:29 +08003571 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 +08003572 // 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 +08003573 fprintf(stderr, "cmd: %s\n", cmd);
3574 if ((f = popen(cmd, "r")) == NULL) {
3575 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3576 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003577 }
developer5550e242022-09-30 09:59:32 +08003578
3579 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3580 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3581
developer615510b2022-09-27 10:14:35 +08003582 ret = fgets(line, sizeof(line), f);
3583 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003584 if(strstr(line, "BSS") != NULL) { // new neighbor info
3585 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3586 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3587 // 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 +08003588
developera3c68b92022-09-13 15:27:29 +08003589 if (!filter_BSS) {
3590 index++;
3591 wifi_neighbor_ap2_t *tmp;
3592 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3593 if (tmp == NULL) { // no more memory to use
3594 index--;
3595 wifi_dbg_printf("%s: realloc failed\n", __func__);
3596 break;
3597 }
3598 scan_array = tmp;
3599 }
3600 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3601
3602 filter_BSS = false;
3603 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3604 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3605 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3606 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3607 } else if (strstr(line, "freq") != NULL) {
3608 sscanf(line," freq: %d", &freq);
3609 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3610
3611 if (freq >= 2412 && freq <= 2484) {
3612 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3613 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3614 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3615 }
3616 else if (freq >= 5160 && freq <= 5805) {
3617 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3618 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3619 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3620 }
3621
3622 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003623 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003624 for (int i = 0; i < channels_num; i++) {
3625 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3626 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3627 break;
3628 }
3629 }
3630 }
3631 } else if (strstr(line, "beacon interval") != NULL) {
3632 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3633 } else if (strstr(line, "signal") != NULL) {
3634 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3635 } else if (strstr(line,"SSID") != NULL) {
3636 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3637 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3638 filter_BSS = true;
3639 }
3640 } else if (strstr(line, "Supported rates") != NULL) {
3641 char SRate[80] = {0}, *tmp = NULL;
3642 memset(buf, 0, sizeof(buf));
3643 strcpy(SRate, line);
3644 tmp = strtok(SRate, ":");
3645 tmp = strtok(NULL, ":");
3646 strcpy(buf, tmp);
3647 memset(SRate, 0, sizeof(SRate));
3648
3649 tmp = strtok(buf, " \n");
3650 while (tmp != NULL) {
3651 strcat(SRate, tmp);
3652 if (SRate[strlen(SRate) - 1] == '*') {
3653 SRate[strlen(SRate) - 1] = '\0';
3654 }
3655 strcat(SRate, ",");
3656
3657 tmp = strtok(NULL, " \n");
3658 }
3659 SRate[strlen(SRate) - 1] = '\0';
3660 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3661 } else if (strstr(line, "DTIM") != NULL) {
3662 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3663 } else if (strstr(line, "VHT capabilities") != NULL) {
3664 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3665 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3666 } else if (strstr(line, "HT capabilities") != NULL) {
3667 strcat(scan_array[index].ap_SupportedStandards, ",n");
3668 strcpy(scan_array[index].ap_OperatingStandards, "n");
3669 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003670 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003671 sscanf(line," * channel width: %d", &vht_channel_width);
3672 if(vht_channel_width == 1) {
3673 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3674 } else {
3675 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3676 }
3677 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3678 continue;
3679 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003680 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003681 sscanf(line," * secondary channel offset: %s", &buf);
3682 if (!strcmp(buf, "above")) {
3683 //40Mhz +
3684 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3685 }
3686 else if (!strcmp(buf, "below")) {
3687 //40Mhz -
3688 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3689 } else {
3690 //20Mhz
3691 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3692 }
3693 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3694 continue;
3695 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003696 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3697 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3698 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003699 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3700 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003701 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003702 else
developer615510b2022-09-27 10:14:35 +08003703 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003704 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003705 if (strstr(line, "HE80/5GHz") != NULL) {
3706 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3707 ret = fgets(line, sizeof(line), f);
3708 } else
3709 continue;
developera3c68b92022-09-13 15:27:29 +08003710 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003711 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003712 }
developer615510b2022-09-27 10:14:35 +08003713 continue;
developera3c68b92022-09-13 15:27:29 +08003714 } else if (strstr(line, "WPA") != NULL) {
3715 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3716 } else if (strstr(line, "RSN") != NULL) {
3717 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3718 } else if (strstr(line, "Group cipher") != NULL) {
3719 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3720 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3721 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3722 }
3723 }
developer615510b2022-09-27 10:14:35 +08003724 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003725 }
3726
3727 if (!filter_BSS) {
3728 *output_array_size = index + 1;
3729 } else {
3730 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3731 *output_array_size = index;
3732 }
3733 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003734 pclose(f);
developer5550e242022-09-30 09:59:32 +08003735 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003737 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003738}
3739
3740//>> Deprecated: used for old RDKB code.
3741INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3742{
3743 INT status = RETURN_ERR;
3744
3745 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3746 output_struct->wifi_PLCPErrorCount = 0;
3747 output_struct->wifi_FCSErrorCount = 0;
3748 output_struct->wifi_InvalidMACCount = 0;
3749 output_struct->wifi_PacketsOtherReceived = 0;
3750 output_struct->wifi_Noise = 0;
3751 status = RETURN_OK;
3752 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3753 return status;
3754}
3755
3756INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3757{
3758 char cmd[128];
3759 char buf[1280];
3760 char *pos = NULL;
3761
3762 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3763 if (NULL == output_struct)
3764 return RETURN_ERR;
3765
3766 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3767
3768 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3769 _syscmd(cmd, buf, sizeof(buf));
3770
3771 pos = buf;
3772 if ((pos = strstr(pos, "RX packets:")) == NULL)
3773 return RETURN_ERR;
3774 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3775
3776 if ((pos = strstr(pos, "TX packets:")) == NULL)
3777 return RETURN_ERR;
3778 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3779
3780 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3781 return RETURN_ERR;
3782 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3783
3784 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3785 return RETURN_ERR;
3786 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3787
3788 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3789 _syscmd(cmd, buf, sizeof(buf));
3790 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3791
3792#if 0
3793 //TODO: need to revisit below implementation
3794 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3795 char interface_name[MAX_BUF_SIZE] = {0};
3796 char interface_status[MAX_BUF_SIZE] = {0};
3797 char Value[MAX_BUF_SIZE] = {0};
3798 char buf[MAX_CMD_SIZE] = {0};
3799 char cmd[MAX_CMD_SIZE] = {0};
3800 FILE *fp = NULL;
3801
3802 if (NULL == output_struct) {
3803 return RETURN_ERR;
3804 }
3805
3806 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3807
3808 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3809 {
3810 if(apIndex == 0) //private_wifi for 2.4G
3811 {
3812 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3813 }
3814 else if(apIndex == 1) //private_wifi for 5G
3815 {
3816 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3817 }
3818 else if(apIndex == 4) //public_wifi for 2.4G
3819 {
3820 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3821 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3822 {
3823 return RETURN_ERR;
3824 }
3825 if(buf[0] == '#')//tp-link
3826 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3827 else//tenda
3828 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3829 }
3830 else if(apIndex == 5) //public_wifi for 5G
3831 {
3832 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3833 }
3834
3835 GetIfacestatus(interface_name, interface_status);
3836
3837 if(0 != strcmp(interface_status, "1"))
3838 return RETURN_ERR;
3839
3840 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3841 system(cmd);
3842
3843 fp = fopen("/tmp/SSID_Stats.txt", "r");
3844 if(fp == NULL)
3845 {
3846 printf("/tmp/SSID_Stats.txt not exists \n");
3847 return RETURN_ERR;
3848 }
3849 fclose(fp);
3850
3851 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3852 File_Reading(buf, Value);
3853 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3854
3855 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3856 File_Reading(buf, Value);
3857 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3858
3859 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3860 File_Reading(buf, Value);
3861 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3862
3863 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3864 File_Reading(buf, Value);
3865 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3866
3867 /* There is no specific parameter from caller to associate the value wifi_Associations */
3868 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3869 //_syscmd(cmd, buf, sizeof(buf));
3870 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3871 }
3872#endif
3873 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3874 return RETURN_OK;
3875}
3876
3877INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3878{
3879 char interface_name[MAX_BUF_SIZE] = {0};
3880 char interface_status[MAX_BUF_SIZE] = {0};
3881 char Value[MAX_BUF_SIZE] = {0};
3882 char buf[MAX_CMD_SIZE] = {0};
3883 char cmd[MAX_CMD_SIZE] = {0};
3884 FILE *fp = NULL;
3885
3886 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3887 if (NULL == output_struct)
3888 return RETURN_ERR;
3889
3890 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
3891
3892 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3893 {
3894 if(apIndex == 0) //private_wifi for 2.4G
3895 {
3896 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3897 }
3898 else if(apIndex == 1) //private_wifi for 5G
3899 {
3900 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3901 }
3902 else if(apIndex == 4) //public_wifi for 2.4G
3903 {
3904 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3905 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3906 {
3907 return RETURN_ERR;
3908 }
3909 if(buf[0] == '#')
3910 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3911 else
3912 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3913 }
3914 else if(apIndex == 5) //public_wifi for 5G
3915 {
3916 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3917 }
3918
3919 GetIfacestatus(interface_name, interface_status);
3920
3921 if(0 != strcmp(interface_status, "1"))
3922 return RETURN_ERR;
3923
3924 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3925 system(cmd);
3926
3927 fp = fopen("/tmp/SSID_Stats.txt", "r");
3928 if(fp == NULL)
3929 {
3930 printf("/tmp/SSID_Stats.txt not exists \n");
3931 return RETURN_ERR;
3932 }
3933 fclose(fp);
3934
3935 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3936 File_Reading(buf, Value);
3937 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
3938
3939 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3940 File_Reading(buf, Value);
3941 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
3942
3943 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3944 File_Reading(buf, Value);
3945 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
3946
3947 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3948 File_Reading(buf, Value);
3949 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
3950 }
3951
3952 output_struct->wifi_UnicastPacketsSent = 0;
3953 output_struct->wifi_UnicastPacketsReceived = 0;
3954 output_struct->wifi_MulticastPacketsSent = 0;
3955 output_struct->wifi_MulticastPacketsReceived = 0;
3956 output_struct->wifi_BroadcastPacketsSent = 0;
3957 output_struct->wifi_BroadcastPacketsRecevied = 0;
3958 output_struct->wifi_UnknownPacketsReceived = 0;
3959
3960 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3961 return RETURN_OK;
3962}
3963
3964INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
3965{
3966 INT status = RETURN_ERR;
3967
3968 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3969 //Below values should get updated from hal
3970 output_struct->wifi_RetransCount=0;
3971 output_struct->wifi_FailedRetransCount=0;
3972 output_struct->wifi_RetryCount=0;
3973 output_struct->wifi_MultipleRetryCount=0;
3974 output_struct->wifi_ACKFailureCount=0;
3975 output_struct->wifi_AggregatedPacketCount=0;
3976
3977 status = RETURN_OK;
3978 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3979
3980 return status;
3981}
3982
3983INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
3984{
3985 INT status = RETURN_ERR;
3986 UINT index;
3987 wifi_neighbor_ap_t *pt=NULL;
3988
3989 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3990 *output_array_size=2;
3991 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
3992 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
3993 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
3994 strcpy(pt->ap_Radio,"");
3995 strcpy(pt->ap_SSID,"");
3996 strcpy(pt->ap_BSSID,"");
3997 strcpy(pt->ap_Mode,"");
3998 pt->ap_Channel=1;
3999 pt->ap_SignalStrength=0;
4000 strcpy(pt->ap_SecurityModeEnabled,"");
4001 strcpy(pt->ap_EncryptionMode,"");
4002 strcpy(pt->ap_OperatingFrequencyBand,"");
4003 strcpy(pt->ap_SupportedStandards,"");
4004 strcpy(pt->ap_OperatingStandards,"");
4005 strcpy(pt->ap_OperatingChannelBandwidth,"");
4006 pt->ap_BeaconPeriod=1;
4007 pt->ap_Noise=0;
4008 strcpy(pt->ap_BasicDataTransferRates,"");
4009 strcpy(pt->ap_SupportedDataTransferRates,"");
4010 pt->ap_DTIMPeriod=1;
4011 pt->ap_ChannelUtilization = 1;
4012 }
4013
4014 status = RETURN_OK;
4015 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4016
4017 return status;
4018}
4019
4020//----------------- AP HAL -------------------------------
4021
4022//>> Deprecated: used for old RDKB code.
4023INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4024{
4025 if (NULL == output_ulong || NULL == output_struct)
4026 return RETURN_ERR;
4027 *output_ulong = 0;
4028 *output_struct = NULL;
4029 return RETURN_OK;
4030}
4031
4032#ifdef HAL_NETLINK_IMPL
4033static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4034 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4035 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4036 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4037 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4038 char mac_addr[20];
4039 static int count=0;
4040 int rate=0;
4041
4042 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4043
4044 nla_parse(tb,
4045 NL80211_ATTR_MAX,
4046 genlmsg_attrdata(gnlh, 0),
4047 genlmsg_attrlen(gnlh, 0),
4048 NULL);
4049
4050 if(!tb[NL80211_ATTR_STA_INFO]) {
4051 fprintf(stderr, "sta stats missing!\n");
4052 return NL_SKIP;
4053 }
4054
4055
4056 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4057 fprintf(stderr, "failed to parse nested attributes!\n");
4058 return NL_SKIP;
4059 }
4060
4061 //devIndex starts from 1
4062 if( ++count == out->wifi_devIndex )
4063 {
4064 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4065 //Getting the mac addrress
4066 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4067
4068 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4069 fprintf(stderr, "failed to parse nested rate attributes!");
4070 return NL_SKIP;
4071 }
4072
4073 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4074 if(rinfo[NL80211_RATE_INFO_BITRATE])
4075 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4076 out->wifi_devTxRate = rate/10;
4077 }
4078
4079 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4080 fprintf(stderr, "failed to parse nested rate attributes!");
4081 return NL_SKIP;
4082 }
4083
4084 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4085 if(rinfo[NL80211_RATE_INFO_BITRATE])
4086 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4087 out->wifi_devRxRate = rate/10;
4088 }
4089 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4090 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4091
4092 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4093 count = 0; //starts the count for next cycle
4094 return NL_STOP;
4095 }
4096
4097 return NL_SKIP;
4098
4099}
4100#endif
4101
4102INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4103{
4104#ifdef HAL_NETLINK_IMPL
4105 Netlink nl;
4106 char if_name[10];
4107
4108 wifi_device_info_t info;
4109 info.wifi_devIndex = devIndex;
4110
4111 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4112
4113 nl.id = initSock80211(&nl);
4114
4115 if (nl.id < 0) {
4116 fprintf(stderr, "Error initializing netlink \n");
4117 return -1;
4118 }
4119
4120 struct nl_msg* msg = nlmsg_alloc();
4121
4122 if (!msg) {
4123 fprintf(stderr, "Failed to allocate netlink message.\n");
4124 nlfree(&nl);
4125 return -2;
4126 }
4127
4128 genlmsg_put(msg,
4129 NL_AUTO_PORT,
4130 NL_AUTO_SEQ,
4131 nl.id,
4132 0,
4133 NLM_F_DUMP,
4134 NL80211_CMD_GET_STATION,
4135 0);
4136
4137 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4138 nl_send_auto(nl.socket, msg);
4139 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4140 nl_recvmsgs(nl.socket, nl.cb);
4141 nlmsg_free(msg);
4142 nlfree(&nl);
4143
4144 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4145 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4146 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4147 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4148 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4149 return RETURN_OK;
4150#else
4151 //iw utility to retrieve station information
4152#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4153#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4154#define MACFILE "/tmp/wifi_AssoMac.txt"
4155#define TXRATEFILE "/tmp/wifi_txrate.txt"
4156#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4157 FILE *file = NULL;
4158 char if_name[10] = {'\0'};
4159 char pipeCmd[256] = {'\0'};
4160 char line[256];
4161 int count,device = 0;
4162
4163 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4164
4165 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4166 file = popen(pipeCmd, "r");
4167
4168 if(file == NULL)
4169 return RETURN_ERR; //popen failed
4170
4171 fgets(line, sizeof line, file);
4172 device = atoi(line);
4173 pclose(file);
4174
4175 if(device == 0)
4176 return RETURN_ERR; //No devices are connected
4177
4178 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4179 system(pipeCmd);
4180
4181 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4182
4183 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4184
4185 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4186
4187 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4188
4189 //devIndex starts from 1, ++count
4190 if((file = fopen(SIGNALFILE, "r")) != NULL )
4191 {
4192 for(count =0;fgets(line, sizeof line, file) != NULL;)
4193 {
4194 if (++count == devIndex)
4195 {
4196 output_struct->wifi_devSignalStrength = atoi(line);
4197 break;
4198 }
4199 }
4200 fclose(file);
4201 }
4202 else
4203 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4204
4205 if((file = fopen(MACFILE, "r")) != NULL )
4206 {
4207 for(count =0;fgets(line, sizeof line, file) != NULL;)
4208 {
4209 if (++count == devIndex)
4210 {
4211 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]);
4212 break;
4213 }
4214 }
4215 fclose(file);
4216 }
4217 else
4218 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4219
4220 if((file = fopen(TXRATEFILE, "r")) != NULL )
4221 {
4222 for(count =0;fgets(line, sizeof line, file) != NULL;)
4223 {
4224 if (++count == devIndex)
4225 {
4226 output_struct->wifi_devTxRate = atoi(line);
4227 break;
4228 }
4229 }
4230 fclose(file);
4231 }
4232 else
4233 fprintf(stderr,"fopen wifi_txrate.txt failed");
4234
4235 if((file = fopen(RXRATEFILE, "r")) != NULL)
4236 {
4237 for(count =0;fgets(line, sizeof line, file) != NULL;)
4238 {
4239 if (++count == devIndex)
4240 {
4241 output_struct->wifi_devRxRate = atoi(line);
4242 break;
4243 }
4244 }
4245 fclose(file);
4246 }
4247 else
4248 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4249
4250 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4251
4252 return RETURN_OK;
4253#endif
4254}
4255
4256INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4257{
4258 if (NULL == device)
4259 return RETURN_ERR;
4260 return RETURN_OK;
4261}
4262//<<
4263
4264
4265//--------------wifi_ap_hal-----------------------------
4266//enables CTS protection for the radio used by this AP
4267INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4268{
4269 //save config and Apply instantly
4270 return RETURN_ERR;
4271}
4272
4273// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4274INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4275{
developer463d39a2022-09-13 15:32:51 +08004276 char config_file[64] = {'\0'};
4277 char buf[64] = {'\0'};
4278 struct params list;
4279
4280 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4281 list.name = "ht_coex";
4282 snprintf(buf, sizeof(buf), "%d", enable);
4283 list.value = buf;
4284
4285 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4286 wifi_hostapdWrite(config_file, &list, 1);
4287 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4288
4289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4290
4291 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004292}
4293
4294//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4295INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4296{
developerea4bcce2022-09-13 15:26:13 +08004297 char config_file[MAX_BUF_SIZE] = {'\0'};
4298 char buf[MAX_BUF_SIZE] = {'\0'};
4299 struct params list;
4300
4301 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4302 if (threshold < 256 || threshold > 2346 )
4303 return RETURN_ERR;
4304 list.name = "fragm_threshold";
4305 snprintf(buf, sizeof(buf), "%d", threshold);
4306 list.value = buf;
4307
4308 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4309 wifi_hostapdWrite(config_file, &list, 1);
4310 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004311
developerea4bcce2022-09-13 15:26:13 +08004312 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004313
4314 return RETURN_OK;
4315}
4316
4317// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4318INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4319{
developer51a927d2022-09-13 15:42:22 +08004320 char config_file[64] = {'\0'};
4321 char cmd[128] = {'\0'};
4322 char buf[64] = {'\0'};
4323 char stbc_config[16] = {'\0'};
4324 wifi_band band;
4325 int iterator = 0;
4326 BOOL current_stbc = FALSE;
4327
4328 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4329
4330 band = wifi_index_to_band(radioIndex);
4331 if (band == band_invalid)
4332 return RETURN_ERR;
4333
4334 if (band == band_2_4)
4335 iterator = 1;
4336 else if (band == band_5)
4337 iterator = 2;
4338 else
4339 return RETURN_OK;
4340
4341 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4342
4343 // set ht and vht config
4344 for (int i = 0; i < iterator; i++) {
4345 memset(stbc_config, 0, sizeof(stbc_config));
4346 memset(cmd, 0, sizeof(cmd));
4347 memset(buf, 0, sizeof(buf));
4348 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4349 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4350 _syscmd(cmd, buf, sizeof(buf));
4351 if (strlen(buf) != 0)
4352 current_stbc = TRUE;
4353 if (current_stbc == STBC_Enable)
4354 continue;
4355
4356 if (STBC_Enable == TRUE) {
4357 // Append the STBC flags in capab config
4358 memset(cmd, 0, sizeof(cmd));
4359 if (i == 0)
4360 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4361 else
4362 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4363 _syscmd(cmd, buf, sizeof(buf));
4364 } else if (STBC_Enable == FALSE) {
4365 // Remove the STBC flags and remain other flags in capab
4366 memset(cmd, 0, sizeof(cmd));
4367 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4368 _syscmd(cmd, buf, sizeof(buf));
4369 memset(cmd, 0, sizeof(cmd));
4370 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4371 _syscmd(cmd, buf, sizeof(buf));
4372 }
4373 }
4374
4375 wifi_reloadAp(radioIndex);
4376
4377 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4378 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004379}
4380
4381// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4382INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4383{
developer54e6b9f2022-09-28 14:41:20 +08004384 char AMSDU_file_path[64] = {0};
4385
4386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4387
4388 if(output_bool == NULL)
4389 return RETURN_ERR;
4390
4391 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4392
4393 if (access(AMSDU_file_path, F_OK) == 0)
4394 *output_bool = TRUE;
4395 else
4396 *output_bool = FALSE;
4397
4398 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4399 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004400}
4401
4402// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4403INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4404{
developer54e6b9f2022-09-28 14:41:20 +08004405 char cmd[64]={0};
4406 char buf[64]={0};
4407 char AMSDU_file_path[64] = {0};
4408
4409 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4410
4411 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4412 _syscmd(cmd, buf, sizeof(buf));
4413
4414 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4415 memset(cmd, 0, sizeof(cmd));
4416 if (amsduEnable == TRUE)
4417 sprintf(cmd, "touch %s", AMSDU_file_path);
4418 else
4419 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4420 _syscmd(cmd, buf, sizeof(buf));
4421
4422 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4423 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004424}
4425
4426//P2 // outputs the number of Tx streams
4427INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4428{
developer2de97692022-09-26 14:00:03 +08004429 char buf[8] = {0};
4430 char cmd[128] = {0};
4431
4432 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4433
4434 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4435 _syscmd(cmd, buf, sizeof(buf));
4436
4437 // if there is no record, output the max number of spatial streams
4438 if (strlen(buf) == 0) {
4439 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4440 _syscmd(cmd, buf, sizeof(buf));
4441 }
4442
4443 *output_int = (INT)strtol(buf, NULL, 10);
4444
4445 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4446
4447 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004448}
4449
4450//P2 // sets the number of Tx streams to an enviornment variable
4451INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4452{
developer2de97692022-09-26 14:00:03 +08004453 char cmd[128] = {0};
4454 char buf[128] = {0};
4455 char chain_mask_file[128] = {0};
4456 FILE *f = NULL;
4457
4458 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4459
4460 if (numStreams == 0) {
4461 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4462 return RETURN_ERR;
4463 }
4464 wifi_setRadioEnable(radioIndex, FALSE);
4465 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4466 _syscmd(cmd, buf, sizeof(buf));
4467
4468 if (strlen(buf) > 0) {
4469 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4470 return RETURN_ERR;
4471 }
4472 wifi_setRadioEnable(radioIndex, TRUE);
4473
4474 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4475 f = fopen(chain_mask_file, "w");
4476 if (f == NULL) {
4477 fprintf(stderr, "%s: fopen failed.\n", __func__);
4478 return RETURN_ERR;
4479 }
4480 fprintf(f, "%d", numStreams);
4481 fclose(f);
4482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4483 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004484}
4485
4486//P2 // outputs the number of Rx streams
4487INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4488{
developer2de97692022-09-26 14:00:03 +08004489 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4490 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4491 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004492 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004493 }
4494 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004495 return RETURN_OK;
4496}
4497
4498//P2 // sets the number of Rx streams to an enviornment variable
4499INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4500{
developer2de97692022-09-26 14:00:03 +08004501 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4502 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4503 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4504 return RETURN_ERR;
4505 }
4506 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004507 return RETURN_ERR;
4508}
4509
4510//Get radio RDG enable setting
4511INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4512{
4513 if (NULL == output_bool)
4514 return RETURN_ERR;
4515 *output_bool = TRUE;
4516 return RETURN_OK;
4517}
4518
4519//Get radio RDG enable setting
4520INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4521{
4522 if (NULL == output_bool)
4523 return RETURN_ERR;
4524 *output_bool = TRUE;
4525 return RETURN_OK;
4526}
4527
4528//Set radio RDG enable setting
4529INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4530{
4531 return RETURN_ERR;
4532}
4533
4534//Get radio ADDBA enable setting
4535INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4536{
4537 if (NULL == output_bool)
4538 return RETURN_ERR;
4539 *output_bool = TRUE;
4540 return RETURN_OK;
4541}
4542
4543//Set radio ADDBA enable setting
4544INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4545{
4546 return RETURN_ERR;
4547}
4548
4549//Get radio auto block ack enable setting
4550INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4551{
4552 if (NULL == output_bool)
4553 return RETURN_ERR;
4554 *output_bool = TRUE;
4555 return RETURN_OK;
4556}
4557
4558//Set radio auto block ack enable setting
4559INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4560{
4561 return RETURN_ERR;
4562}
4563
4564//Get radio 11n pure mode enable support
4565INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4566{
4567 if (NULL == output_bool)
4568 return RETURN_ERR;
4569 *output_bool = TRUE;
4570 return RETURN_OK;
4571}
4572
4573//Get radio 11n pure mode enable setting
4574INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4575{
4576 if (NULL == output_bool)
4577 return RETURN_ERR;
4578 *output_bool = TRUE;
4579 return RETURN_OK;
4580}
4581
4582//Set radio 11n pure mode enable setting
4583INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4584{
4585 return RETURN_ERR;
4586}
4587
4588//Get radio IGMP snooping enable setting
4589INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4590{
developer81bf2ed2022-09-13 15:31:14 +08004591 char cmd[128]={0};
4592 char buf[4]={0};
4593 bool bridge = FALSE, mac80211 = FALSE;
4594 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4595
4596 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004597 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004598
4599 *output_bool = FALSE;
4600
4601 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4602 _syscmd(cmd, buf, sizeof(buf));
4603 if (strncmp(buf, "1", 1) == 0)
4604 bridge = TRUE;
4605
4606 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4607 _syscmd(cmd, buf, sizeof(buf));
4608 if (strncmp(buf, "1", 1) == 0)
4609 mac80211 = TRUE;
4610
4611 if (bridge && mac80211)
4612 *output_bool = TRUE;
4613
4614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004615 return RETURN_OK;
4616}
4617
4618//Set radio IGMP snooping enable setting
4619INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4620{
developer81bf2ed2022-09-13 15:31:14 +08004621 char cmd[128]={0};
4622 char buf[4]={0};
4623
4624 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4625
4626 // bridge
4627 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4628 _syscmd(cmd, buf, sizeof(buf));
4629
4630 // mac80211
4631 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4632 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4633 _syscmd(cmd, buf, sizeof(buf));
4634 }
4635 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4636 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004637}
4638
4639//Get the Reset count of radio
4640INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4641{
4642 if (NULL == output_int)
4643 return RETURN_ERR;
4644 *output_int = (radioIndex==0)? 1: 3;
4645
4646 return RETURN_OK;
4647}
4648
4649
4650//---------------------------------------------------------------------------------------------------
4651//
4652// Additional Wifi AP level APIs used for Access Point devices
4653//
4654//---------------------------------------------------------------------------------------------------
4655
4656// creates a new ap and pushes these parameters to the hardware
4657INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4658{
4659 char buf[1024];
4660 char cmd[128];
4661
4662 if (NULL == essid)
4663 return RETURN_ERR;
4664
4665 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4666 _syscmd(cmd, buf, sizeof(buf));
4667
4668 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4669 _syscmd(cmd, buf, sizeof(buf));
4670
4671 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4672
4673 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4674 _syscmd(cmd, buf, sizeof(buf));
4675
4676 return RETURN_OK;
4677}
4678
4679// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4680INT wifi_deleteAp(INT apIndex)
4681{
4682 char buf[1024];
4683 char cmd[128];
4684
4685 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4686 _syscmd(cmd, buf, sizeof(buf));
4687
4688 wifi_removeApSecVaribles(apIndex);
4689
4690 return RETURN_OK;
4691}
4692
4693// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4694INT wifi_getApName(INT apIndex, CHAR *output_string)
4695{
4696 if(NULL == output_string)
4697 return RETURN_ERR;
4698
4699 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4700 return RETURN_OK;
4701}
4702
4703// Outputs the index number in that corresponds to the SSID string
4704INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4705{
4706 CHAR *pos = NULL;
4707
4708 *output_int = -1;
4709 pos = strstr(inputSsidString, AP_PREFIX);
4710 if(pos)
4711 {
4712 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4713 return RETURN_OK;
4714 }
4715 return RETURN_ERR;
4716}
4717
4718INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4719{
4720 return wifi_getIndexFromName(inputSsidString, output_int);
4721}
4722
4723// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4724INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4725{
4726 char buf[MAX_BUF_SIZE] = {0};
4727 char cmd[MAX_CMD_SIZE] = {0};
4728 char config_file[MAX_BUF_SIZE] = {0};
4729
4730 if(NULL == output_string)
4731 return RETURN_ERR;
4732
4733 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4734 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4735 if((strcmp(buf,"3")==0))
4736 snprintf(output_string, 32, "WPAand11i");
4737 else if((strcmp(buf,"2")==0))
4738 snprintf(output_string, 32, "11i");
4739 else if((strcmp(buf,"1")==0))
4740 snprintf(output_string, 32, "WPA");
4741 else
4742 snprintf(output_string, 32, "None");
4743
4744 return RETURN_OK;
4745}
4746
4747// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4748INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4749{
4750 char config_file[MAX_BUF_SIZE] = {0};
4751 struct params list;
4752
4753 if (NULL == beaconTypeString)
4754 return RETURN_ERR;
4755 list.name = "wpa";
4756 list.value = "0";
4757
4758 if((strcmp(beaconTypeString,"WPAand11i")==0))
4759 list.value="3";
4760 else if((strcmp(beaconTypeString,"11i")==0))
4761 list.value="2";
4762 else if((strcmp(beaconTypeString,"WPA")==0))
4763 list.value="1";
4764
4765 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4766 wifi_hostapdWrite(config_file, &list, 1);
4767 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4768 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4769 return RETURN_OK;
4770}
4771
4772// sets the beacon interval on the hardware for this AP
4773INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4774{
developer5f222492022-09-13 15:21:52 +08004775 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4776 struct params params={'\0'};
4777 char buf[MAX_BUF_SIZE] = {'\0'};
4778 char config_file[MAX_BUF_SIZE] = {'\0'};
4779
4780 params.name = "beacon_int";
4781 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4782 params.value = buf;
4783
4784 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4785 wifi_hostapdWrite(config_file, &params, 1);
4786
4787 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4788 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4789 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004790}
4791
4792INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4793{
4794 //save config and apply instantly
4795 return RETURN_ERR;
4796}
4797
4798// Get the packet size threshold supported.
4799INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4800{
4801 //save config and apply instantly
4802 if (NULL == output_bool)
4803 return RETURN_ERR;
4804 *output_bool = FALSE;
4805 return RETURN_OK;
4806}
4807
4808// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4809INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4810{
4811 char cmd[128];
4812 char buf[512];
4813
4814 if (threshold > 0)
4815 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4816 else
4817 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4818 _syscmd(cmd, buf, sizeof(buf));
4819
4820 return RETURN_OK;
4821}
4822
4823// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4824INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4825{
4826 if (NULL == output_string)
4827 return RETURN_ERR;
4828 snprintf(output_string, 32, "TKIPandAESEncryption");
4829 return RETURN_OK;
4830
4831}
4832
4833// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4834INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4835{
4836 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4837 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4838
4839 if(NULL == output_string)
4840 return RETURN_ERR;
4841
4842 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4843 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4844
4845 if(strcmp(buf,"0")==0)
4846 {
4847 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4848 snprintf(output_string, 32, "None");
4849 return RETURN_OK;
4850 }
4851 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4852 param_name = "rsn_pairwise";
4853 else if((strcmp(buf,"1")==0))
4854 param_name = "wpa_pairwise";
4855 else
4856 return RETURN_ERR;
4857 memset(output_string,'\0',32);
4858 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4859 wifi_hostapdRead(config_file,param_name,output_string,32);
4860 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4861
4862 if(strcmp(output_string,"TKIP") == 0)
4863 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4864 else if(strcmp(output_string,"CCMP") == 0)
4865 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4866 else if(strcmp(output_string,"TKIP CCMP") == 0)
4867 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4868
4869 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4870 return RETURN_OK;
4871}
4872
4873// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4874INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4875{
4876 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4877 struct params params={'\0'};
4878 char output_string[32];
4879 char config_file[MAX_BUF_SIZE] = {0};
4880
4881 memset(output_string,'\0',32);
4882 wifi_getApWpaEncryptionMode(apIndex,output_string);
4883
4884 if(strcmp(encMode, "TKIPEncryption") == 0)
4885 params.value = "TKIP";
4886 else if(strcmp(encMode,"AESEncryption") == 0)
4887 params.value = "CCMP";
4888 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
4889 params.value = "TKIP CCMP";
4890
4891 if((strcmp(output_string,"WPAand11i")==0))
4892 {
4893 params.name = "wpa_pairwise";
4894 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4895 wifi_hostapdWrite(config_file, &params, 1);
4896 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4897
4898 params.name,"rsn_pairwise";
4899 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4900 wifi_hostapdWrite(config_file, &params, 1);
4901 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4902
4903 return RETURN_OK;
4904 }
4905 else if((strcmp(output_string,"11i")==0))
4906 {
4907 params.name = "rsn_pairwise";
4908 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4909 wifi_hostapdWrite(config_file, &params, 1);
4910 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4911 return RETURN_OK;
4912 }
4913 else if((strcmp(output_string,"WPA")==0))
4914 {
4915 params.name = "wpa_pairwise";
4916 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4917 wifi_hostapdWrite(config_file, &params, 1);
4918 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4919 return RETURN_OK;
4920 }
4921
4922 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4923 return RETURN_OK;
4924}
4925
4926// deletes internal security varable settings for this ap
4927INT wifi_removeApSecVaribles(INT apIndex)
4928{
4929 //TODO: remove the entry in hostapd config file
4930 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4931 //_syscmd(cmd, buf, sizeof(buf));
4932
4933 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
4934 //_syscmd(cmd, buf, sizeof(buf));
4935 return RETURN_ERR;
4936}
4937
4938// changes the hardware settings to disable encryption on this ap
4939INT wifi_disableApEncryption(INT apIndex)
4940{
4941 //Apply instantly
4942 return RETURN_ERR;
4943}
4944
4945// set the authorization mode on this ap
4946// mode mapping as: 1: open, 2: shared, 4:auto
4947INT wifi_setApAuthMode(INT apIndex, INT mode)
4948{
developeraf95c502022-09-13 16:18:22 +08004949 struct params params={0};
4950 char config_file[64] = {0};
4951 int ret;
4952
4953 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4954
4955 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
4956 params.name = "auth_algs";
4957
4958 if (mode & 1 && mode & 2)
4959 params.value = "3";
4960 else if (mode & 2)
4961 params.value = "2";
4962 else if (mode & 1)
4963 params.value = "1";
4964 else
4965 params.value = "0";
4966
4967 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4968 wifi_hostapdWrite(config_file, &params, 1);
4969 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4970 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4971
4972 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004973}
4974
4975// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
4976INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
4977{
4978 //save to wifi config, and wait for wifi restart to apply
4979 struct params params={'\0'};
4980 char config_file[MAX_BUF_SIZE] = {0};
4981 int ret;
4982
4983 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4984 if(authMode == NULL)
4985 return RETURN_ERR;
4986
4987 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
4988 params.name = "wpa_key_mgmt";
4989
4990 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
4991 params.value = "WPA-PSK";
4992 else if(strcmp(authMode,"EAPAuthentication") == 0)
4993 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08004994 else if (strcmp(authMode, "SAEAuthentication") == 0)
4995 params.value = "SAE";
4996 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
4997 params.value = "WPA-EAP-SUITE-B-192";
developer06a01d92022-09-07 16:32:39 +08004998 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
4999 return RETURN_OK; //This is taken careof in beaconType
5000
5001 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5002 ret=wifi_hostapdWrite(config_file,&params,1);
5003 if(!ret)
5004 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5006
5007 return ret;
5008}
5009
5010// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5011INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5012{
5013 //save to wifi config, and wait for wifi restart to apply
5014 char BeaconType[50] = {0};
5015 char config_file[MAX_BUF_SIZE] = {0};
5016
5017 *authMode = 0;
5018 wifi_getApBeaconType(apIndex,BeaconType);
5019 printf("%s____%s \n",__FUNCTION__,BeaconType);
5020
5021 if(strcmp(BeaconType,"None") == 0)
5022 strcpy(authMode,"None");
5023 else
5024 {
5025 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5026 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5027 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5028 if(strcmp(authMode,"WPA-PSK") == 0)
5029 strcpy(authMode,"SharedAuthentication");
5030 else if(strcmp(authMode,"WPA-EAP") == 0)
5031 strcpy(authMode,"EAPAuthentication");
5032 }
5033
5034 return RETURN_OK;
5035}
5036
5037// Outputs the number of stations associated per AP
5038INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5039{
5040 char cmd[128]={0};
5041 char buf[128]={0};
5042 BOOL status = false;
5043
5044 if(apIndex > MAX_APS)
5045 return RETURN_ERR;
5046
5047 wifi_getApEnable(apIndex,&status);
5048 if (!status)
5049 return RETURN_OK;
5050
5051 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5052 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5053 _syscmd(cmd, buf, sizeof(buf));
5054 sscanf(buf,"%lu", output_ulong);
5055
5056 return RETURN_OK;
5057}
5058
5059// manually removes any active wi-fi association with the device specified on this ap
5060INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5061{
5062 char buf[126]={'\0'};
5063
5064 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5065 system(buf);
5066
5067 return RETURN_OK;
5068}
5069
5070// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5071INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5072{
5073 if(NULL == output_int)
5074 return RETURN_ERR;
5075 *output_int = apIndex%2;
5076 return RETURN_OK;
5077}
5078
5079// sets the radio index for the specific ap
5080INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5081{
5082 //set to config only and wait for wifi reset to apply settings
5083 return RETURN_ERR;
5084}
5085
5086// Get the ACL MAC list per AP
5087INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5088{
5089 char cmd[MAX_CMD_SIZE]={'\0'};
5090 int ret = 0;
5091
5092 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5093 ret = _syscmd(cmd,macArray,buf_size);
5094 if (ret != 0)
5095 return RETURN_ERR;
5096
5097 return RETURN_OK;
5098}
5099
developere6aafda2022-09-13 14:59:28 +08005100INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5101{
5102 char cmd[MAX_CMD_SIZE]={'\0'};
5103 int ret = 0;
5104
5105 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5106 ret = _syscmd(cmd,macArray,buf_size);
5107 if (ret != 0)
5108 return RETURN_ERR;
5109
5110 return RETURN_OK;
5111}
5112
5113
developer06a01d92022-09-07 16:32:39 +08005114// Get the list of stations associated per AP
5115INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5116{
5117 char cmd[128];
5118
5119 if(apIndex > 3) //Currently supporting apIndex upto 3
5120 return RETURN_ERR;
5121 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5122 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5123 _syscmd(cmd, macArray, buf_size);
5124
5125 return RETURN_OK;
5126}
5127
5128// adds the mac address to the filter list
5129//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5130INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5131{
5132 char cmd[MAX_CMD_SIZE]={'\0'};
5133 char buf[MAX_BUF_SIZE]={'\0'};
5134
5135#if 0
5136 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5137 if(_syscmd(cmd,buf,sizeof(buf)))
5138 return RETURN_ERR;
5139#endif
5140 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5141 if(_syscmd(cmd,buf,sizeof(buf)))
5142 return RETURN_ERR;
5143
5144 return RETURN_OK;
5145}
5146
5147// deletes the mac address from the filter list
5148//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5149INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5150{
5151 char cmd[MAX_CMD_SIZE]={'\0'};
5152 char buf[MAX_BUF_SIZE]={'\0'};
5153
5154#if 0
5155 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5156 if(_syscmd(cmd,buf,sizeof(buf)))
5157 return RETURN_ERR;
5158
5159#endif
5160 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5161 if(_syscmd(cmd,buf,sizeof(buf)))
5162 return RETURN_ERR;
5163
5164 return RETURN_OK;
5165}
5166
5167// outputs the number of devices in the filter list
5168INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5169{
developere6aafda2022-09-13 14:59:28 +08005170 char cmd[MAX_BUF_SIZE]={0};
5171 char buf[MAX_CMD_SIZE]={0};
5172
5173 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5174 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005175 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005176
5177 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5178 _syscmd(cmd, buf, sizeof(buf));
5179
5180 *output_uint = atoi(buf);
5181
5182 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5183 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005184}
5185
5186INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5187{
5188 char cmd[128]={'\0'};
5189 char buf[128]={'\0'};
5190
5191 if(strcmp(action,"DENY")==0)
5192 {
5193 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5194 system(buf);
5195 return RETURN_OK;
5196 }
5197
5198 if(strcmp(action,"ALLOW")==0)
5199 {
5200 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5201 system(buf);
5202 return RETURN_OK;
5203 }
5204
5205 return RETURN_ERR;
5206
5207}
5208
5209// enable kick for devices on acl black list
5210INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5211{
5212 char aclArray[512] = {0}, *acl = NULL;
5213 char assocArray[512] = {0}, *asso = NULL;
5214
developere6aafda2022-09-13 14:59:28 +08005215 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005216 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5217
5218 // if there are no devices connected there is nothing to do
5219 if (strlen(assocArray) < 17)
5220 return RETURN_OK;
5221
5222 if (enable == TRUE)
5223 {
5224 //kick off the MAC which is in ACL array (deny list)
5225 acl = strtok(aclArray, "\r\n");
5226 while (acl != NULL) {
5227 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5228 wifi_kickApAssociatedDevice(apIndex, acl);
5229
5230 acl = strtok(NULL, "\r\n");
5231 }
developere6aafda2022-09-13 14:59:28 +08005232 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005233 }
5234 else
5235 {
developere6aafda2022-09-13 14:59:28 +08005236 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005237 }
5238
5239#if 0
5240 //TODO: need to revisit below implementation
5241 char aclArray[512]={0}, *acl=NULL;
5242 char assocArray[512]={0}, *asso=NULL;
5243 char buf[256]={'\0'};
5244 char action[10]={'\0'};
5245 FILE *fr=NULL;
5246 char interface[10]={'\0'};
5247 char config_file[MAX_BUF_SIZE] = {0};
5248
5249 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5250 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5251 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5252 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5253
5254 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5255 system(buf);
5256 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5257 system(buf);
5258 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5259 system(buf);
5260 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5261 system(buf);
5262 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5263 system(buf);
5264
5265 if ( enable == TRUE )
5266 {
5267 int device_count=0;
5268 strcpy(action,"DENY");
5269 //kick off the MAC which is in ACL array (deny list)
5270 acl = strtok (aclArray,",");
5271 while (acl != NULL) {
5272 if(strlen(acl)>=17)
5273 {
5274 apply_rules(apIndex, acl,action,interface);
5275 device_count++;
5276 //Register mac to be blocked ,in syscfg.db persistent storage
5277 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5278 system(buf);
5279 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5280 system(buf);
5281 system("syscfg commit");
5282
5283 wifi_kickApAssociatedDevice(apIndex, acl);
5284 }
5285 acl = strtok (NULL, ",");
5286 }
5287 }
5288 else
5289 {
5290 int device_count=0;
5291 char cmdmac[20]={'\0'};
5292 strcpy(action,"ALLOW");
5293 //kick off the MAC which is not in ACL array (allow list)
5294 acl = strtok (aclArray,",");
5295 while (acl != NULL) {
5296 if(strlen(acl)>=17)
5297 {
5298 apply_rules(apIndex, acl,action,interface);
5299 device_count++;
5300 //Register mac to be Allowed ,in syscfg.db persistent storage
5301 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5302 system(buf);
5303 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5304 system(buf);
5305 sprintf(cmdmac,"%s",acl);
5306 }
5307 acl = strtok (NULL, ",");
5308 }
5309 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5310 system(buf);
5311
5312 //Disconnect the mac which is not in ACL
5313 asso = strtok (assocArray,",");
5314 while (asso != NULL) {
5315 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5316 wifi_kickApAssociatedDevice(apIndex, asso);
5317 asso = strtok (NULL, ",");
5318 }
5319 }
5320#endif
5321 return RETURN_OK;
5322}
5323
5324INT wifi_setPreferPrivateConnection(BOOL enable)
5325{
5326 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5327 char buf[1024] = {0};
5328
5329 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5330 if(enable == TRUE)
5331 {
5332 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5333 sprintf(buf,"ifconfig %s down" ,interface_name);
5334 system(buf);
5335 memset(buf,0,sizeof(buf));
5336 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5337 sprintf(buf,"ifconfig %s down" ,interface_name);
5338 system(buf);
5339 }
5340 else
5341 {
5342 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5343 if(strcmp(ssid_cur_value,"1") == 0)
5344 wifi_RestartPrivateWifi_5G();
5345 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5346 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5347 if(strcmp(ssid_cur_value,"1") == 0)
5348 wifi_RestartHostapd_2G();
5349 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5350 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5351 if(strcmp(ssid_cur_value,"1") == 0)
5352 wifi_RestartHostapd_5G();
5353 }
5354 return RETURN_OK;
5355}
5356
5357// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5358INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5359{
5360 int items = 1;
5361 struct params list[2];
5362 char buf[MAX_BUF_SIZE] = {0};
5363 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005364 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005365
5366 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005367
developer10adcc12022-09-13 14:39:17 +08005368 if (filterMode == 0) {
5369 sprintf(buf, "%d", 0);
5370 list[0].value = buf;
5371
5372 char cmd[128], rtn[128];
5373 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5374 _syscmd(cmd, rtn, sizeof(rtn));
5375 memset(cmd,0,sizeof(cmd));
5376 // Delete deny_mac_file in hostapd configuration
5377 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5378 _syscmd(cmd, rtn, sizeof(rtn));
5379 }
5380 else if (filterMode == 1) {
5381 sprintf(buf, "%d", filterMode);
5382 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005383 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5384 list[1].name = "accept_mac_file";
5385 list[1].value = acl_file;
5386 items = 2;
developer10adcc12022-09-13 14:39:17 +08005387 } else if (filterMode == 2) {
5388 //TODO: deny_mac_file
5389 sprintf(buf, "%d", 0);
5390 list[0].value = buf;
5391 list[1].name = "deny_mac_file";
5392 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5393 list[1].value = deny_file;
5394 items = 2;
5395 } else {
5396 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005397 }
developer10adcc12022-09-13 14:39:17 +08005398
developer06a01d92022-09-07 16:32:39 +08005399 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5400 wifi_hostapdWrite(config_file, list, items);
5401
5402 return RETURN_OK;
5403
5404#if 0
5405 if(apIndex==0 || apIndex==1)
5406 {
5407 //set the filtermode
5408 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5409 system(buf);
5410 system("syscfg commit");
5411
5412 if(filterMode==0)
5413 {
5414 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5415 system(buf);
5416 return RETURN_OK;
5417 }
5418 }
5419 return RETURN_OK;
5420#endif
5421}
5422
5423// 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.
5424INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5425{
5426 return RETURN_ERR;
5427}
5428
5429// gets the vlan ID for this ap from an internal enviornment variable
5430INT wifi_getApVlanID(INT apIndex, INT *output_int)
5431{
5432 if(apIndex=0)
5433 {
5434 *output_int=100;
5435 return RETURN_OK;
5436 }
5437
5438 return RETURN_ERR;
5439}
5440
5441// sets the vlan ID for this ap to an internal enviornment variable
5442INT wifi_setApVlanID(INT apIndex, INT vlanId)
5443{
5444 //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)
5445 return RETURN_ERR;
5446}
5447
5448// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5449INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5450{
5451 snprintf(bridgeName, 32, "brlan0");
5452 snprintf(IP, 32, "10.0.0.1");
5453 snprintf(subnet, 32, "255.255.255.0");
5454
5455 return RETURN_OK;
5456}
5457
5458//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5459INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5460{
5461 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5462 return RETURN_ERR;
5463}
5464
5465// reset the vlan configuration for this ap
5466INT wifi_resetApVlanCfg(INT apIndex)
5467{
developerf5fef612022-09-20 19:38:26 +08005468 char original_config_file[64] = {0};
5469 char current_config_file[64] = {0};
5470 char buf[64] = {0};
5471 char cmd[64] = {0};
5472 char vlan_file[64] = {0};
5473 char vlan_tagged_interface[16] = {0};
5474 char vlan_bridge[16] = {0};
5475 char vlan_naming[16] = {0};
5476 struct params list[4] = {0};
5477 wifi_band band;
5478
5479 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5480
5481 band = wifi_index_to_band(apIndex);
5482 if (band == band_2_4)
5483 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5484 else if (band = band_5)
5485 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5486 else if (band = band_6)
5487 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5488
5489 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5490
5491 if (strlen(vlan_file) == 0)
5492 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005493
developerf5fef612022-09-20 19:38:26 +08005494 // The file should exist or this vap would not work.
5495 if (access(vlan_file, F_OK) != 0) {
5496 sprintf(cmd, "touch %s", vlan_file);
5497 _syscmd(cmd, buf, sizeof(buf));
5498 }
5499 list[0].name = "vlan_file";
5500 list[0].value = vlan_file;
5501
5502 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5503 list[1].name = "vlan_tagged_interface";
5504 list[1].value = vlan_tagged_interface;
5505
5506 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5507 list[2].name = "vlan_bridge";
5508 list[2].value = vlan_bridge;
5509
5510 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5511 list[3].name = "vlan_naming";
5512 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005513
developerf5fef612022-09-20 19:38:26 +08005514 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5515 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005516 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005517 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005518
developerf5fef612022-09-20 19:38:26 +08005519 // restart this ap
5520 wifi_setApEnable(apIndex, FALSE);
5521 wifi_setApEnable(apIndex, TRUE);
5522
5523 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5524
5525 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005526}
5527
5528// 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.
5529INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5530{
5531 return RETURN_ERR;
5532}
5533
5534// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5535INT wifi_startHostApd()
5536{
5537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5538 system("systemctl start hostapd.service");
5539 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5540 return RETURN_OK;
5541 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5542}
5543
5544// stops hostapd
5545INT wifi_stopHostApd()
5546{
5547 char cmd[128] = {0};
5548 char buf[128] = {0};
5549
5550 sprintf(cmd,"systemctl stop hostapd");
5551 _syscmd(cmd, buf, sizeof(buf));
5552
5553 return RETURN_OK;
5554}
5555
5556// restart hostapd dummy function
5557INT wifi_restartHostApd()
5558{
5559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5560 system("systemctl restart hostapd-global");
5561 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5562
5563 return RETURN_OK;
5564}
5565
5566static int align_hostapd_config(int index)
5567{
5568 ULONG lval;
5569 wifi_getRadioChannel(index%2, &lval);
5570 wifi_setRadioChannel(index%2, lval);
5571}
5572
5573// sets the AP enable status variable for the specified ap.
5574INT wifi_setApEnable(INT apIndex, BOOL enable)
5575{
5576 char config_file[MAX_BUF_SIZE] = {0};
5577 char cmd[MAX_CMD_SIZE] = {0};
5578 char buf[MAX_BUF_SIZE] = {0};
5579 BOOL status;
5580
5581 wifi_getApEnable(apIndex,&status);
5582 if (enable == status)
5583 return RETURN_OK;
5584
5585 if (enable == TRUE) {
5586 int radioIndex = apIndex % NUMBER_OF_RADIOS;
5587 align_hostapd_config(apIndex);
5588 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5589 //Hostapd will bring up this interface
5590 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5591 _syscmd(cmd, buf, sizeof(buf));
5592 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5593 _syscmd(cmd, buf, sizeof(buf));
5594 }
5595 else {
5596 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5597 _syscmd(cmd, buf, sizeof(buf));
5598 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5599 _syscmd(cmd, buf, sizeof(buf));
5600 }
5601 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5602 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5603 _syscmd(cmd, buf, sizeof(buf));
5604 //Wait for wifi up/down to apply
5605 return RETURN_OK;
5606}
5607
5608// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5609INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5610{
5611 char cmd[MAX_CMD_SIZE] = {'\0'};
5612 char buf[MAX_BUF_SIZE] = {'\0'};
5613
5614 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5615 return RETURN_ERR;
5616
5617 *output_bool = 0;
5618
5619 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5620 {
developer70490032022-09-13 15:45:20 +08005621 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005622 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5623 }
5624
5625 return RETURN_OK;
5626}
5627
5628// Outputs the AP "Enabled" "Disabled" status from driver
5629INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5630{
5631 char cmd[128] = {0};
5632 char buf[128] = {0};
5633 BOOL output_bool;
5634
5635 if ( NULL == output_string)
5636 return RETURN_ERR;
5637 wifi_getApEnable(apIndex,&output_bool);
5638
5639 if(output_bool == 1)
5640 snprintf(output_string, 32, "Up");
5641 else
5642 snprintf(output_string, 32, "Disable");
5643
5644 return RETURN_OK;
5645}
5646
5647//Indicates whether or not beacons include the SSID name.
5648// outputs a 1 if SSID on the AP is enabled, else outputs 0
5649INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5650{
5651 //get the running status
5652 char config_file[MAX_BUF_SIZE] = {0};
5653 char buf[16] = {0};
5654
5655 if (!output)
5656 return RETURN_ERR;
5657
5658 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5659 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5660 *output = (strncmp("0",buf,1) == 0);
5661
5662 return RETURN_OK;
5663}
5664
5665// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5666INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5667{
5668 //store the config, apply instantly
5669 char config_file[MAX_BUF_SIZE] = {0};
5670 struct params list;
5671
5672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5673 list.name = "ignore_broadcast_ssid";
5674 list.value = enable?"0":"1";
5675
5676 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5677 wifi_hostapdWrite(config_file, &list, 1);
5678 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5679 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005680 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5682
5683 return RETURN_OK;
5684}
5685
5686//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5687INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5688{
5689 //get the running status
5690 if(!output_uint)
5691 return RETURN_ERR;
5692 *output_uint=16;
5693 return RETURN_OK;
5694}
5695
5696INT wifi_setApRetryLimit(INT apIndex, UINT number)
5697{
5698 //apply instantly
5699 return RETURN_ERR;
5700}
5701
5702//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5703INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5704{
5705 if(!output)
5706 return RETURN_ERR;
5707 *output=TRUE;
5708 return RETURN_OK;
5709}
5710
5711//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5712INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5713{
5714 //get the running status from driver
5715 if(!output)
5716 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005717
5718 char config_file[MAX_BUF_SIZE] = {0};
5719 char buf[16] = {0};
5720
5721 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5722 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
5723 if (strncmp("1",buf,1) == 0)
5724 *output = TRUE;
5725 else
5726 *output = FALSE;
5727
developer06a01d92022-09-07 16:32:39 +08005728 return RETURN_OK;
5729}
5730
5731//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5732INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5733{
5734 //get the running status from driver
5735 if(!output)
5736 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005737
5738 char config_file[MAX_BUF_SIZE] = {0};
5739 char buf[16] = {0};
5740
5741 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5742 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5743 if (strncmp("1",buf,1) == 0)
5744 *output = TRUE;
5745 else
5746 *output = FALSE;
5747
developer06a01d92022-09-07 16:32:39 +08005748 return RETURN_OK;
5749}
5750
5751// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5752INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5753{
5754 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005755 char config_file[MAX_BUF_SIZE] = {0};
5756 struct params list;
5757
5758 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5759 list.name = "wmm_enabled";
5760 list.value = enable?"1":"0";
5761
5762 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5763 wifi_hostapdWrite(config_file, &list, 1);
5764 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5765 wifi_reloadAp(apIndex);
5766 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5767
5768 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005769}
5770
5771//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.
5772INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5773{
5774 //get the running status from driver
5775 if(!output)
5776 return RETURN_ERR;
5777 *output=TRUE;
5778 return RETURN_OK;
5779}
5780
5781// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5782INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5783{
5784 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005785 char config_file[MAX_BUF_SIZE] = {0};
5786 struct params list;
5787
5788 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5789 list.name = "uapsd_advertisement_enabled";
5790 list.value = enable?"1":"0";
5791
5792 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5793 wifi_hostapdWrite(config_file, &list, 1);
5794 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5795 wifi_reloadAp(apIndex);
5796 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5797
5798 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005799}
5800
5801// Sets the WMM ACK polity on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
5802INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5803{
5804 //save config and apply instantly.
5805 return RETURN_ERR;
5806}
5807
5808//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.
5809INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5810{
5811 //get the running status from driver
5812 if(!output_uint)
5813 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005814
5815 char output[16]={'\0'};
5816 char config_file[MAX_BUF_SIZE] = {0};
5817
5818 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5819 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5820 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5821 else {
5822 int device_num = atoi(output);
5823 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5824 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5825 return RETURN_ERR;
5826 }
5827 else {
5828 *output_uint = device_num;
5829 }
5830 }
5831
developer06a01d92022-09-07 16:32:39 +08005832 return RETURN_OK;
5833}
5834
5835INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5836{
5837 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005838 char str[MAX_BUF_SIZE]={'\0'};
5839 char cmd[MAX_CMD_SIZE]={'\0'};
5840 struct params params;
5841 char config_file[MAX_BUF_SIZE] = {0};
5842
5843 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5844 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5845 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5846 return RETURN_ERR;
5847 }
5848 sprintf(str, "%d", number);
5849 params.name = "max_num_sta";
5850 params.value = str;
5851
5852 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5853 int ret = wifi_hostapdWrite(config_file, &params, 1);
5854 if (ret) {
5855 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5856 ,__func__, ret);
5857 }
5858
5859 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5860 if (ret) {
5861 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
5862 ,__func__, ret);
5863 }
5864 wifi_reloadAp(apIndex);
5865 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5866
5867 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005868}
5869
5870//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.
5871INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
5872{
5873 //get the current threshold
5874 if(!output_uint)
5875 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005876 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
5877 if (*output_uint == 0)
5878 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08005879 return RETURN_OK;
5880}
5881
5882INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
5883{
5884 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08005885 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
5886 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005887 return RETURN_ERR;
5888}
5889
5890//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.
5891INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
5892{
5893 if(!output_uint)
5894 return RETURN_ERR;
5895 *output_uint = 3;
5896 return RETURN_OK;
5897}
5898
5899//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
5900INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
5901{
5902 if(!output_uint)
5903 return RETURN_ERR;
5904 *output_uint = 3;
5905 return RETURN_OK;
5906}
5907
5908//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.
5909INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
5910{
5911 if(!output_in_seconds)
5912 return RETURN_ERR;
5913 *output_in_seconds = 0;
5914 return RETURN_OK;
5915}
5916
5917//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
5918INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
5919{
5920 if(!output || apIndex>=MAX_APS)
5921 return RETURN_ERR;
5922 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08005923 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08005924 return RETURN_OK;
5925}
5926
5927//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
5928INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
5929{
developer587c1b62022-09-27 15:58:59 +08005930 char config_file[128] = {0};
5931 char wpa[16] = {0};
5932 char key_mgmt[64] = {0};
5933 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005934 if (!output)
5935 return RETURN_ERR;
5936
5937 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08005938 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08005939
developer587c1b62022-09-27 15:58:59 +08005940 strcpy(output, "None");//Copying "None" to output string for default case
5941 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
5942 if (strstr(key_mgmt, "WPA-PSK")) {
5943 if (strcmp(wpa, "1"))
5944 snprintf(output, 32, "WPA-Personal");
5945 else if (strcmp(wpa, "2"))
5946 snprintf(output, 32, "WPA2-Personal");
5947 else if (strcmp(wpa, "3"))
5948 snprintf(output, 32, "WPA-WPA2-Personal");
5949
5950 } else if (strstr(key_mgmt, "WPA-EAP")) {
5951 if (strcmp(wpa, "1"))
5952 snprintf(output, 32, "WPA-Enterprise");
5953 else if (strcmp(wpa, "2"))
5954 snprintf(output, 32, "WPA2-Enterprise");
5955 else if (strcmp(wpa, "3"))
5956 snprintf(output, 32, "WPA-WPA2-Enterprise");
5957 } else if (strstr(key_mgmt, "SAE")) {
5958 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
5959 int disable = strtol(buf, NULL, 16);
5960 if (disable & 0x1)
5961 snprintf(output, 32, "WPA3-Personal");
5962 else
5963 snprintf(output, 32, "WPA3-Transition");
5964 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
5965 snprintf(output, 32, "WPA3-Enterprise");
5966 }
developer06a01d92022-09-07 16:32:39 +08005967
5968 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5969 return RETURN_OK;
5970#if 0
5971 //TODO: need to revisit below implementation
5972 char securityType[32], authMode[32];
5973 int enterpriseMode=0;
5974
5975 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5976 if(!output)
5977 return RETURN_ERR;
5978
5979 wifi_getApBeaconType(apIndex, securityType);
5980 strcpy(output,"None");//By default, copying "None" to output string
5981 if (strncmp(securityType,"None", strlen("None")) == 0)
5982 return RETURN_OK;
5983
5984 wifi_getApBasicAuthenticationMode(apIndex, authMode);
5985 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
5986
5987 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
5988 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
5989 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
5990 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
5991 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
5992 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
5993 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5994
5995 return RETURN_OK;
5996#endif
5997}
5998
5999INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6000{
6001 char securityType[32];
6002 char authMode[32];
6003
6004 //store settings and wait for wifi up to apply
6005 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6006 if(!encMode)
6007 return RETURN_ERR;
6008
developer06a01d92022-09-07 16:32:39 +08006009 if (strcmp(encMode, "None")==0)
6010 {
6011 strcpy(securityType,"None");
6012 strcpy(authMode,"None");
6013 }
6014 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6015 {
6016 strcpy(securityType,"WPAand11i");
6017 strcpy(authMode,"PSKAuthentication");
6018 }
6019 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6020 {
6021 strcpy(securityType,"WPAand11i");
6022 strcpy(authMode,"EAPAuthentication");
6023 }
6024 else if (strcmp(encMode, "WPA-Personal")==0)
6025 {
6026 strcpy(securityType,"WPA");
6027 strcpy(authMode,"PSKAuthentication");
6028 }
6029 else if (strcmp(encMode, "WPA-Enterprise")==0)
6030 {
6031 strcpy(securityType,"WPA");
6032 strcpy(authMode,"EAPAuthentication");
6033 }
6034 else if (strcmp(encMode, "WPA2-Personal")==0)
6035 {
6036 strcpy(securityType,"11i");
6037 strcpy(authMode,"PSKAuthentication");
6038 }
6039 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6040 {
6041 strcpy(securityType,"11i");
6042 strcpy(authMode,"EAPAuthentication");
6043 }
developer587c1b62022-09-27 15:58:59 +08006044 else if (strcmp(encMode, "WPA3-Personal") == 0)
6045 {
6046 strcpy(securityType,"11i");
6047 strcpy(authMode,"SAEAuthentication");
6048 }
6049 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6050 {
6051 strcpy(securityType,"11i");
6052 strcpy(authMode,"EAP_192-bit_Authentication");
6053 }
developer06a01d92022-09-07 16:32:39 +08006054 else
6055 {
6056 strcpy(securityType,"None");
6057 strcpy(authMode,"None");
6058 }
6059 wifi_setApBeaconType(apIndex, securityType);
6060 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6061 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6062
6063 return RETURN_OK;
6064}
6065
6066
6067//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6068// output_string must be pre-allocated as 64 character string by caller
6069// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6070INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6071{
6072 char buf[16];
6073 char config_file[MAX_BUF_SIZE] = {0};
6074
6075 if(output_string==NULL)
6076 return RETURN_ERR;
6077
6078 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6079 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6080
6081 if(strcmp(buf,"0")==0)
6082 {
6083 printf("wpa_mode is %s ......... \n",buf);
6084 return RETURN_ERR;
6085 }
6086
6087 wifi_dbg_printf("\nFunc=%s\n",__func__);
6088 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6089 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6090 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6091
6092 return RETURN_OK;
6093}
6094
6095// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6096// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6097INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6098{
6099 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6100 struct params params={'\0'};
6101 int ret;
6102 char config_file[MAX_BUF_SIZE] = {0};
6103
6104 if(NULL == preSharedKey)
6105 return RETURN_ERR;
6106
6107 params.name = "wpa_passphrase";
6108
6109 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6110 {
6111 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6112 return RETURN_ERR;
6113 }
6114 params.value = preSharedKey;
6115 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6116 ret = wifi_hostapdWrite(config_file, &params, 1);
6117 if(!ret)
6118 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6119 return ret;
6120 //TODO: call hostapd_cli for dynamic_config_control
6121}
6122
6123//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6124// outputs the passphrase, maximum 63 characters
6125INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6126{
6127 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6128
6129 wifi_dbg_printf("\nFunc=%s\n",__func__);
6130 if (NULL == output_string)
6131 return RETURN_ERR;
6132
6133 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6134 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6135 if(strcmp(buf,"0")==0)
6136 {
6137 printf("wpa_mode is %s ......... \n",buf);
6138 return RETURN_ERR;
6139 }
6140
6141 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6142 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6143
6144 return RETURN_OK;
6145}
6146
6147// sets the passphrase enviornment variable, max 63 characters
6148INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6149{
6150 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6151 struct params params={'\0'};
6152 char config_file[MAX_BUF_SIZE] = {0};
6153 int ret;
6154
6155 if(NULL == passPhrase)
6156 return RETURN_ERR;
6157
6158 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6159 {
6160 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6161 return RETURN_ERR;
6162 }
6163 params.name = "wpa_passphrase";
6164 params.value = passPhrase;
6165 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6166 ret=wifi_hostapdWrite(config_file,&params,1);
6167 if(!ret)
6168 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6169
6170 return ret;
6171}
6172
6173//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.
6174INT wifi_setApSecurityReset(INT apIndex)
6175{
developer8d583982022-09-20 11:28:22 +08006176 char original_config_file[64] = {0};
6177 char current_config_file[64] = {0};
6178 char buf[64] = {0};
6179 char cmd[64] = {0};
6180 char wpa[4] = {0};
6181 char wpa_psk[64] = {0};
6182 char wpa_passphrase[64] = {0};
6183 char wpa_psk_file[128] = {0};
6184 char wpa_key_mgmt[64] = {0};
6185 char wpa_pairwise[32] = {0};
6186 wifi_band band;
6187 struct params list[6];
6188
6189 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6190
6191 band = wifi_index_to_band(apIndex);
6192 if (band == band_2_4)
6193 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6194 else if (band = band_5)
6195 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6196 else if (band = band_6)
6197 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6198 else
6199 return RETURN_ERR;
6200
6201 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6202 list[0].name = "wpa";
6203 list[0].value = wpa;
6204
6205 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6206 list[1].name = "wpa_psk";
6207 list[1].value = wpa_psk;
6208
6209 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6210 list[2].name = "wpa_passphrase";
6211 list[2].value = wpa_passphrase;
6212
6213 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6214
6215 if (strlen(wpa_psk_file) == 0)
6216 strcpy(wpa_psk_file, PSK_FILE);
6217
6218 if (access(wpa_psk_file, F_OK) != 0) {
6219 sprintf(cmd, "touch %s", wpa_psk_file);
6220 _syscmd(cmd, buf, sizeof(buf));
6221 }
6222 list[3].name = "wpa_psk_file";
6223 list[3].value = wpa_psk_file;
6224
6225 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6226 list[4].name = "wpa_key_mgmt";
6227 list[4].value = wpa_key_mgmt;
6228
6229 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6230 list[5].name = "wpa_pairwise";
6231 list[5].value = wpa_pairwise;
6232
6233 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6234 wifi_hostapdWrite(current_config_file, list, 6);
6235
6236 wifi_setApEnable(apIndex, FALSE);
6237 wifi_setApEnable(apIndex, TRUE);
6238
6239 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6240 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006241}
6242
6243//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).
6244INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6245{
developer8f2ddd52022-09-13 15:39:24 +08006246 char config_file[64] = {0};
6247 char buf[64] = {0};
6248 char cmd[256] = {0};
6249
6250 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6251
developer06a01d92022-09-07 16:32:39 +08006252 if(!IP_output || !Port_output || !RadiusSecret_output)
6253 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006254
developer8f2ddd52022-09-13 15:39:24 +08006255 // Read the first matched config
6256 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6257 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6258 _syscmd(cmd, buf, sizeof(buf));
6259 strncpy(IP_output, buf, 64);
6260
6261 memset(buf, 0, sizeof(buf));
6262 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6263 _syscmd(cmd, buf, sizeof(buf));
6264 *Port_output = atoi(buf);
6265
6266 memset(buf, 0, sizeof(buf));
6267 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6268 _syscmd(cmd, buf, sizeof(buf));
6269 strncpy(RadiusSecret_output, buf, 64);
6270
6271 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006272 return RETURN_OK;
6273}
6274
6275INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6276{
developer8f2ddd52022-09-13 15:39:24 +08006277 char config_file[64] = {0};
6278 char port_str[8] = {0};
6279 char cmd[256] = {0};
6280 char buf[128] = {0};
6281
6282 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6283
6284 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6285
6286 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6287 _syscmd(cmd, buf, sizeof(buf));
6288 memset(cmd, 0, sizeof(cmd));
6289
6290 snprintf(port_str, sizeof(port_str), "%d", port);
6291 if (strlen(buf) == 0)
6292 // Append
6293 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6294 "auth_server_addr=%s\\n"
6295 "auth_server_port=%s\\n"
6296 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6297 else {
6298 // Delete the three lines setting after the "# radius 1" comment
6299 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6300 _syscmd(cmd, buf, sizeof(buf));
6301 memset(cmd, 0, sizeof(cmd));
6302 // Use "# radius 1" comment to find the location to insert the radius setting
6303 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6304 "# radius 1\\n"
6305 "auth_server_addr=%s\\n"
6306 "auth_server_port=%s\\n"
6307 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6308 }
6309 if(_syscmd(cmd, buf, sizeof(buf))) {
6310 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6311 return RETURN_ERR;
6312 }
6313
6314 wifi_reloadAp(apIndex);
6315 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6316 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006317}
6318
6319INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6320{
developer8f2ddd52022-09-13 15:39:24 +08006321 char config_file[64] = {0};
6322 char buf[64] = {0};
6323 char cmd[256] = {0};
6324
6325 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6326
developer06a01d92022-09-07 16:32:39 +08006327 if(!IP_output || !Port_output || !RadiusSecret_output)
6328 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006329
6330 // Read the second matched config
6331 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6332 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6333 _syscmd(cmd, buf, sizeof(buf));
6334 strncpy(IP_output, buf, 64);
6335
6336 memset(buf, 0, sizeof(buf));
6337 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6338 _syscmd(cmd, buf, sizeof(buf));
6339 *Port_output = atoi(buf);
6340
6341 memset(buf, 0, sizeof(buf));
6342 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6343 _syscmd(cmd, buf, sizeof(buf));
6344 strncpy(RadiusSecret_output, buf, 64);
6345
6346 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006347 return RETURN_OK;
6348}
6349
6350INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6351{
developer8f2ddd52022-09-13 15:39:24 +08006352 char config_file[64] = {0};
6353 char port_str[8] = {0};
6354 char cmd[256] = {0};
6355 char buf[128] = {0};
6356
6357 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6358
6359 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6360
6361 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6362 _syscmd(cmd, buf, sizeof(buf));
6363 memset(cmd, 0, sizeof(cmd));
6364
6365 snprintf(port_str, sizeof(port_str), "%d", port);
6366 if (strlen(buf) == 0)
6367 // Append
6368 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6369 "auth_server_addr=%s\\n"
6370 "auth_server_port=%s\\n"
6371 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6372 else {
6373 // Delete the three lines setting after the "# radius 2" comment
6374 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6375 _syscmd(cmd, buf, sizeof(buf));
6376 memset(cmd, 0, sizeof(cmd));
6377 // Use "# radius 2" comment to find the location to insert the radius setting
6378 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6379 "# radius 2\\n"
6380 "auth_server_addr=%s\\n"
6381 "auth_server_port=%s\\n"
6382 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6383 }
6384 if(_syscmd(cmd, buf, sizeof(buf))) {
6385 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6386 return RETURN_ERR;
6387 }
6388
6389 wifi_reloadAp(apIndex);
6390 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6391 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006392}
6393
6394//RadiusSettings
6395INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6396{
6397 if(!output)
6398 return RETURN_ERR;
6399
6400 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6401 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6402 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6403 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6404 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6405 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.
6406 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6407 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6408 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6409 //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.
6410
6411 return RETURN_OK;
6412}
6413
6414INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6415{
6416 //store the paramters, and apply instantly
6417 return RETURN_ERR;
6418}
6419
6420//Device.WiFi.AccessPoint.{i}.WPS.Enable
6421//Enables or disables WPS functionality for this access point.
6422// outputs the WPS enable state of this ap in output_bool
6423INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6424{
6425 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6426 if(!output_bool || !(apIndex==0 || apIndex==1))
6427 return RETURN_ERR;
6428 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6429 _syscmd(cmd, buf, sizeof(buf));
6430 if(strstr(buf, "configured"))
6431 *output_bool=TRUE;
6432 else
6433 *output_bool=FALSE;
6434
6435 return RETURN_OK;
6436}
6437
6438//Device.WiFi.AccessPoint.{i}.WPS.Enable
6439// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6440INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6441{
6442 char config_file[MAX_BUF_SIZE] = {0};
6443 struct params params;
6444
6445 if(!(apIndex==0 || apIndex==1))
6446 return RETURN_ERR;
6447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6448 //store the paramters, and wait for wifi up to apply
6449 params.name = "wps_state";
6450 params.value = enable ? "2":"0";
6451
6452 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6453 wifi_hostapdWrite(config_file, &params, 1);
6454 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6455 wifi_reloadAp(apIndex);
6456
6457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6458 return RETURN_OK;
6459}
6460
6461//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
6462INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6463{
6464 if(!output)
6465 return RETURN_ERR;
6466 snprintf(output, 128, "PushButton,PIN");
6467 return RETURN_OK;
6468}
6469
6470//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6471//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.
6472// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6473INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6474{
6475 if(!output)
6476 return RETURN_ERR;
6477 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6478
6479 return RETURN_OK;
6480}
6481
6482//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6483// 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
6484INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6485{
6486 //apply instantly. No setting need to be stored.
6487 char methods[MAX_BUF_SIZE], *token, *next_token;
6488 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6489 struct params params;
6490
6491 if(!methodString || !(apIndex==0 || apIndex==1))
6492 return RETURN_ERR;
6493 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6494 //store the paramters, and wait for wifi up to apply
6495
6496 snprintf(methods, sizeof(methods), "%s", methodString);
6497 for(token=methods; *token; token=next_token)
6498 {
6499 strtok_r(token, ",", &next_token);
6500 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6501 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6502 else if(*token=='E')
6503 {
6504 if(!strcmp(methods, "Ethernet"))
6505 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6506 else if(!strcmp(methods, "ExternalNFCToken"))
6507 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6508 else
6509 printf("%s: Unknown WpsConfigMethod\n", __func__);
6510 }
6511 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6512 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6513 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6514 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6515 else if(*token=='P' )
6516 {
6517 if(!strcmp(token, "PushButton"))
6518 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6519 else if(!strcmp(token, "PIN"))
6520 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6521 else
6522 printf("%s: Unknown WpsConfigMethod\n", __func__);
6523 }
6524 else
6525 printf("%s: Unknown WpsConfigMethod\n", __func__);
6526 }
6527 params.name = "config_methods";
6528 params.value = config_methods;
6529 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6530 wifi_hostapdWrite(config_file, &params, 1);
6531 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6532 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6533
6534 return RETURN_OK;
6535}
6536
6537// outputs the pin value, ulong_pin must be allocated by the caller
6538INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6539{
6540 char buf[MAX_BUF_SIZE] = {0};
6541 char cmd[MAX_CMD_SIZE] = {0};
6542
6543 if(!output_ulong || !(apIndex==0 || apIndex==1))
6544 return RETURN_ERR;
6545 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6546 _syscmd(cmd, buf, sizeof(buf));
6547 if(strlen(buf) > 0)
6548 *output_ulong=strtoul(buf, NULL, 10);
6549
6550 return RETURN_OK;
6551}
6552
6553// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6554INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6555{
6556 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6557 char ap_pin[16] = {0};
6558 char buf[MAX_BUF_SIZE] = {0};
6559 char config_file[MAX_BUF_SIZE] = {0};
6560 ULONG prev_pin = 0;
6561 struct params params;
6562
6563 if(!(apIndex==0 || apIndex==1))
6564 return RETURN_ERR;
6565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6566 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6567 params.name = "ap_pin";
6568 params.value = ap_pin;
6569 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6570 wifi_hostapdWrite(config_file, &params, 1);
6571 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6572 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6573
6574 return RETURN_OK;
6575}
6576
6577// Output string is either Not configured or Configured, max 32 characters
6578INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6579{
6580 char cmd[MAX_CMD_SIZE];
6581 char buf[MAX_BUF_SIZE]={0};
6582
6583 if(!output_string || !(apIndex==0 || apIndex==1))
6584 return RETURN_ERR;
6585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6586 snprintf(output_string, 32, "Not configured");
6587 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6588 _syscmd(cmd, buf, sizeof(buf));
6589
developer348e3d92022-09-13 14:48:41 +08006590 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006591 snprintf(output_string, 32, "Configured");
6592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6593
6594 return RETURN_OK;
6595}
6596
6597// sets the WPS pin for this AP
6598INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6599{
6600 char cmd[MAX_CMD_SIZE];
6601 char buf[MAX_BUF_SIZE]={0};
6602 BOOL enable;
6603
6604 if(!(apIndex==0 || apIndex==1))
6605 return RETURN_ERR;
6606 wifi_getApEnable(apIndex, &enable);
6607 if (!enable)
6608 return RETURN_ERR;
6609 wifi_getApWpsEnable(apIndex, &enable);
6610 if (!enable)
6611 return RETURN_ERR;
6612
6613 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6614 _syscmd(cmd, buf, sizeof(buf));
6615 if((strstr(buf, "OK"))!=NULL)
6616 return RETURN_OK;
6617
6618 return RETURN_ERR;
6619}
6620
6621// This function is called when the WPS push button has been pressed for this AP
6622INT wifi_setApWpsButtonPush(INT apIndex)
6623{
6624 char cmd[MAX_CMD_SIZE];
6625 char buf[MAX_BUF_SIZE]={0};
6626 BOOL enable=FALSE;
6627
6628 if(!(apIndex==0 || apIndex==1))
6629 return RETURN_ERR;
6630 wifi_getApEnable(apIndex, &enable);
6631 if (!enable)
6632 return RETURN_ERR;
6633
6634 wifi_getApWpsEnable(apIndex, &enable);
6635 if (!enable)
6636 return RETURN_ERR;
6637
6638 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6639 _syscmd(cmd, buf, sizeof(buf));
6640
6641 if((strstr(buf, "OK"))!=NULL)
6642 return RETURN_OK;
6643 return RETURN_ERR;
6644}
6645
6646// cancels WPS mode for this AP
6647INT wifi_cancelApWPS(INT apIndex)
6648{
6649 char cmd[MAX_CMD_SIZE];
6650 char buf[MAX_BUF_SIZE]={0};
6651
6652 if(!(apIndex==0 || apIndex==1))
6653 return RETURN_ERR;
6654 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6655 _syscmd(cmd,buf, sizeof(buf));
6656
6657 if((strstr(buf, "OK"))!=NULL)
6658 return RETURN_OK;
6659 return RETURN_ERR;
6660}
6661
6662//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6663//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6664INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6665{
6666 FILE *f;
6667 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6668 char cmd[256], buf[2048];
6669 char *param , *value, *line=NULL;
6670 size_t len = 0;
6671 ssize_t nread;
6672 wifi_associated_dev_t *dev=NULL;
6673
6674 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6675 *associated_dev_array = NULL;
6676 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6677 _syscmd(cmd,buf,sizeof(buf));
6678 *output_array_size = atoi(buf);
6679
6680 if (*output_array_size <= 0)
6681 return RETURN_OK;
6682
6683 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6684 *associated_dev_array = dev;
6685 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6686 _syscmd(cmd,buf,sizeof(buf));
6687 f = fopen("/tmp/connected_devices.txt", "r");
6688 if (f==NULL)
6689 {
6690 *output_array_size=0;
6691 return RETURN_ERR;
6692 }
6693 while ((nread = getline(&line, &len, f)) != -1)
6694 {
6695 param = strtok(line,"=");
6696 value = strtok(NULL,"=");
6697
6698 if( strcmp("flags",param) == 0 )
6699 {
6700 value[strlen(value)-1]='\0';
6701 if(strstr (value,"AUTHORIZED") != NULL )
6702 {
6703 dev[auth_temp].cli_AuthenticationState = 1;
6704 dev[auth_temp].cli_Active = 1;
6705 auth_temp++;
6706 read_flag=1;
6707 }
6708 }
6709 if(read_flag==1)
6710 {
6711 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6712 {
6713 value[strlen(value)-1]='\0';
6714 sscanf(value, "%x:%x:%x:%x:%x:%x",
6715 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6716 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6717 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6718 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6719 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6720 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6721 mac_temp++;
6722 read_flag=0;
6723 }
6724 }
6725 }
6726 *output_array_size = auth_temp;
6727 auth_temp=0;
6728 mac_temp=0;
6729 free(line);
6730 fclose(f);
6731 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6732 return RETURN_OK;
6733}
6734
6735#define MACADDRESS_SIZE 6
6736
6737INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6738{
6739 FILE *fp = NULL;
6740 char str[MAX_BUF_SIZE] = {0};
6741 int wificlientindex = 0 ;
6742 int count = 0;
6743 int signalstrength = 0;
6744 int arr[MACADDRESS_SIZE] = {0};
6745 unsigned char mac[MACADDRESS_SIZE] = {0};
6746 UINT wifi_count = 0;
6747 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6748 char pipeCmd[MAX_CMD_SIZE] = {0};
6749
6750 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6751 *output_array_size = 0;
6752 *associated_dev_array = NULL;
6753
6754 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6755 fp = popen(pipeCmd, "r");
6756 if (fp == NULL)
6757 {
6758 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6759 return RETURN_ERR;
6760 }
6761
6762 /* Read the output a line at a time - output it. */
6763 fgets(str, sizeof(str)-1, fp);
6764 wifi_count = (unsigned int) atoi ( str );
6765 *output_array_size = wifi_count;
6766 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6767 pclose(fp);
6768
6769 if(wifi_count == 0)
6770 {
6771 return RETURN_OK;
6772 }
6773 else
6774 {
6775 wifi_associated_dev3_t* temp = NULL;
6776 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6777 if(temp == NULL)
6778 {
6779 printf("Error Statement. Insufficient memory \n");
6780 return RETURN_ERR;
6781 }
6782
6783 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6784 system(pipeCmd);
6785 memset(pipeCmd,0,sizeof(pipeCmd));
6786 if(apIndex == 0)
6787 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6788 else if(apIndex == 1)
6789 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6790 system(pipeCmd);
6791
6792 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6793 if(fp == NULL)
6794 {
6795 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6796 return RETURN_ERR;
6797 }
6798 fclose(fp);
6799
6800 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6801 fp = popen(pipeCmd, "r");
6802 if(fp)
6803 {
6804 for(count =0 ; count < wifi_count; count++)
6805 {
6806 fgets(str, MAX_BUF_SIZE, fp);
6807 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6808 {
6809 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6810 {
6811 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6812
6813 }
6814 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6815 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]);
6816 }
6817 temp[count].cli_AuthenticationState = 1; //TODO
6818 temp[count].cli_Active = 1; //TODO
6819 }
6820 pclose(fp);
6821 }
6822
6823 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6824 fp = popen(pipeCmd, "r");
6825 if(fp)
6826 {
6827 pclose(fp);
6828 }
6829 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6830 if(fp)
6831 {
6832 for(count =0 ; count < wifi_count ;count++)
6833 {
6834 fgets(str, MAX_BUF_SIZE, fp);
6835 signalstrength = atoi(str);
6836 temp[count].cli_SignalStrength = signalstrength;
6837 temp[count].cli_RSSI = signalstrength;
6838 temp[count].cli_SNR = signalstrength + 95;
6839 }
6840 pclose(fp);
6841 }
6842
6843
6844 if((apIndex == 0) || (apIndex == 4))
6845 {
6846 for(count =0 ; count < wifi_count ;count++)
6847 {
6848 strcpy(temp[count].cli_OperatingStandard,"g");
6849 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6850 }
6851
6852 //BytesSent
6853 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6854 fp = popen(pipeCmd, "r");
6855 if(fp)
6856 {
6857 pclose(fp);
6858 }
6859 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
6860 if(fp)
6861 {
6862 for (count = 0; count < wifi_count; count++)
6863 {
6864 fgets(str, MAX_BUF_SIZE, fp);
6865 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
6866 }
6867 pclose(fp);
6868 }
6869
6870 //BytesReceived
6871 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
6872 fp = popen(pipeCmd, "r");
6873 if (fp)
6874 {
6875 pclose(fp);
6876 }
6877 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
6878 if (fp)
6879 {
6880 for (count = 0; count < wifi_count; count++)
6881 {
6882 fgets(str, MAX_BUF_SIZE, fp);
6883 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
6884 }
6885 pclose(fp);
6886 }
6887
6888 //PacketsSent
6889 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
6890 fp = popen(pipeCmd, "r");
6891 if (fp)
6892 {
6893 pclose(fp);
6894 }
6895
6896 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
6897 if (fp)
6898 {
6899 for (count = 0; count < wifi_count; count++)
6900 {
6901 fgets(str, MAX_BUF_SIZE, fp);
6902 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
6903 }
6904 pclose(fp);
6905 }
6906
6907 //PacketsReceived
6908 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
6909 fp = popen(pipeCmd, "r");
6910 if (fp)
6911 {
6912 pclose(fp);
6913 }
6914 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
6915 if (fp)
6916 {
6917 for (count = 0; count < wifi_count; count++)
6918 {
6919 fgets(str, MAX_BUF_SIZE, fp);
6920 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
6921 }
6922 pclose(fp);
6923 }
6924
6925 //ErrorsSent
6926 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6927 fp = popen(pipeCmd, "r");
6928 if (fp)
6929 {
6930 pclose(fp);
6931 }
6932 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6933 if (fp)
6934 {
6935 for (count = 0; count < wifi_count; count++)
6936 {
6937 fgets(str, MAX_BUF_SIZE, fp);
6938 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6939 }
6940 pclose(fp);
6941 }
6942
6943 //ErrorsSent
6944 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
6945 fp = popen(pipeCmd, "r");
6946 if (fp)
6947 {
6948 pclose(fp);
6949 }
6950 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
6951 if (fp)
6952 {
6953 for (count = 0; count < wifi_count; count++)
6954 {
6955 fgets(str, MAX_BUF_SIZE, fp);
6956 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
6957 }
6958 pclose(fp);
6959 }
6960
6961 //LastDataDownlinkRate
6962 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
6963 fp = popen(pipeCmd, "r");
6964 if (fp)
6965 {
6966 pclose(fp);
6967 }
6968 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
6969 if (fp)
6970 {
6971 for (count = 0; count < wifi_count; count++)
6972 {
6973 fgets(str, MAX_BUF_SIZE, fp);
6974 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
6975 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
6976 }
6977 pclose(fp);
6978 }
6979
6980 //LastDataUplinkRate
6981 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
6982 fp = popen(pipeCmd, "r");
6983 if (fp)
6984 {
6985 pclose(fp);
6986 }
6987 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
6988 if (fp)
6989 {
6990 for (count = 0; count < wifi_count; count++)
6991 {
6992 fgets(str, MAX_BUF_SIZE, fp);
6993 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
6994 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
6995 }
6996 pclose(fp);
6997 }
6998
6999 }
7000 else if ((apIndex == 1) || (apIndex == 5))
7001 {
7002 for (count = 0; count < wifi_count; count++)
7003 {
7004 strcpy(temp[count].cli_OperatingStandard, "a");
7005 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7006 temp[count].cli_BytesSent = 0;
7007 temp[count].cli_BytesReceived = 0;
7008 temp[count].cli_LastDataUplinkRate = 0;
7009 temp[count].cli_LastDataDownlinkRate = 0;
7010 temp[count].cli_PacketsSent = 0;
7011 temp[count].cli_PacketsReceived = 0;
7012 temp[count].cli_ErrorsSent = 0;
7013 }
7014 }
7015
7016 for (count = 0; count < wifi_count; count++)
7017 {
7018 temp[count].cli_Retransmissions = 0;
7019 temp[count].cli_DataFramesSentAck = 0;
7020 temp[count].cli_DataFramesSentNoAck = 0;
7021 temp[count].cli_MinRSSI = 0;
7022 temp[count].cli_MaxRSSI = 0;
7023 strncpy(temp[count].cli_InterferenceSources, "", 64);
7024 memset(temp[count].cli_IPAddress, 0, 64);
7025 temp[count].cli_RetransCount = 0;
7026 temp[count].cli_FailedRetransCount = 0;
7027 temp[count].cli_RetryCount = 0;
7028 temp[count].cli_MultipleRetryCount = 0;
7029 }
7030 *associated_dev_array = temp;
7031 }
7032 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7033 return RETURN_OK;
7034}
7035
7036int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7037{
7038 FILE *fp = NULL;
7039 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7040 char cmd[MAX_CMD_SIZE];
7041 int count = 0;
7042
7043 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7044 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7045 fp = popen(cmd,"r");
7046 if(fp == NULL)
7047 {
7048 printf("Failed to run command in Function %s\n",__FUNCTION__);
7049 return 0;
7050 }
7051 if(fgets(path, sizeof(path)-1, fp) != NULL)
7052 {
7053 for(count=0;path[count]!='\n';count++)
7054 status[count]=path[count];
7055 status[count]='\0';
7056 }
7057 strcpy(wifi_status,status);
7058 pclose(fp);
7059 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7060 return RETURN_OK;
7061}
7062
7063/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7064struct hostapd_sta_param {
7065 char key[50];
7066 char value[100];
7067}
7068
7069static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7070 int i = 0;
7071
7072 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7073 if (strncmp(params[i].key,key,50) == 0){
7074 return &params[i].value;
7075 }
7076 i++;
7077 }
7078 return NULL;
7079
7080} */
7081
7082static unsigned int count_occurences(const char *buf, const char *word)
7083{
7084 unsigned int n = 0;
7085 char *ptr = strstr(buf, word);
7086
7087 while (ptr++) {
7088 n++;
7089 ptr = strstr(ptr, word);
7090 }
7091
7092 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7093 return n;
7094}
7095
7096static const char *get_line_from_str_buf(const char *buf, char *line)
7097{
7098 int i;
7099 int n = strlen(buf);
7100
7101 for (i = 0; i < n; i++) {
7102 line[i] = buf[i];
7103 if (buf[i] == '\n') {
7104 line[i] = '\0';
7105 return &buf[i + 1];
7106 }
7107 }
7108
7109 return NULL;
7110}
7111
7112INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7113{
7114 unsigned int assoc_cnt = 0;
7115 char interface_name[50] = {0};
7116 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7117 char cmd[MAX_CMD_SIZE] = {'\0'};
7118 char line[256] = {'\0'};
7119 int i = 0;
7120 int ret = 0;
7121 const char *ptr = NULL;
7122 char *key = NULL;
7123 char *val = NULL;
7124 wifi_associated_dev3_t *temp = NULL;
7125 int rssi;
7126
7127 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7128
7129 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7130 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7131 return RETURN_ERR;
7132 }
7133
7134 // Example filtered output of 'iw dev' command:
7135 // Station 0a:69:72:10:d2:fa (on wifi0)
7136 // signal avg:-67 [-71, -71] dBm
7137 // Station 28:c2:1f:25:5f:99 (on wifi0)
7138 // signal avg:-67 [-71, -70] dBm
7139 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7140 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7141 return RETURN_ERR;
7142 }
7143
7144 ret = _syscmd(cmd, buf, sizeof(buf));
7145 if (ret == RETURN_ERR) {
7146 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7147 return RETURN_ERR;
7148 }
7149
7150 *output_array_size = count_occurences(buf, "Station");
7151 if (*output_array_size == 0) return RETURN_OK;
7152
7153 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7154 if (temp == NULL) {
7155 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7156 return RETURN_ERR;
7157 }
7158 *associated_dev_array = temp;
7159
7160 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7161 ptr = get_line_from_str_buf(buf, line);
7162 i = -1;
7163 while (ptr) {
7164 if (strstr(line, "Station")) {
7165 i++;
7166 key = strtok(line, " ");
7167 val = strtok(NULL, " ");
7168 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7169 &temp[i].cli_MACAddress[0],
7170 &temp[i].cli_MACAddress[1],
7171 &temp[i].cli_MACAddress[2],
7172 &temp[i].cli_MACAddress[3],
7173 &temp[i].cli_MACAddress[4],
7174 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7175 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7176 free(*associated_dev_array);
7177 return RETURN_ERR;
7178 }
7179 }
7180 else if (i < 0) {
7181 ptr = get_line_from_str_buf(ptr, line);
7182 continue; // We didn't detect 'station' entry yet
7183 }
7184 else if (strstr(line, "signal avg")) {
7185 key = strtok(line, ":");
7186 val = strtok(NULL, " ");
7187 if (sscanf(val, "%d", &rssi) <= 0 ) {
7188 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7189 free(*associated_dev_array);
7190 return RETURN_ERR;
7191 }
7192 temp[i].cli_RSSI = rssi;
7193 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7194 }
7195 // Here other fields can be parsed if added to filter of 'iw dev' command
7196
7197 ptr = get_line_from_str_buf(ptr, line);
7198 };
7199
7200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7201
7202 return RETURN_OK;
7203}
7204
7205#if 0
7206//To-do
7207INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7208{
7209 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7210
7211 //Using different approach to get required WiFi Parameters from system available commands
7212#if 0
7213 FILE *f;
7214 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7215 char cmd[256], buf[2048];
7216 char *param , *value, *line=NULL;
7217 size_t len = 0;
7218 ssize_t nread;
7219 wifi_associated_dev3_t *dev=NULL;
7220 *associated_dev_array = NULL;
7221 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7222 _syscmd(cmd,buf,sizeof(buf));
7223 *output_array_size = atoi(buf);
7224
7225 if (*output_array_size <= 0)
7226 return RETURN_OK;
7227
7228 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7229 *associated_dev_array = dev;
7230 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7231 _syscmd(cmd,buf,sizeof(buf));
7232 f = fopen("/tmp/connected_devices.txt", "r");
7233 if (f==NULL)
7234 {
7235 *output_array_size=0;
7236 return RETURN_ERR;
7237 }
7238 while ((nread = getline(&line, &len, f)) != -1)
7239 {
7240 param = strtok(line,"=");
7241 value = strtok(NULL,"=");
7242
7243 if( strcmp("flags",param) == 0 )
7244 {
7245 value[strlen(value)-1]='\0';
7246 if(strstr (value,"AUTHORIZED") != NULL )
7247 {
7248 dev[auth_temp].cli_AuthenticationState = 1;
7249 dev[auth_temp].cli_Active = 1;
7250 auth_temp++;
7251 read_flag=1;
7252 }
7253 }
7254 if(read_flag==1)
7255 {
7256 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7257 {
7258 value[strlen(value)-1]='\0';
7259 sscanf(value, "%x:%x:%x:%x:%x:%x",
7260 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7261 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7262 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7263 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7264 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7265 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7266
7267 }
7268 else if( strcmp("rx_packets",param) == 0 )
7269 {
7270 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7271 }
7272
7273 else if( strcmp("tx_packets",param) == 0 )
7274 {
7275 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7276 }
7277
7278 else if( strcmp("rx_bytes",param) == 0 )
7279 {
7280 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7281 }
7282
7283 else if( strcmp("tx_bytes",param) == 0 )
7284 {
7285 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7286 mac_temp++;
7287 read_flag=0;
7288 }
7289 }
7290 }
7291
7292 *output_array_size = auth_temp;
7293 auth_temp=0;
7294 mac_temp=0;
7295 free(line);
7296 fclose(f);
7297#endif
7298 char interface_name[MAX_BUF_SIZE] = {0};
7299 char wifi_status[MAX_BUF_SIZE] = {0};
7300 char hostapdconf[MAX_BUF_SIZE] = {0};
7301
7302 wifi_associated_dev3_t *dev_array = NULL;
7303 ULONG wifi_count = 0;
7304
7305 *associated_dev_array = NULL;
7306 *output_array_size = 0;
7307
7308 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7309 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7310 {
7311 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7312
7313 GetInterfaceName(interface_name, hostapdconf);
7314
7315 if(strlen(interface_name) > 1)
7316 {
7317 wifihal_interfacestatus(wifi_status,interface_name);
7318 if(strcmp(wifi_status,"RUNNING") == 0)
7319 {
7320 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7321
7322 *associated_dev_array = dev_array;
7323 *output_array_size = wifi_count;
7324 }
7325 else
7326 {
7327 *associated_dev_array = NULL;
7328 }
7329 }
7330 }
7331
7332 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7333 return RETURN_OK;
7334}
7335#endif
7336
7337/* getIPAddress function */
7338/**
7339* @description Returning IpAddress of the Matched String
7340*
7341* @param
7342* @str Having MacAddress
7343* @ipaddr Having ipaddr
7344* @return The status of the operation
7345* @retval RETURN_OK if successful
7346* @retval RETURN_ERR if any error is detected
7347*
7348*/
7349
7350INT getIPAddress(char *str,char *ipaddr)
7351{
7352 FILE *fp = NULL;
7353 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7354 int LeaseTime = 0,ret = 0;
7355 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7356 {
7357 return RETURN_ERR;
7358 }
7359
7360 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7361 {
7362 /*
7363 Sample:sss
7364 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7365 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7366 */
7367 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7368 &(LeaseTime),
7369 phyAddr,
7370 ipAddr,
7371 hostName
7372 );
7373 if(ret != 4)
7374 continue;
7375 if(strcmp(str,phyAddr) == 0)
7376 strcpy(ipaddr,ipAddr);
7377 }
7378 return RETURN_OK;
7379}
7380
7381/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7382/**
7383* @description Returning Inactive wireless connected clients informations
7384*
7385* @param
7386* @filename Holding private_wifi 2g/5g content files
7387* @associated_dev_array Having inactiv wireless clients informations
7388* @output_array_size Returning Inactive wireless counts
7389* @return The status of the operation
7390* @retval RETURN_OK if successful
7391* @retval RETURN_ERR if any error is detected
7392*
7393*/
7394
7395INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7396{
7397 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7398 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7399 FILE *fp = NULL;
7400 int arr[MACADDRESS_SIZE] = {0};
7401 unsigned char mac[MACADDRESS_SIZE] = {0};
7402 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7403 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7404 fp = popen(buf,"r");
7405 if(fp == NULL)
7406 return RETURN_ERR;
7407 else
7408 {
7409 fgets(path,sizeof(path),fp);
7410 maccount = atoi(path);
7411 }
7412 pclose(fp);
7413 *output_array_size = maccount;
7414 wifi_associated_dev3_t* temp = NULL;
7415 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7416 *associated_dev_array = temp;
7417 if(temp == NULL)
7418 {
7419 printf("Error Statement. Insufficient memory \n");
7420 return RETURN_ERR;
7421 }
7422 memset(buf,0,sizeof(buf));
7423 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7424 fp = popen(buf,"r");
7425 for(count = 0; count < maccount ; count++)
7426 {
7427 fgets(path,sizeof(path),fp);
7428 for(i = 0; path[i]!='\n';i++)
7429 str[i]=path[i];
7430 str[i]='\0';
7431 getIPAddress(str,ipaddr);
7432 memset(buf,0,sizeof(buf));
7433 if(strlen(ipaddr) > 0)
7434 {
7435 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7436 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7437 {
7438 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7439 {
7440 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7441 {
7442 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7443
7444 }
7445 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7446 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]);
7447 }
7448 temp[count].cli_AuthenticationState = 0; //TODO
7449 temp[count].cli_Active = 0; //TODO
7450 temp[count].cli_SignalStrength = 0;
7451 }
7452 else //Active wireless clients info
7453 {
7454 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7455 {
7456 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7457 {
7458 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7459
7460 }
7461 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7462 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]);
7463 }
7464 temp[count].cli_Active = 1;
7465 }
7466 }
7467 memset(ipaddr,0,sizeof(ipaddr));
7468 }
7469 pclose(fp);
7470 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7471 return RETURN_OK;
7472}
7473//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7474//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7475//To get Band Steering Capability
7476INT wifi_getBandSteeringCapability(BOOL *support)
7477{
7478 *support = FALSE;
7479 return RETURN_OK;
7480}
7481
7482
7483//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7484//To get Band Steering enable status
7485INT wifi_getBandSteeringEnable(BOOL *enable)
7486{
7487 *enable = FALSE;
7488 return RETURN_OK;
7489}
7490
7491//To turn on/off Band steering
7492INT wifi_setBandSteeringEnable(BOOL enable)
7493{
7494 return RETURN_OK;
7495}
7496
7497//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7498//To get Band Steering AP group
7499INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7500{
7501 if (NULL == output_ApGroup)
7502 return RETURN_ERR;
7503
7504 strcpy(output_ApGroup, "1,2");
7505 return RETURN_OK;
7506}
7507
7508//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7509//to set and read the band steering BandUtilizationThreshold parameters
7510INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7511{
7512 return RETURN_ERR;
7513}
7514
7515INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7516{
7517 return RETURN_ERR;
7518}
7519
7520//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7521//to set and read the band steering RSSIThreshold parameters
7522INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7523{
7524 return RETURN_ERR;
7525}
7526
7527INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7528{
7529 return RETURN_ERR;
7530}
7531
7532
7533//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7534//to set and read the band steering physical modulation rate threshold parameters
7535INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7536{
7537 //If chip is not support, return -1
7538 return RETURN_ERR;
7539}
7540
7541INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7542{
7543 //If chip is not support, return -1
7544 return RETURN_ERR;
7545}
7546
7547//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7548//to set and read the inactivity time (in seconds) for steering under overload condition
7549INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7550{
7551 return RETURN_ERR;
7552}
7553
7554INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7555{
7556 return RETURN_ERR;
7557}
7558
7559//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7560//to set and read the inactivity time (in seconds) for steering under Idle condition
7561INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7562{
7563 return RETURN_ERR;
7564}
7565
7566INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7567{
7568 return RETURN_ERR;
7569}
7570
7571//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7572//pClientMAC[64]
7573//pSourceSSIDIndex[64]
7574//pDestSSIDIndex[64]
7575//pSteeringReason[256]
7576INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7577{
7578 //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
7579 *pSteeringTime=time(NULL);
7580 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7581 return RETURN_OK;
7582}
7583
7584INT wifi_ifConfigDown(INT apIndex)
7585{
7586 INT status = RETURN_OK;
7587 char cmd[64];
7588
7589 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7590 printf("%s: %s\n", __func__, cmd);
7591 system(cmd);
7592
7593 return status;
7594}
7595
7596INT wifi_ifConfigUp(INT apIndex)
7597{
7598 char cmd[128];
7599 char buf[1024];
7600
7601 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7602 _syscmd(cmd, buf, sizeof(buf));
7603 return 0;
7604}
7605
7606//>> Deprecated. Replace with wifi_applyRadioSettings
7607INT wifi_pushBridgeInfo(INT apIndex)
7608{
7609 char ip[32];
7610 char subnet[32];
7611 char bridge[32];
7612 int vlanId;
7613 char cmd[128];
7614 char buf[1024];
7615
7616 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7617 wifi_getApVlanID(apIndex,&vlanId);
7618
7619 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7620 _syscmd(cmd,buf, sizeof(buf));
7621
7622 return 0;
7623}
7624
7625INT wifi_pushChannel(INT radioIndex, UINT channel)
7626{
7627 char cmd[128];
7628 char buf[1024];
7629 int apIndex;
7630
7631 apIndex=(radioIndex==0)?0:1;
7632 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7633 _syscmd(cmd,buf, sizeof(buf));
7634
7635 return 0;
7636}
7637
7638INT wifi_pushChannelMode(INT radioIndex)
7639{
7640 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7641 return RETURN_ERR;
7642}
7643
7644INT wifi_pushDefaultValues(INT radioIndex)
7645{
7646 //Apply Comcast specified default radio settings instantly
7647 //AMPDU=1
7648 //AMPDUFrames=32
7649 //AMPDULim=50000
7650 //txqueuelen=1000
7651
7652 return RETURN_ERR;
7653}
7654
7655INT wifi_pushTxChainMask(INT radioIndex)
7656{
7657 //Apply default TxChainMask instantly
7658 return RETURN_ERR;
7659}
7660
7661INT wifi_pushRxChainMask(INT radioIndex)
7662{
7663 //Apply default RxChainMask instantly
7664 return RETURN_ERR;
7665}
7666
7667INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7668{
7669 INT status;
7670
7671 status = wifi_setSSIDName(apIndex,ssid);
7672 wifi_setApEnable(apIndex,FALSE);
7673 wifi_setApEnable(apIndex,TRUE);
7674
7675 return status;
7676}
7677
7678INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7679{
7680 //Apply default Ssid Advertisement instantly
7681 return RETURN_ERR;
7682}
7683
7684INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7685{
7686 INT status = RETURN_ERR;
7687 *output = 0;
7688 return RETURN_ERR;
7689}
7690
7691INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7692{
7693 return RETURN_OK;
7694}
7695
7696INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7697{
7698 return RETURN_OK;
7699}
7700
7701//To-do
7702INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7703{
developereb199ae2022-09-13 14:04:27 +08007704 char output[16]={'\0'};
7705 char config_file[MAX_BUF_SIZE] = {0};
7706
7707 if (!output_string)
7708 return RETURN_ERR;
7709
7710 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7711 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7712
7713 if (strlen(output) == 0)
7714 snprintf(output_string, 64, "Disabled");
7715 else if (strncmp(output, "0", 1) == 0)
7716 snprintf(output_string, 64, "Disabled");
7717 else if (strncmp(output, "1", 1) == 0)
7718 snprintf(output_string, 64, "Optional");
7719 else if (strncmp(output, "2", 1) == 0)
7720 snprintf(output_string, 64, "Required");
7721 else {
7722 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7723 return RETURN_ERR;
7724 }
7725
7726 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007727 return RETURN_OK;
7728}
7729INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7730{
developereb199ae2022-09-13 14:04:27 +08007731 char str[MAX_BUF_SIZE]={'\0'};
7732 char cmd[MAX_CMD_SIZE]={'\0'};
7733 struct params params;
7734 char config_file[MAX_BUF_SIZE] = {0};
7735
7736 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7737 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7738 return RETURN_ERR;
7739
7740 params.name = "ieee80211w";
7741 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7742 params.value = "0";
7743 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7744 params.value = "1";
7745 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7746 params.value = "2";
7747 else{
7748 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7749 return RETURN_ERR;
7750 }
7751 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7752 wifi_hostapdWrite(config_file, &params, 1);
7753 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007754 return RETURN_OK;
7755}
7756INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7757{
7758 char output[16]={'\0'};
7759 char config_file[MAX_BUF_SIZE] = {0};
7760
7761 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7762 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7763 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7764
7765 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7766 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7767
7768 return RETURN_OK;
7769}
7770
7771INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7772{
7773 return RETURN_OK;
7774}
7775
7776INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7777{
7778 return RETURN_OK;
7779}
7780
7781INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7782{
7783 return RETURN_OK;
7784}
7785
7786INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7787{
7788 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7789 char config_file[MAX_BUF_SIZE] = {0};
7790
7791 if (NULL == output)
7792 return RETURN_ERR;
7793 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7794 wifi_hostapdRead(config_file,"hw_mode",output,64);
7795
7796 if(strcmp(output,"b")==0)
7797 sprintf(output, "%s", "1,2,5.5,11");
7798 else if (strcmp(output,"a")==0)
7799 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7800 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7801 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7802
7803 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7804 return RETURN_OK;
7805}
7806
7807INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7808{
7809 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7810 char *temp;
7811 char temp_output[128];
7812 char temp_TransmitRates[128];
7813 char config_file[MAX_BUF_SIZE] = {0};
7814
7815 if (NULL == output)
7816 return RETURN_ERR;
7817
7818 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7819 wifi_hostapdRead(config_file,"supported_rates",output,64);
7820
7821 strcpy(temp_TransmitRates,output);
7822 strcpy(temp_output,"");
7823 temp = strtok(temp_TransmitRates," ");
7824 while(temp!=NULL)
7825 {
7826 temp[strlen(temp)-1]=0;
7827 if((temp[0]=='5') && (temp[1]=='\0'))
7828 {
7829 temp="5.5";
7830 }
7831 strcat(temp_output,temp);
7832 temp = strtok(NULL," ");
7833 if(temp!=NULL)
7834 {
7835 strcat(temp_output,",");
7836 }
7837 }
7838 strcpy(output,temp_output);
7839 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7840
7841 return RETURN_OK;
7842}
7843
7844INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7845{
7846 return RETURN_OK;
7847}
7848
7849
7850INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7851{
7852 int i=0;
7853 char *temp;
7854 char temp1[128];
7855 char temp_output[128];
7856 char temp_TransmitRates[128];
7857 struct params params={'\0'};
7858 char config_file[MAX_BUF_SIZE] = {0};
7859
7860 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7861 if(NULL == output)
7862 return RETURN_ERR;
7863
7864 strcpy(temp_TransmitRates,output);
7865
7866 for(i=0;i<strlen(temp_TransmitRates);i++)
7867 {
7868 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
7869 {
7870 continue;
7871 }
7872 else
7873 {
7874 return RETURN_ERR;
7875 }
7876 }
7877 strcpy(temp_output,"");
7878 temp = strtok(temp_TransmitRates," ");
7879 while(temp!=NULL)
7880 {
7881 strcpy(temp1,temp);
7882 if(wlanIndex==1)
7883 {
7884 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
7885 {
7886 return RETURN_ERR;
7887 }
7888 }
7889
7890 if(strcmp(temp,"5.5")==0)
7891 {
7892 strcpy(temp1,"55");
7893 }
7894 else
7895 {
7896 strcat(temp1,"0");
7897 }
7898 strcat(temp_output,temp1);
7899 temp = strtok(NULL," ");
7900 if(temp!=NULL)
7901 {
7902 strcat(temp_output," ");
7903 }
7904 }
7905 strcpy(output,temp_output);
7906
7907
7908 params.name = "supported_rates";
7909 params.value = output;
7910
7911 wifi_dbg_printf("\n%s:",__func__);
7912 wifi_dbg_printf("params.value=%s\n",params.value);
7913 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7914 wifi_hostapdWrite(config_file,&params,1);
7915 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7916
7917 return RETURN_OK;
7918}
7919
7920
7921static char *sncopy(char *dst, int dst_sz, const char *src)
7922{
7923 if (src && dst && dst_sz > 0) {
7924 strncpy(dst, src, dst_sz);
7925 dst[dst_sz - 1] = '\0';
7926 }
7927 return dst;
7928}
7929
7930static int util_get_sec_chan_offset(int channel, const char* ht_mode)
7931{
7932 if (0 == strcmp(ht_mode, "HT40") ||
7933 0 == strcmp(ht_mode, "HT80") ||
7934 0 == strcmp(ht_mode, "HT160")) {
7935 switch (channel) {
7936 case 1 ... 7:
7937 case 36:
7938 case 44:
7939 case 52:
7940 case 60:
7941 case 100:
7942 case 108:
7943 case 116:
7944 case 124:
7945 case 132:
7946 case 140:
7947 case 149:
7948 case 157:
7949 return 1;
7950 case 8 ... 13:
7951 case 40:
7952 case 48:
7953 case 56:
7954 case 64:
7955 case 104:
7956 case 112:
7957 case 120:
7958 case 128:
7959 case 136:
7960 case 144:
7961 case 153:
7962 case 161:
7963 return -1;
7964 default:
7965 return -EINVAL;
7966 }
7967 }
7968
7969 return -EINVAL;
7970}
7971
7972static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
7973{
7974 if (NULL == hw_mode) return;
7975
7976 if (0 == strcmp(hw_mode, "ac"))
7977 sncopy(bw_mode, bw_mode_len, "ht vht");
7978
7979 if (0 == strcmp(hw_mode, "n"))
7980 sncopy(bw_mode, bw_mode_len, "ht");
7981
7982 return;
7983}
7984
7985static int util_chan_to_freq(int chan)
7986{
7987 if (chan == 14)
7988 return 2484;
7989 else if (chan < 14)
7990 return 2407 + chan * 5;
7991 else if (chan >= 182 && chan <= 196)
7992 return 4000 + chan * 5;
7993 else
7994 return 5000 + chan * 5;
7995 return 0;
7996}
7997
7998const int *util_unii_5g_chan2list(int chan, int width)
7999{
8000 static const int lists[] = {
8001 // <width>, <chan1>, <chan2>..., 0,
8002 20, 36, 0,
8003 20, 40, 0,
8004 20, 44, 0,
8005 20, 48, 0,
8006 20, 52, 0,
8007 20, 56, 0,
8008 20, 60, 0,
8009 20, 64, 0,
8010 20, 100, 0,
8011 20, 104, 0,
8012 20, 108, 0,
8013 20, 112, 0,
8014 20, 116, 0,
8015 20, 120, 0,
8016 20, 124, 0,
8017 20, 128, 0,
8018 20, 132, 0,
8019 20, 136, 0,
8020 20, 140, 0,
8021 20, 144, 0,
8022 20, 149, 0,
8023 20, 153, 0,
8024 20, 157, 0,
8025 20, 161, 0,
8026 20, 165, 0,
8027 40, 36, 40, 0,
8028 40, 44, 48, 0,
8029 40, 52, 56, 0,
8030 40, 60, 64, 0,
8031 40, 100, 104, 0,
8032 40, 108, 112, 0,
8033 40, 116, 120, 0,
8034 40, 124, 128, 0,
8035 40, 132, 136, 0,
8036 40, 140, 144, 0,
8037 40, 149, 153, 0,
8038 40, 157, 161, 0,
8039 80, 36, 40, 44, 48, 0,
8040 80, 52, 56, 60, 64, 0,
8041 80, 100, 104, 108, 112, 0,
8042 80, 116, 120, 124, 128, 0,
8043 80, 132, 136, 140, 144, 0,
8044 80, 149, 153, 157, 161, 0,
8045 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8046 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8047 -1 // final delimiter
8048 };
8049 const int *start;
8050 const int *p;
8051
8052 for (p = lists; *p != -1; p++) {
8053 if (*p == width) {
8054 for (start = ++p; *p != 0; p++) {
8055 if (*p == chan)
8056 return start;
8057 }
8058 }
8059 // move to the end of channel list of given width
8060 while (*p != 0) {
8061 p++;
8062 }
8063 }
8064
8065 return NULL;
8066}
8067
8068static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8069{
8070 if (NULL == ht_mode)
8071 return 0;
8072
8073 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8074 const int *chans = util_unii_5g_chan2list(channel, width);
8075 int sum = 0;
8076 int cnt = 0;
8077
8078 if (NULL == chans)
8079 return 0;
8080
8081 while (*chans) {
8082 sum += *chans;
8083 cnt++;
8084 chans++;
8085 }
8086 return sum / cnt;
8087}
8088
8089static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8090{
8091 BOOL onlyG, onlyN, onlyA;
8092 CHAR tmp[64];
8093 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8094 if (ret == RETURN_OK) {
8095 sncopy(hw_mode, hw_mode_size, tmp);
8096 }
8097 return ret;
8098}
8099
8100INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8101{
8102 // Sample commands:
8103 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8104 // hostapd_cli -i wifi0 chan_switch 30 2437
8105 char cmd[MAX_CMD_SIZE] = {0};
8106 char buf[MAX_BUF_SIZE] = {0};
8107 int freq = 0, ret = 0;
8108 char center_freq1_str[32] = ""; // center_freq1=%d
8109 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8110 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8111 char hw_mode[16] = ""; // n|ac
8112 char bw_mode[16] = ""; // ht|ht vht
8113 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8114 int sec_chan_offset;
8115 int width;
8116
8117 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8118
8119 freq = util_chan_to_freq(channel);
8120
8121 // Get radio mode HT20|HT40|HT80 etc.
8122 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
8123 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8124 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8125 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8126 if (sec_chan_offset != -EINVAL)
8127 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
8128
8129
8130 // Provide bandwith if specified
8131 if (channel_width_MHz > 20) {
8132 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8133 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8134 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
8135
8136 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8137 }
8138
8139 int center_chan = 0;
8140 if (channel_width_MHz > 20) {
8141 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8142 if (center_chan > 0) {
8143 int center_freq1 = util_chan_to_freq(center_chan);
8144 if (center_freq1)
8145 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8146 }
8147 }
8148
8149 {
8150 // Only the first AP, other are hanging on the same radio
8151 int apIndex = radioIndex;
8152 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8153 AP_PREFIX, apIndex, csa_beacon_count, freq,
8154 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8155 wifi_dbg_printf("execute: '%s'\n", cmd);
8156 ret = _syscmd(cmd, buf, sizeof(buf));
8157 }
8158
8159 wifi_setRadioChannel(radioIndex, channel);
8160
8161 char *ext_str = "None";
8162 if (sec_chan_offset == 1) ext_str = "Above";
8163 else if (sec_chan_offset == -1) ext_str = "Below";
8164 wifi_setRadioExtChannel(radioIndex, ext_str);
8165
8166 wifi_setRadioCenterChannel(radioIndex, center_chan);
8167
8168 char mhz_str[16];
8169 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8170 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8171
8172 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8173
8174 return RETURN_OK;
8175}
8176
8177INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8178{
developer615510b2022-09-27 10:14:35 +08008179 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008180 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008181 char cmd[256]={0};
8182 char buf[128]={0};
8183 char file_name[32] = {0};
8184 char filter_SSID[32] = {0};
8185 char line[256] = {0};
8186 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008187 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008188 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008189 size_t len=0;
8190 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008191 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008192 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008193 bool filter_enable = false;
8194 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008195
developer615510b2022-09-27 10:14:35 +08008196 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008197
developer615510b2022-09-27 10:14:35 +08008198 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8199 f = fopen(file_name, "r");
8200 if (f != NULL) {
8201 fgets(filter_SSID, sizeof(file_name), f);
8202 if (strlen(filter_SSID) != 0)
8203 filter_enable = true;
8204 fclose(f);
8205 }
8206
8207 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8208 _syscmd(cmd, buf, sizeof(buf));
8209 channels_num = strtol(buf, NULL, 10);
8210
developer615510b2022-09-27 10:14:35 +08008211 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8212 // 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);
8213 fprintf(stderr, "cmd: %s\n", cmd);
8214 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008215 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8216 return RETURN_ERR;
8217 }
developer5550e242022-09-30 09:59:32 +08008218
8219 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8220 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8221
developer615510b2022-09-27 10:14:35 +08008222 ret = fgets(line, sizeof(line), f);
8223 while (ret != NULL) {
8224 if(strstr(line, "BSS") != NULL) { // new neighbor info
8225 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8226 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8227 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8228
8229 if (!filter_BSS) {
8230 index++;
8231 wifi_neighbor_ap2_t *tmp;
8232 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8233 if (tmp == NULL) { // no more memory to use
8234 index--;
8235 wifi_dbg_printf("%s: realloc failed\n", __func__);
8236 break;
8237 }
8238 scan_array = tmp;
8239 }
8240 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008241
developer615510b2022-09-27 10:14:35 +08008242 filter_BSS = false;
8243 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8244 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8245 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8246 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8247 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008248 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008249 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008250
developer615510b2022-09-27 10:14:35 +08008251 if (freq >= 2412 && freq <= 2484) {
8252 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8253 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8254 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8255 }
8256 else if (freq >= 5160 && freq <= 5805) {
8257 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8258 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8259 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8260 }
developer06a01d92022-09-07 16:32:39 +08008261
developer615510b2022-09-27 10:14:35 +08008262 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008263 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008264 for (int i = 0; i < channels_num; i++) {
8265 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8266 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8267 break;
8268 }
8269 }
developer06a01d92022-09-07 16:32:39 +08008270 }
developer615510b2022-09-27 10:14:35 +08008271 } else if (strstr(line, "beacon interval") != NULL) {
8272 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8273 } else if (strstr(line, "signal") != NULL) {
8274 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8275 } else if (strstr(line,"SSID") != NULL) {
8276 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8277 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8278 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008279 }
developer615510b2022-09-27 10:14:35 +08008280 } else if (strstr(line, "Supported rates") != NULL) {
8281 char SRate[80] = {0}, *tmp = NULL;
8282 memset(buf, 0, sizeof(buf));
8283 strcpy(SRate, line);
8284 tmp = strtok(SRate, ":");
8285 tmp = strtok(NULL, ":");
8286 strcpy(buf, tmp);
8287 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008288
developer615510b2022-09-27 10:14:35 +08008289 tmp = strtok(buf, " \n");
8290 while (tmp != NULL) {
8291 strcat(SRate, tmp);
8292 if (SRate[strlen(SRate) - 1] == '*') {
8293 SRate[strlen(SRate) - 1] = '\0';
8294 }
8295 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008296
developer615510b2022-09-27 10:14:35 +08008297 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008298 }
developer615510b2022-09-27 10:14:35 +08008299 SRate[strlen(SRate) - 1] = '\0';
8300 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8301 } else if (strstr(line, "DTIM") != NULL) {
8302 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8303 } else if (strstr(line, "VHT capabilities") != NULL) {
8304 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8305 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8306 } else if (strstr(line, "HT capabilities") != NULL) {
8307 strcat(scan_array[index].ap_SupportedStandards, ",n");
8308 strcpy(scan_array[index].ap_OperatingStandards, "n");
8309 } else if (strstr(line, "VHT operation") != NULL) {
8310 ret = fgets(line, sizeof(line), f);
8311 sscanf(line," * channel width: %d", &vht_channel_width);
8312 if(vht_channel_width == 1) {
8313 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8314 } else {
8315 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8316 }
8317 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8318 continue;
8319 } else if (strstr(line, "HT operation") != NULL) {
8320 ret = fgets(line, sizeof(line), f);
8321 sscanf(line," * secondary channel offset: %s", &buf);
8322 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008323 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008324 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 +08008325 }
developer615510b2022-09-27 10:14:35 +08008326 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008327 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008328 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8329 } else {
8330 //20Mhz
8331 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 +08008332 }
developer615510b2022-09-27 10:14:35 +08008333 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008334 continue;
developer615510b2022-09-27 10:14:35 +08008335 } else if (strstr(line, "HE capabilities") != NULL) {
8336 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8337 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8338 ret = fgets(line, sizeof(line), f);
8339 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8340 if (strstr(line, "HE40/2.4GHz") != NULL)
8341 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8342 else
8343 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8344 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8345 if (strstr(line, "HE80/5GHz") != NULL) {
8346 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8347 ret = fgets(line, sizeof(line), f);
8348 } else
8349 continue;
8350 if (strstr(line, "HE160/5GHz") != NULL)
8351 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008352 }
developer615510b2022-09-27 10:14:35 +08008353 continue;
8354 } else if (strstr(line, "WPA") != NULL) {
8355 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8356 } else if (strstr(line, "RSN") != NULL) {
8357 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8358 } else if (strstr(line, "Group cipher") != NULL) {
8359 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8360 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8361 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008362 }
developer06a01d92022-09-07 16:32:39 +08008363 }
developer615510b2022-09-27 10:14:35 +08008364 ret = fgets(line, sizeof(line), f);
8365 }
8366
8367 if (!filter_BSS) {
8368 *output_array_size = index + 1;
8369 } else {
8370 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8371 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008372 }
developer06a01d92022-09-07 16:32:39 +08008373 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008374 pclose(f);
developer5550e242022-09-30 09:59:32 +08008375 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008376 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008377 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008378}
developer615510b2022-09-27 10:14:35 +08008379
developer06a01d92022-09-07 16:32:39 +08008380INT wifi_getApAssociatedDeviceStats(
8381 INT apIndex,
8382 mac_address_t *clientMacAddress,
8383 wifi_associated_dev_stats_t *associated_dev_stats,
8384 u64 *handle)
8385{
8386 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8387 char interface_name[50] = {0};
8388 char cmd[1024] = {0};
8389 char mac_str[18] = {0};
8390 char *key = NULL;
8391 char *val = NULL;
8392 FILE *f = NULL;
8393 char *line = NULL;
8394 size_t len = 0;
8395 ssize_t read = 0;
8396
8397 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8398 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8399 return RETURN_ERR;
8400 }
8401
8402 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8403 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8404 if((f = popen(cmd, "r")) == NULL) {
8405 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8406 return RETURN_ERR;
8407 }
8408
8409 while ((read = getline(&line, &len, f)) != -1) {
8410 key = strtok(line,":");
8411 val = strtok(NULL,":");
8412
8413 if(!strncmp(key,"rx bytes",8))
8414 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8415 if(!strncmp(key,"tx bytes",8))
8416 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8417 if(!strncmp(key,"rx packets",10))
8418 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8419 if(!strncmp(key,"tx packets",10))
8420 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8421 if(!strncmp(key,"tx retries",10))
8422 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8423 if(!strncmp(key,"tx failed",9))
8424 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8425 if(!strncmp(key,"rx drop misc",13))
8426 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8427 if(!strncmp(key,"rx bitrate",10)) {
8428 val = strtok(val, " ");
8429 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8430 }
8431 if(!strncmp(key,"tx bitrate",10)) {
8432 val = strtok(val, " ");
8433 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8434 }
8435 }
8436 free(line);
8437 pclose(f);
8438 return RETURN_OK;
8439}
8440
8441INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8442{
8443 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8444
8445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8446 if (NULL == output_string)
8447 return RETURN_ERR;
8448
8449 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8450 _syscmd(cmd, buf, sizeof(buf));
8451
8452 //size of SSID name restricted to value less than 32 bytes
8453 snprintf(output_string, 32, "%s", buf);
8454 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8455
8456 return RETURN_OK;
8457}
8458
8459INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8460{
8461 //char cmd[MAX_CMD_SIZE] = {0};
8462 char config_file[MAX_BUF_SIZE] = {0};
8463 char buf[32] = {0};
8464
8465 if (!output_filterMode)
8466 return RETURN_ERR;
8467
8468 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8469 //_syscmd(cmd, buf, sizeof(buf));
8470 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8471 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008472 if(strlen(buf) == 0) {
8473 *output_filterMode = 0;
8474 }
8475 else {
8476 int macaddr_acl_mode = strtol(buf, NULL, 10);
8477 if (macaddr_acl_mode == 1) {
8478 *output_filterMode = 1;
8479 } else if (macaddr_acl_mode == 0) {
8480 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8481 if (strlen(buf) == 0) {
8482 *output_filterMode = 0;
8483 } else {
8484 *output_filterMode = 2;
8485 }
8486 } else {
8487 return RETURN_ERR;
8488 }
8489 }
developer06a01d92022-09-07 16:32:39 +08008490
8491 return RETURN_OK;
8492}
8493
8494INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8495{
8496 FILE *fp = NULL;
8497 char str[MAX_BUF_SIZE] = {0};
8498 int wificlientindex = 0 ;
8499 int count = 0;
8500 int signalstrength = 0;
8501 int arr[MACADDRESS_SIZE] = {0};
8502 unsigned char mac[MACADDRESS_SIZE] = {0};
8503 UINT wifi_count = 0;
8504 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8505 char pipeCmd[MAX_CMD_SIZE] = {0};
8506
8507 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8508 *output_array_size = 0;
8509 *associated_dev_array = NULL;
8510 char interface_name[50] = {0};
8511
8512 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8513 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8514 return RETURN_ERR;
8515 }
8516
8517 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8518 fp = popen(pipeCmd, "r");
8519 if (fp == NULL)
8520 {
8521 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8522 return RETURN_ERR;
8523 }
8524
8525 /* Read the output a line at a time - output it. */
8526 fgets(str, sizeof(str)-1, fp);
8527 wifi_count = (unsigned int) atoi ( str );
8528 *output_array_size = wifi_count;
8529 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8530 pclose(fp);
8531
8532 if(wifi_count == 0)
8533 {
8534 return RETURN_OK;
8535 }
8536 else
8537 {
8538 wifi_associated_dev2_t* temp = NULL;
8539 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8540 *associated_dev_array = temp;
8541 if(temp == NULL)
8542 {
8543 printf("Error Statement. Insufficient memory \n");
8544 return RETURN_ERR;
8545 }
8546
8547 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8548 system(pipeCmd);
8549
8550 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8551 if(fp == NULL)
8552 {
8553 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8554 return RETURN_ERR;
8555 }
8556 fclose(fp);
8557
8558 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8559 fp = popen(pipeCmd, "r");
8560 if(fp)
8561 {
8562 for(count =0 ; count < wifi_count; count++)
8563 {
8564 fgets(str, MAX_BUF_SIZE, fp);
8565 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8566 {
8567 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8568 {
8569 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8570
8571 }
8572 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8573 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]);
8574 }
8575 temp[count].cli_AuthenticationState = 1; //TODO
8576 temp[count].cli_Active = 1; //TODO
8577 }
8578 pclose(fp);
8579 }
8580
8581 //Updating RSSI per client
8582 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8583 fp = popen(pipeCmd, "r");
8584 if(fp)
8585 {
8586 pclose(fp);
8587 }
8588 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8589 if(fp)
8590 {
8591 for(count =0 ; count < wifi_count ;count++)
8592 {
8593 fgets(str, MAX_BUF_SIZE, fp);
8594 signalstrength = atoi(str);
8595 temp[count].cli_RSSI = signalstrength;
8596 }
8597 pclose(fp);
8598 }
8599
8600
8601 //LastDataDownlinkRate
8602 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8603 fp = popen(pipeCmd, "r");
8604 if (fp)
8605 {
8606 pclose(fp);
8607 }
8608 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8609 if (fp)
8610 {
8611 for (count = 0; count < wifi_count; count++)
8612 {
8613 fgets(str, MAX_BUF_SIZE, fp);
8614 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8615 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8616 }
8617 pclose(fp);
8618 }
8619
8620 //LastDataUplinkRate
8621 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8622 fp = popen(pipeCmd, "r");
8623 if (fp)
8624 {
8625 pclose(fp);
8626 }
8627 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8628 if (fp)
8629 {
8630 for (count = 0; count < wifi_count; count++)
8631 {
8632 fgets(str, MAX_BUF_SIZE, fp);
8633 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8634 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8635 }
8636 pclose(fp);
8637 }
8638 }
8639 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8640 return RETURN_OK;
8641
8642}
8643
8644INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8645{
8646#if 0
8647 /*char buf[1024] = {0};
8648 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8649 _syscmd(cmd, buf, sizeof(buf));*/
8650
8651 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8652 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8653 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8654 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8655
8656 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.
8657 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].
8658 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].
8659 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].
8660 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8661 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8662
8663 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8664 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8665 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8666 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.
8667 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.
8668 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.
8669 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.
8670 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.
8671 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.
8672 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.
8673 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8674#endif
8675
8676 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008677 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008678 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008679 char pipeCmd[128] = {0};
8680 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008681 wifi_ssidTrafficStats2_t *out = output_struct;
8682
developerce736392022-09-13 15:24:34 +08008683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008684 if (!output_struct)
8685 return RETURN_ERR;
8686
developerce736392022-09-13 15:24:34 +08008687 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8688 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8689 GetInterfaceName(interface_name, HConf_file);
8690 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008691
developer06a01d92022-09-07 16:32:39 +08008692 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008693 if (fp == NULL) {
8694 fprintf(stderr, "%s: popen failed\n", __func__);
8695 return RETURN_ERR;
8696 }
8697 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008698
developerce736392022-09-13 15:24:34 +08008699 if (strlen(str) == 0) // interface not exist
8700 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008701
developerce736392022-09-13 15:24:34 +08008702 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8703 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008704 pclose(fp);
8705
developerce736392022-09-13 15:24:34 +08008706 memset(str, 0, sizeof(str));
8707 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008708 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008709 if (fp == NULL) {
8710 fprintf(stderr, "%s: popen failed\n", __func__);
8711 return RETURN_ERR;
8712 }
8713 fgets(str, sizeof(str), fp);
8714
8715 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8716 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008717 pclose(fp);
developerce736392022-09-13 15:24:34 +08008718
8719 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8720 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8721
8722 // Not supported
8723 output_struct->ssid_RetransCount = 0;
8724 output_struct->ssid_FailedRetransCount = 0;
8725 output_struct->ssid_RetryCount = 0;
8726 output_struct->ssid_MultipleRetryCount = 0;
8727 output_struct->ssid_ACKFailureCount = 0;
8728 output_struct->ssid_AggregatedPacketCount = 0;
8729
developer06a01d92022-09-07 16:32:39 +08008730 return RETURN_OK;
8731}
8732
8733//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).
8734INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8735{
8736 char output_val[16]={'\0'};
8737 char config_file[MAX_BUF_SIZE] = {0};
8738
8739 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8740 if (!output)
8741 return RETURN_ERR;
8742 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8743 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8744
8745 if( strcmp(output_val,"1") == 0 )
8746 *output = TRUE;
8747 else
8748 *output = FALSE;
8749 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8750
8751 return RETURN_OK;
8752}
8753
8754INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8755{
8756 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8757 char str[MAX_BUF_SIZE]={'\0'};
8758 char string[MAX_BUF_SIZE]={'\0'};
8759 char cmd[MAX_CMD_SIZE]={'\0'};
8760 char *ch;
8761 char config_file[MAX_BUF_SIZE] = {0};
8762 struct params params;
8763
8764 if(enable == TRUE)
8765 strcpy(string,"1");
8766 else
8767 strcpy(string,"0");
8768
8769 params.name = "ap_isolate";
8770 params.value = string;
8771
8772 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8773 wifi_hostapdWrite(config_file,&params,1);
8774 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8775
8776 return RETURN_OK;
8777}
8778
8779INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8780{
8781 if (NULL == output_dBm)
8782 return RETURN_ERR;
8783
8784 *output_dBm = 0;
8785 return RETURN_OK;
8786}
8787
8788INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8789{
8790 return RETURN_OK;
8791}
8792INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8793{
8794 return RETURN_OK;
8795}
8796INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8797{
8798 return RETURN_OK;
8799}
8800INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8801{
8802 return RETURN_OK;
8803}
8804INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8805{
8806 return RETURN_OK;
8807}
8808INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8809{
8810 char config_file[MAX_BUF_SIZE] = {0};
8811 struct params list;
8812
8813 list.name = "bss_transition";
8814 list.value = activate?"1":"0";
8815 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8816 wifi_hostapdWrite(config_file, &list, 1);
8817
8818 return RETURN_OK;
8819}
8820wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8821
8822void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8823{
8824 return;
8825}
8826
8827INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8828{
8829 // TODO Implement me!
8830 return RETURN_OK;
8831}
8832
8833INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8834{
developera3c68b92022-09-13 15:27:29 +08008835 char file_name[128] = {0};
8836 char buf[128] = {0};
8837 FILE *f = NULL;
8838
8839 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8840
8841 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8842 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8843 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8844 f = fopen(file_name, "w");
8845 if (f == NULL)
8846 return RETURN_ERR;
8847 // For mode == 0 is to disable filter, just don't write to the file.
8848 if (mode)
8849 fprintf(f, "%s", essid);
8850
8851 fclose(f);
8852 }
8853 } else { // special case, need to set AP's SSID as filter for each radio.
8854 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
8855 f = fopen(file_name, "w");
8856 if (f == NULL)
8857 return RETURN_ERR;
8858
8859 // For mode == 0 is to disable filter, just don't write to the file.
8860 if (mode)
8861 fprintf(f, "%s", essid);
8862
8863 fclose(f);
8864 }
8865
8866 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008867 return RETURN_OK;
8868}
8869
8870INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
8871{
8872 // TODO Implement me!
8873 //Apply wifi_pushRadioChannel() instantly
8874 return RETURN_ERR;
8875}
8876
8877INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
8878{
8879 // TODO Implement me!
8880 return RETURN_OK;
8881}
8882
8883#ifdef HAL_NETLINK_IMPL
8884static int tidStats_callback(struct nl_msg *msg, void *arg) {
8885 struct nlattr *tb[NL80211_ATTR_MAX + 1];
8886 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
8887 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
8888 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
8889 int rem , tid_index = 0;
8890
8891 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
8892 wifi_associated_dev_tid_entry_t *stats_entry;
8893
8894 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
8895 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
8896 };
8897 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
8898 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
8899 };
8900
8901 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
8902 genlmsg_attrlen(gnlh, 0), NULL);
8903
8904
8905 if (!tb[NL80211_ATTR_STA_INFO]) {
8906 fprintf(stderr, "station stats missing!\n");
8907 return NL_SKIP;
8908 }
8909
8910 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
8911 tb[NL80211_ATTR_STA_INFO],
8912 stats_policy)) {
8913 fprintf(stderr, "failed to parse nested attributes!\n");
8914 return NL_SKIP;
8915 }
8916
8917 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
8918 {
8919 stats_entry = &out->tid_array[tid_index];
8920
8921 stats_entry->tid = tid_index;
8922 stats_entry->ac = _tid_ac_index_get[tid_index];
8923
8924 if(sinfo[NL80211_STA_INFO_TID_STATS])
8925 {
8926 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
8927 printf("failed to parse nested stats attributes!");
8928 return NL_SKIP;
8929 }
8930 }
8931 if(stats_info[NL80211_TID_STATS_TX_MSDU])
8932 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
8933
8934 if(tid_index < (PS_MAX_TID - 1))
8935 tid_index++;
8936 }
8937 //ToDo: sum_time_ms, ewma_time_ms
8938 return NL_SKIP;
8939}
8940#endif
8941
8942INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
8943{
8944#ifdef HAL_NETLINK_IMPL
8945 Netlink nl;
8946 char if_name[10];
8947
8948 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8949
8950 nl.id = initSock80211(&nl);
8951
8952 if (nl.id < 0) {
8953 fprintf(stderr, "Error initializing netlink \n");
8954 return -1;
8955 }
8956
8957 struct nl_msg* msg = nlmsg_alloc();
8958
8959 if (!msg) {
8960 fprintf(stderr, "Failed to allocate netlink message.\n");
8961 nlfree(&nl);
8962 return -2;
8963 }
8964
8965 genlmsg_put(msg,
8966 NL_AUTO_PORT,
8967 NL_AUTO_SEQ,
8968 nl.id,
8969 0,
8970 0,
8971 NL80211_CMD_GET_STATION,
8972 0);
8973
8974 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
8975 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
8976 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
8977 nl_send_auto(nl.socket, msg);
8978 nl_recvmsgs(nl.socket, nl.cb);
8979 nlmsg_free(msg);
8980 nlfree(&nl);
8981 return RETURN_OK;
8982#else
8983//iw implementation
8984#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
8985#define TOTAL_MAX_LINES 50
8986
8987 char buf[256] = {'\0'}; /* or other suitable maximum line size */
8988 char if_name[10];
8989 FILE *fp=NULL;
8990 char pipeCmd[1024]= {'\0'};
8991 int lines,tid_index=0;
8992 char mac_addr[20] = {'\0'};
8993
8994 wifi_associated_dev_tid_entry_t *stats_entry;
8995
8996 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
8997 strcpy(mac_addr,clientMacAddress);
8998
8999 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9000 fp= popen(pipeCmd,"r");
9001 if(fp == NULL)
9002 {
9003 perror("popen for station dump failed\n");
9004 return RETURN_ERR;
9005 }
9006 pclose(fp);
9007
9008 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9009 fp=popen(pipeCmd,"r");
9010 if(fp == NULL)
9011 {
9012 perror("popen for grep station failed\n");
9013 return RETURN_ERR;
9014 }
9015 else if(fgets(buf,sizeof(buf),fp) != NULL)
9016 lines=atoi(buf);
9017 else
9018 {
9019 pclose(fp);
9020 fprintf(stderr,"No devices are connected \n");
9021 return RETURN_ERR;
9022 }
9023 pclose(fp);
9024
9025 if(lines == 1)
9026 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9027
9028 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9029 {
9030 stats_entry = &tid_stats->tid_array[tid_index];
9031 stats_entry->tid = tid_index;
9032
9033 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);
9034
9035 fp=popen(pipeCmd,"r");
9036 if(fp ==NULL)
9037 {
9038 perror("Failed to read from tid file \n");
9039 return RETURN_ERR;
9040 }
9041 else if(fgets(buf,sizeof(buf),fp) != NULL)
9042 stats_entry->num_msdus = atol(buf);
9043
9044 pclose(fp);
9045 stats_entry->ac = _tid_ac_index_get[tid_index];
9046// TODO:
9047// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9048// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9049 }
9050 return RETURN_OK;
9051#endif
9052}
9053
9054
9055INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9056{
developer615510b2022-09-27 10:14:35 +08009057 char cmd[128]={0};
9058 char buf[128]={0};
9059 int freq = 0;
9060
9061 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9062
9063 // full mode is used to scan all channels.
9064 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9065 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9066 ieee80211_channel_to_frequency(chan_list[0], &freq);
9067
9068 if (freq)
9069 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9070 else
9071 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9072
9073 _syscmd(cmd, buf, sizeof(buf));
9074 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9075
developer06a01d92022-09-07 16:32:39 +08009076 return RETURN_OK;
9077}
9078
9079
9080INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9081{
9082 // TODO Implement me!
9083 return RETURN_ERR;
9084}
9085
9086INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9087{
9088 // TODO Implement me!
9089 return RETURN_ERR;
9090}
9091
9092INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9093{
9094 // TODO Implement me!
9095 return RETURN_ERR;
9096}
9097
9098INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9099{
9100 // TODO Implement me!
9101 return RETURN_ERR;
9102}
9103
9104INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9105{
9106 // TODO Implement me!
9107 return RETURN_ERR;
9108}
9109
9110INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9111{
9112 // TODO Implement me!
9113 return RETURN_ERR;
9114}
9115
9116INT wifi_steering_eventUnregister(void)
9117{
9118 // TODO Implement me!
9119 return RETURN_ERR;
9120}
9121
9122INT wifi_delApAclDevices(INT apIndex)
9123{
9124#if 0
9125 char cmd[MAX_BUF_SIZE] = {0};
9126 char buf[MAX_BUF_SIZE] = {0};
9127
9128 /* Not reset proof solution */
9129 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9130 if(_syscmd(cmd,buf,sizeof(buf)))
9131 return RETURN_ERR;
9132#endif
developere6aafda2022-09-13 14:59:28 +08009133 char cmd[MAX_CMD_SIZE]={0};
9134 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009135
developere6aafda2022-09-13 14:59:28 +08009136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9137 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9138 if(_syscmd(cmd, buf, sizeof(buf)))
9139 return RETURN_ERR;
9140 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009141
9142 return RETURN_OK;
9143}
9144
9145#ifdef HAL_NETLINK_IMPL
9146static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9147 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9148 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9149 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9150 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9151 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9152 char mac_addr[20],dev[20];
9153
9154 nla_parse(tb,
9155 NL80211_ATTR_MAX,
9156 genlmsg_attrdata(gnlh, 0),
9157 genlmsg_attrlen(gnlh, 0),
9158 NULL);
9159
9160 if(!tb[NL80211_ATTR_STA_INFO]) {
9161 fprintf(stderr, "sta stats missing!\n");
9162 return NL_SKIP;
9163 }
9164
9165 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9166 fprintf(stderr, "failed to parse nested attributes!\n");
9167 return NL_SKIP;
9168 }
9169 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9170
9171 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9172
9173 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9174 fprintf(stderr, "failed to parse nested rate attributes!");
9175 return NL_SKIP;
9176 }
9177
9178 if(sinfo[NL80211_STA_INFO_TID_STATS])
9179 {
9180 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9181 printf("failed to parse nested stats attributes!");
9182 return NL_SKIP;
9183 }
9184 }
9185
9186 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9187 {
9188 printf("Type is VHT\n");
9189 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9190 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9191
9192 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9193 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9194 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9195 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9196 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9197 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9198 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9199 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9200 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9201 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9202 }
9203 else
9204 {
9205 printf(" OFDM or CCK \n");
9206 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9207 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9208 }
9209
9210 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9211 if(rinfo[NL80211_RATE_INFO_MCS])
9212 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9213 }
9214 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9215 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9216 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9217 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9218
9219 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9220 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9221
9222 if (sinfo[NL80211_STA_INFO_SIGNAL])
9223 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9224 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9225 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9226 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9227 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9228 //rssi_array need to be filled
9229 return NL_SKIP;
9230}
9231#endif
9232
9233INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9234{
9235#ifdef HAL_NETLINK_IMPL
9236 Netlink nl;
9237 char if_name[10];
9238
9239 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9240
9241 if (*output_array_size <= 0)
9242 return RETURN_OK;
9243
9244 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9245 nl.id = initSock80211(&nl);
9246
9247 if (nl.id < 0) {
9248 fprintf(stderr, "Error initializing netlink \n");
9249 return 0;
9250 }
9251
9252 struct nl_msg* msg = nlmsg_alloc();
9253
9254 if (!msg) {
9255 fprintf(stderr, "Failed to allocate netlink message.\n");
9256 nlfree(&nl);
9257 return 0;
9258 }
9259
9260 genlmsg_put(msg,
9261 NL_AUTO_PORT,
9262 NL_AUTO_SEQ,
9263 nl.id,
9264 0,
9265 0,
9266 NL80211_CMD_GET_STATION,
9267 0);
9268
9269 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9270 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9271 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9272 nl_send_auto(nl.socket, msg);
9273 nl_recvmsgs(nl.socket, nl.cb);
9274 nlmsg_free(msg);
9275 nlfree(&nl);
9276 return RETURN_OK;
9277#else
9278 //TODO Implement me
9279 return RETURN_OK;
9280#endif
9281}
9282
9283#ifdef HAL_NETLINK_IMPL
9284static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9285 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9286 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9287 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9288 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9289 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9290 char mac_addr[20],dev[20];
9291
9292 nla_parse(tb,
9293 NL80211_ATTR_MAX,
9294 genlmsg_attrdata(gnlh, 0),
9295 genlmsg_attrlen(gnlh, 0),
9296 NULL);
9297
9298 if(!tb[NL80211_ATTR_STA_INFO]) {
9299 fprintf(stderr, "sta stats missing!\n");
9300 return NL_SKIP;
9301 }
9302
9303 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9304 fprintf(stderr, "failed to parse nested attributes!\n");
9305 return NL_SKIP;
9306 }
9307
9308 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9309
9310 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9311
9312 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9313 fprintf(stderr, "failed to parse nested rate attributes!");
9314 return NL_SKIP;
9315 }
9316
9317 if(sinfo[NL80211_STA_INFO_TID_STATS])
9318 {
9319 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9320 printf("failed to parse nested stats attributes!");
9321 return NL_SKIP;
9322 }
9323 }
9324 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9325 {
9326 printf("Type is VHT\n");
9327 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9328 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9329
9330 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9331 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9332 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9333 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9334 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9335 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9336 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9337 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9338 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9339 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9340 }
9341 else
9342 {
9343 printf(" OFDM or CCK \n");
9344 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9345 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9346 }
9347
9348 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9349 if(rinfo[NL80211_RATE_INFO_MCS])
9350 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9351 }
9352
9353 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9354 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9355 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9356 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9357
9358 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9359 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9360 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9361
9362 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9363 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9364
9365 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9366 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9367
9368 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9369 ((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]);
9370
9371 return NL_SKIP;
9372}
9373#endif
9374
9375INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9376{
9377#ifdef HAL_NETLINK_IMPL
9378 Netlink nl;
9379 char if_name[10];
9380
9381 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9382
9383 if (*output_array_size <= 0)
9384 return RETURN_OK;
9385
9386 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9387
9388 nl.id = initSock80211(&nl);
9389
9390 if(nl.id < 0) {
9391 fprintf(stderr, "Error initializing netlink \n");
9392 return 0;
9393 }
9394
9395 struct nl_msg* msg = nlmsg_alloc();
9396
9397 if(!msg) {
9398 fprintf(stderr, "Failed to allocate netlink message.\n");
9399 nlfree(&nl);
9400 return 0;
9401 }
9402
9403 genlmsg_put(msg,
9404 NL_AUTO_PORT,
9405 NL_AUTO_SEQ,
9406 nl.id,
9407 0,
9408 0,
9409 NL80211_CMD_GET_STATION,
9410 0);
9411
9412 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9413 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9414 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9415 nl_send_auto(nl.socket, msg);
9416 nl_recvmsgs(nl.socket, nl.cb);
9417 nlmsg_free(msg);
9418 nlfree(&nl);
9419 return RETURN_OK;
9420#else
9421 //TODO Implement me
9422 return RETURN_OK;
9423#endif
9424}
9425
9426INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9427{
9428 // TODO Implement me!
9429 char buf[MAX_BUF_SIZE] = {0};
9430 char config_file[MAX_BUF_SIZE] = {0};
9431
9432 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9433 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9434 *activate = (strncmp("1",buf,1) == 0);
9435
9436 return RETURN_OK;
9437}
9438
9439INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9440{
9441 char config_file[MAX_BUF_SIZE] = {0};
9442 struct params list;
9443
9444 list.name = "rrm_neighbor_report";
9445 list.value = activate?"1":"0";
9446 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9447 wifi_hostapdWrite(config_file, &list, 1);
9448
9449 return RETURN_OK;
9450}
9451
9452INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9453{
9454 char buf[32] = {0};
9455 char config_file[MAX_BUF_SIZE] = {0};
9456
9457 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9458 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9459 *activate = (strncmp("1",buf,1) == 0);
9460
9461 return RETURN_OK;
9462}
9463#undef HAL_NETLINK_IMPL
9464#ifdef HAL_NETLINK_IMPL
9465static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9466 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9467 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9468 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9469 char dev[20];
9470 int freq =0 ;
9471 static int i=0;
9472
9473 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9474
9475 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9476 };
9477
9478 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9479
9480 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9481
9482 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9483 fprintf(stderr, "survey data missing!\n");
9484 return NL_SKIP;
9485 }
9486
9487 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9488 {
9489 fprintf(stderr, "failed to parse nested attributes!\n");
9490 return NL_SKIP;
9491 }
9492
9493
9494 if(out[0].array_size == 1 )
9495 {
9496 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9497 {
9498 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9499 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9500 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9501
9502 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9503 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9504 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9505 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9506 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9507 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9508 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9509 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9510 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9511 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9512 if (sinfo[NL80211_SURVEY_INFO_TIME])
9513 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9514 return NL_STOP;
9515 }
9516 }
9517 else
9518 {
9519 if ( i <= out[0].array_size )
9520 {
9521 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9522 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9523 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9524
9525 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9526 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9527 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9528 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9529 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9530 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9531 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9532 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9533 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9534 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9535 if (sinfo[NL80211_SURVEY_INFO_TIME])
9536 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9537 }
9538 }
9539
9540 i++;
9541 return NL_SKIP;
9542}
9543#endif
9544
9545static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9546{
9547 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9548 FILE *fp;
9549
9550 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9551 {
9552 printf("Creating Frequency-Channel Map\n");
9553 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9554 }
9555 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9556 if((fp = popen(command, "r")))
9557 {
9558 fgets(output, sizeof(output), fp);
9559 *freqMHz = atoi(output);
9560 fclose(fp);
9561 }
9562
9563 return 0;
9564}
9565
9566static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9567{
9568 int freqMHz = -1;
9569 char cmd[MAX_CMD_SIZE] = {'\0'};
9570
9571 ieee80211_channel_to_frequency(channel, &freqMHz);
9572 if (freqMHz == -1) {
9573 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9574 return -1;
9575 }
9576
9577 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9578 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9579 radioIndex, freqMHz);
9580 return -1;
9581 }
9582
9583 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9584 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9585 return -1;
9586 }
9587
9588 return 0;
9589}
9590
9591static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9592{
9593 const char *ptr = buf;
9594 char *key = NULL;
9595 char *val = NULL;
9596 char line[256] = { '\0' };
9597
9598 while (ptr = get_line_from_str_buf(ptr, line)) {
9599 if (strstr(line, "Frequency")) continue;
9600
9601 key = strtok(line, ":");
9602 val = strtok(NULL, " ");
9603 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9604
9605 if (!strcmp(key, "noise")) {
9606 sscanf(val, "%d", &stats->ch_noise);
9607 if (stats->ch_noise == 0) {
9608 // Workaround for missing noise information.
9609 // Assume -95 for 2.4G and -103 for 5G
9610 if (radioIndex == 0) stats->ch_noise = -95;
9611 if (radioIndex == 1) stats->ch_noise = -103;
9612 }
9613 }
9614 else if (!strcmp(key, "channel active time")) {
9615 sscanf(val, "%llu", &stats->ch_utilization_total);
9616 }
9617 else if (!strcmp(key, "channel busy time")) {
9618 sscanf(val, "%llu", &stats->ch_utilization_busy);
9619 }
9620 else if (!strcmp(key, "channel receive time")) {
9621 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9622 }
9623 else if (!strcmp(key, "channel transmit time")) {
9624 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9625 }
9626 };
9627
9628 return 0;
9629}
9630
9631INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9632{
9633 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9634#ifdef HAL_NETLINK_IMPL
9635 Netlink nl;
9636 wifi_channelStats_t_loc local[array_size];
9637 char if_name[10];
9638
9639 local[0].array_size = array_size;
9640
9641 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9642
9643 nl.id = initSock80211(&nl);
9644
9645 if (nl.id < 0) {
9646 fprintf(stderr, "Error initializing netlink \n");
9647 return -1;
9648 }
9649
9650 struct nl_msg* msg = nlmsg_alloc();
9651
9652 if (!msg) {
9653 fprintf(stderr, "Failed to allocate netlink message.\n");
9654 nlfree(&nl);
9655 return -2;
9656 }
9657
9658 genlmsg_put(msg,
9659 NL_AUTO_PORT,
9660 NL_AUTO_SEQ,
9661 nl.id,
9662 0,
9663 NLM_F_DUMP,
9664 NL80211_CMD_GET_SURVEY,
9665 0);
9666
9667 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9668 nl_send_auto(nl.socket, msg);
9669 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9670 nl_recvmsgs(nl.socket, nl.cb);
9671 nlmsg_free(msg);
9672 nlfree(&nl);
9673 //Copying the Values
9674 for(int i=0;i<array_size;i++)
9675 {
9676 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9677 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9678 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9679 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9680 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9681 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9682 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9683 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9684 }
9685#else
9686 ULONG channel = 0;
9687 int i;
9688 int number_of_channels = array_size;
9689 char buf[512];
9690 INT ret;
9691 wifi_channelStats_t tmp_stats;
9692
9693 if (number_of_channels == 0) {
9694 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9695 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9696 return RETURN_ERR;
9697 }
9698 number_of_channels = 1;
9699 input_output_channelStats_array[0].ch_number = channel;
9700 }
9701
9702 for (i = 0; i < number_of_channels; i++) {
9703
9704 input_output_channelStats_array[i].ch_noise = 0;
9705 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9706 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9707 input_output_channelStats_array[i].ch_utilization_busy = 0;
9708 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9709 input_output_channelStats_array[i].ch_utilization_total = 0;
9710
9711 memset(buf, 0, sizeof(buf));
9712 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9713 return RETURN_ERR;
9714 }
9715 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9716 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9717 return RETURN_ERR;
9718 }
9719
9720 // XXX: fake missing 'self' counter which is not available in iw survey output
9721 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9722 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9723
9724 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9725 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9726 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9727 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9728 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9729
9730 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",
9731 __func__,
9732 input_output_channelStats_array[i].ch_number,
9733 input_output_channelStats_array[i].ch_noise,
9734 input_output_channelStats_array[i].ch_utilization_total,
9735 input_output_channelStats_array[i].ch_utilization_busy,
9736 input_output_channelStats_array[i].ch_utilization_busy_rx,
9737 input_output_channelStats_array[i].ch_utilization_busy_tx,
9738 input_output_channelStats_array[i].ch_utilization_busy_self,
9739 input_output_channelStats_array[i].ch_utilization_busy_ext);
9740 }
9741#endif
9742 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9743 return RETURN_OK;
9744}
9745#define HAL_NETLINK_IMPL
9746
9747/* Hostapd events */
9748
9749#ifndef container_of
9750#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9751#define container_of(ptr, type, member) \
9752 ((type *)((char *)ptr - offset_of(type, member)))
9753#endif /* container_of */
9754
9755struct ctrl {
9756 char sockpath[128];
9757 char sockdir[128];
9758 char bss[IFNAMSIZ];
9759 char reply[4096];
9760 int ssid_index;
9761 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9762 void (*overrun)(struct ctrl *ctrl);
9763 struct wpa_ctrl *wpa;
9764 unsigned int ovfl;
9765 size_t reply_len;
9766 int initialized;
9767 ev_timer retry;
9768 ev_timer watchdog;
9769 ev_stat stat;
9770 ev_io io;
9771};
9772static wifi_newApAssociatedDevice_callback clients_connect_cb;
9773static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9774static struct ctrl wpa_ctrl[MAX_APS];
9775static int initialized;
9776
9777static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9778{
9779 char cbuf[256] = {};
9780 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9781 struct cmsghdr *cmsg;
9782 unsigned int ovfl = ctrl->ovfl;
9783 unsigned int drop;
9784
9785 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9786 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9787 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9788 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9789
9790 drop = ovfl - ctrl->ovfl;
9791 ctrl->ovfl = ovfl;
9792
9793 return drop;
9794}
9795
9796static void ctrl_close(struct ctrl *ctrl)
9797{
9798 if (ctrl->io.cb)
9799 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9800 if (ctrl->retry.cb)
9801 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9802 if (!ctrl->wpa)
9803 return;
9804
9805 wpa_ctrl_detach(ctrl->wpa);
9806 wpa_ctrl_close(ctrl->wpa);
9807 ctrl->wpa = NULL;
9808 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9809}
9810
9811static void ctrl_process(struct ctrl *ctrl)
9812{
9813 const char *str;
9814 int drops;
9815 int level;
9816 int err;
9817
9818 /* Example events:
9819 *
9820 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9821 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9822 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9823 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9824 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9825 */
9826 if (!(str = index(ctrl->reply, '>')))
9827 return;
9828 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9829 return;
9830
9831 str++;
9832
9833 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9834 if (!(str = index(ctrl->reply, ' ')))
9835 return;
9836 wifi_associated_dev_t sta;
9837 memset(&sta, 0, sizeof(sta));
9838
9839 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9840 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9841 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9842
9843 sta.cli_Active=true;
9844
9845 (clients_connect_cb)(ctrl->ssid_index, &sta);
9846 goto handled;
9847 }
9848
9849 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
9850 if (!(str = index(ctrl->reply, ' ')))
9851 return;
9852
9853 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
9854 goto handled;
9855 }
9856
9857 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
9858 printf("CTRL_WPA: handle TERMINATING event\n");
9859 goto retry;
9860 }
9861
9862 if (strncmp("AP-DISABLED", str, 11) == 0) {
9863 printf("CTRL_WPA: handle AP-DISABLED\n");
9864 goto retry;
9865 }
9866
9867 printf("Event not supported!!\n");
9868
9869handled:
9870
9871 if ((drops = ctrl_get_drops(ctrl))) {
9872 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
9873 if (ctrl->overrun)
9874 ctrl->overrun(ctrl);
9875 }
9876
9877 return;
9878
9879retry:
9880 printf("WPA_CTRL: closing\n");
9881 ctrl_close(ctrl);
9882 printf("WPA_CTRL: retrying from ctrl prcoess\n");
9883 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
9884}
9885
9886static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
9887{
9888 struct ctrl *ctrl = container_of(io, struct ctrl, io);
9889 int err;
9890
9891 memset(ctrl->reply, 0, sizeof(ctrl->reply));
9892 ctrl->reply_len = sizeof(ctrl->reply) - 1;
9893 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
9894 ctrl->reply[ctrl->reply_len] = 0;
9895 if (err < 0) {
9896 if (errno == EAGAIN || errno == EWOULDBLOCK)
9897 return;
9898 ctrl_close(ctrl);
9899 ev_timer_again(EV_A_ &ctrl->retry);
9900 return;
9901 }
9902
9903 ctrl_process(ctrl);
9904}
9905
9906static int ctrl_open(struct ctrl *ctrl)
9907{
9908 int fd;
9909
9910 if (ctrl->wpa)
9911 return 0;
9912
9913 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
9914 if (!ctrl->wpa)
9915 goto err;
9916
9917 if (wpa_ctrl_attach(ctrl->wpa) < 0)
9918 goto err_close;
9919
9920 fd = wpa_ctrl_get_fd(ctrl->wpa);
9921 if (fd < 0)
9922 goto err_detach;
9923
9924 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
9925 goto err_detach;
9926
9927 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
9928 ev_io_start(EV_DEFAULT_ &ctrl->io);
9929
9930 return 0;
9931
9932err_detach:
9933 wpa_ctrl_detach(ctrl->wpa);
9934err_close:
9935 wpa_ctrl_close(ctrl->wpa);
9936err:
9937 ctrl->wpa = NULL;
9938 return -1;
9939}
9940
9941static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
9942{
9943 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
9944
9945 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
9946 ctrl_open(ctrl);
9947}
9948
9949static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
9950{
9951 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
9952
9953 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
9954 if (ctrl_open(ctrl) == 0) {
9955 printf("WPA_CTRL: retry successful\n");
9956 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9957 }
9958}
9959
9960int ctrl_enable(struct ctrl *ctrl)
9961{
9962 if (ctrl->wpa)
9963 return 0;
9964
9965 if (!ctrl->stat.cb) {
9966 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
9967 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
9968 }
9969
9970 if (!ctrl->retry.cb) {
9971 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
9972 }
9973
9974 return ctrl_open(ctrl);
9975}
9976
9977static void
9978ctrl_msg_cb(char *buf, size_t len)
9979{
9980 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
9981
9982 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
9983 ctrl_process(ctrl);
9984}
9985
9986static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
9987{
9988 int err;
9989
9990 if (!ctrl->wpa)
9991 return -1;
9992 if (*reply_len < 2)
9993 return -1;
9994
9995 (*reply_len)--;
9996 ctrl->reply_len = sizeof(ctrl->reply);
9997 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
9998 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
9999 if (err < 0)
10000 return err;
10001
10002 if (ctrl->reply_len > *reply_len)
10003 ctrl->reply_len = *reply_len;
10004
10005 *reply_len = ctrl->reply_len;
10006 memcpy(reply, ctrl->reply, *reply_len);
10007 reply[*reply_len - 1] = 0;
10008 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10009 return 0;
10010}
10011
10012static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10013{
10014 const char *pong = "PONG";
10015 const char *ping = "PING";
10016 char reply[1024];
10017 size_t len = sizeof(reply);
10018 int err;
10019 ULONG s, snum;
10020 INT ret;
10021 BOOL status;
10022
10023 printf("WPA_CTRL: watchdog cb\n");
10024
10025 ret = wifi_getSSIDNumberOfEntries(&snum);
10026 if (ret != RETURN_OK) {
10027 printf("%s: failed to get SSID count", __func__);
10028 return;
10029 }
10030
10031 if (snum > MAX_APS) {
10032 printf("more ssid than supported! %lu\n", snum);
10033 return;
10034 }
10035
10036 for (s = 0; s < snum; s++) {
10037 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10038 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10039 continue;
10040 }
10041 if (status == false) continue;
10042
10043 memset(reply, 0, sizeof(reply));
10044 len = sizeof(reply);
10045 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10046 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10047 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10048 continue;
10049
10050 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10051 ctrl_close(&wpa_ctrl[s]);
10052 printf("WPA_CTRL: ev_timer_again %d\n", s);
10053 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10054 }
10055}
10056
10057static int init_wpa()
10058{
10059 int ret = 0, i = 0;
10060 ULONG s, snum;
10061
10062 ret = wifi_getSSIDNumberOfEntries(&snum);
10063 if (ret != RETURN_OK) {
10064 printf("%s: failed to get SSID count", __func__);
10065 return RETURN_ERR;
10066 }
10067
10068 if (snum > MAX_APS) {
10069 printf("more ssid than supported! %lu\n", snum);
10070 return RETURN_ERR;
10071 }
10072
10073 for (s = 0; s < snum; s++) {
10074 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10075 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10076 wpa_ctrl[s].ssid_index = s;
10077 ctrl_enable(&wpa_ctrl[s]);
10078 }
10079
10080 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10081 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10082
10083 initialized = 1;
10084 printf("WPA_CTRL: initialized\n");
10085
10086 return RETURN_OK;
10087}
10088
10089void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10090{
10091 clients_connect_cb = callback_proc;
10092 if (!initialized)
10093 init_wpa();
10094}
10095
10096void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10097{
10098 clients_disconnect_cb = callback_proc;
10099 if (!initialized)
10100 init_wpa();
10101}
10102
10103INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10104{
10105 // TODO Implement me!
10106 return RETURN_ERR;
10107}
10108
10109INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10110{
10111 // TODO Implement me!
10112 return RETURN_ERR;
10113}
10114
10115INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10116{
10117 int i;
10118 char cmd[256];
10119 char channel_numbers_buf[256];
10120 char dfs_state_buf[256];
10121 char line[256];
10122 const char *ptr;
10123
10124 memset(cmd, 0, sizeof(cmd));
10125 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10126 memset(line, 0, sizeof(line));
10127 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10128 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10129
10130 if (radioIndex == 0) { // 2.4G - all allowed
10131 if (outputMapSize < 11) {
10132 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10133 return RETURN_ERR;
10134 }
10135
10136 for (i = 0; i < 11; i++) {
10137 outputMap[i].ch_number = i + 1;
10138 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10139 }
10140
10141 return RETURN_OK;
10142 }
10143
10144 if (radioIndex == 1) { // 5G
10145// Example output of iw list:
10146//
10147// Frequencies:
10148// * 5180 MHz [36] (17.0 dBm)
10149// * 5200 MHz [40] (17.0 dBm)
10150// * 5220 MHz [44] (17.0 dBm)
10151// * 5240 MHz [48] (17.0 dBm)
10152// * 5260 MHz [52] (23.0 dBm) (radar detection)
10153// DFS state: usable (for 78930 sec)
10154// DFS CAC time: 60000 ms
10155// * 5280 MHz [56] (23.0 dBm) (radar detection)
10156// DFS state: usable (for 78930 sec)
10157// DFS CAC time: 60000 ms
10158// * 5300 MHz [60] (23.0 dBm) (radar detection)
10159// DFS state: usable (for 78930 sec)
10160// DFS CAC time: 60000 ms
10161// * 5320 MHz [64] (23.0 dBm) (radar detection)
10162// DFS state: usable (for 78930 sec)
10163// DFS CAC time: 60000 ms
10164// * 5500 MHz [100] (disabled)
10165// * 5520 MHz [104] (disabled)
10166// * 5540 MHz [108] (disabled)
10167// * 5560 MHz [112] (disabled)
10168//
10169// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10170 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10171 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10172 return RETURN_ERR;
10173 }
10174
10175 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10176 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10177 return RETURN_ERR;
10178 }
10179
10180 ptr = channel_numbers_buf;
10181 i = 0;
10182 while (ptr = get_line_from_str_buf(ptr, line)) {
10183 if (i >= outputMapSize) {
10184 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10185 return RETURN_ERR;
10186 }
10187 sscanf(line, "%d", &outputMap[i].ch_number);
10188
10189 memset(cmd, 0, sizeof(cmd));
10190 // Below command should fetch string for DFS state (usable, available or unavailable)
10191 // Example line: "DFS state: usable (for 78930 sec)"
10192 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) {
10193 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10194 return RETURN_ERR;
10195 }
10196
10197 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10198 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10199 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10200 return RETURN_ERR;
10201 }
10202
10203 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10204
10205 if (!strcmp(dfs_state_buf, "usable")) {
10206 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10207 } else if (!strcmp(dfs_state_buf, "available")) {
10208 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10209 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10210 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10211 } else {
10212 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10213 }
10214 i++;
10215 }
10216
10217 return RETURN_OK;
10218 }
10219
10220 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10221 return RETURN_ERR;
10222}
10223
10224INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10225{
10226 // TODO Implement me!
10227 return RETURN_ERR;
10228}
10229
10230INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10231{
10232 return RETURN_OK;
10233}
10234
10235INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10236{
10237 // TODO Implement me!
10238 return RETURN_ERR;
10239}
10240
10241INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10242{
10243 // TODO API refrence Implementaion is present on RPI hal
10244 return RETURN_ERR;
10245}
10246
10247INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10248{
developera5005b62022-09-13 15:43:35 +080010249 char cmd[128]={'\0'};
10250 char buf[128]={'\0'};
10251 char *support;
10252 int maximum_tx = 0, current_tx = 0;
10253
10254 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10255 if(txpwr_pcntg == NULL)
10256 return RETURN_ERR;
10257
10258 // Get the maximum tx power of the device
10259 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10260 _syscmd(cmd, buf, sizeof(buf));
10261 maximum_tx = strtol(buf, NULL, 10);
10262
10263 // Get the current tx power
10264 memset(cmd, 0, sizeof(cmd));
10265 memset(buf, 0, sizeof(buf));
10266 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10267 _syscmd(cmd, buf, sizeof(buf));
10268 current_tx = strtol(buf, NULL, 10);
10269
10270 // Get the power supported list and find the current power percentage in supported list
10271 memset(buf, 0, sizeof(buf));
10272 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10273 support = strtok(buf, ",");
10274 while(true)
10275 {
10276 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10277 *txpwr_pcntg = 0;
10278 wifi_dbg_printf("current power is not in supported list\n");
10279 return RETURN_ERR;
10280 }
10281 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10282 if (tmp == current_tx) {
10283 *txpwr_pcntg = strtol(support, NULL, 10);
10284 break;
10285 }
10286 support = strtok(NULL, ",");
10287 }
10288 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010289 return RETURN_OK;
10290}
10291
10292INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10293{
developer58599c22022-09-13 16:40:34 +080010294 // TODO precac feature.
10295 struct params params = {0};
10296 char config_file[128] = {0};
10297
10298 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10299
10300 params.name = "enable_background_radar";
10301 params.value = enable?"1":"0";
10302 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10303 wifi_hostapdWrite(config_file, &params, 1);
10304 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10305
10306 /* TODO precac feature */
10307
10308 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10309 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010310}
10311
10312INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10313{
developer58599c22022-09-13 16:40:34 +080010314 char config_file[128] = {0};
10315 char buf[64] = {0};
10316
10317 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10318 if (NULL == enable || NULL == precac)
10319 return RETURN_ERR;
10320
10321 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10322 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10323 if (strncmp(enable, "1", 1) == 0)
10324 *enable = true;
10325 else
10326 *enable = false;
10327
10328 /* TODO precac feature */
10329
10330 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10331 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010332}
10333
10334INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10335{
developer58599c22022-09-13 16:40:34 +080010336 *supported = TRUE;
10337 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010338}
10339
developer454b9462022-09-13 15:29:16 +080010340INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10341{
10342 char cmd[128] = {0};
10343 char buf[64] = {0};
10344 char band_str[8] = {0};
10345 char GI[8] = {0};
10346 int tmp = 0;
10347 BOOL ax_mode = FALSE;
10348 BOOL short_GI = FALSE;
10349 FILE *f = NULL;
10350 wifi_band band;
10351
10352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10353
10354 if (wifi_getRadioMode(radio_index, buf, &tmp) == RETURN_ERR) {
10355 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10356 return RETURN_ERR;
10357 }
10358 if (strstr(buf, "ax") != NULL)
10359 ax_mode = TRUE;
10360
10361 if (guard_interval == wifi_guard_interval_400 && ax_mode != TRUE) {
10362 short_GI = TRUE;
10363 strcpy(GI, "0.4");
10364 } else if (guard_interval == wifi_guard_interval_1600 && ax_mode == TRUE)
10365 strcpy(GI, "1.6");
10366 else if (guard_interval == wifi_guard_interval_3200 && ax_mode == TRUE)
10367 strcpy(GI, "3.2");
10368 else // default
10369 strcpy(GI, "0.8");
10370
10371 band = wifi_index_to_band(radio_index);
10372 if (band == band_2_4)
10373 strcpy(band_str, "2.4");
10374 else if (band == band_5)
10375 strcpy(band_str, "5");
10376 else if (band == band_6)
10377 strcpy(band_str, "6");
10378 else {
10379 wifi_dbg_printf("%s: invalid band\n");
10380 return RETURN_ERR;
10381 }
10382
10383 if (ax_mode == TRUE)
10384 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates he-gi-%s %s", AP_PREFIX, radio_index, band_str, GI);
10385 else
10386 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates %sgi-%s", AP_PREFIX, radio_index, (short_GI)?"s":"l", band_str);
10387 _syscmd(cmd, buf, sizeof(buf));
10388
10389 // Record GI for get GI function
10390 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10391 f = fopen(buf, "w");
10392 if (f != NULL) {
10393 fprintf(f, "%s", GI);
10394 }
10395 fclose(f);
10396 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10397 return RETURN_OK;
10398}
10399
10400INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10401{
10402 char buf[32] = {0};
10403 char cmd[64] = {0};
10404
10405 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10406
10407 if (guard_interval == NULL)
10408 return RETURN_ERR;
10409
10410 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10411 _syscmd(cmd, buf, sizeof(buf));
10412
10413 if (strncmp(buf, "0.4", 3) == 0)
10414 *guard_interval = wifi_guard_interval_400;
10415 else if (strncmp(buf, "0.8", 3) == 0)
10416 *guard_interval = wifi_guard_interval_800;
10417 else if (strncmp(buf, "1.6", 3) == 0)
10418 *guard_interval = wifi_guard_interval_1600;
10419 else if (strncmp(buf, "3.2", 3) == 0)
10420 *guard_interval = wifi_guard_interval_3200;
10421 else
10422 *guard_interval = wifi_guard_interval_auto;
10423
10424 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10425 return RETURN_OK;
10426}
10427
developer3cc61d12022-09-13 16:36:05 +080010428INT wifi_setBSSColor(INT radio_index, UCHAR color)
10429{
10430 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10431 struct params params = {0};
10432 char config_file[128] = {0};
10433 char bss_color[4] ={0};
10434
10435 params.name = "he_bss_color";
10436 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10437 params.value = bss_color;
10438 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10439 wifi_hostapdWrite(config_file, &params, 1);
10440 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10441
10442 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10443 return RETURN_OK;
10444}
10445
10446INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10447{
10448 char config_file[128] = {0};
10449 char buf[64] = {0};
10450 char temp_output[128] = {'\0'};
10451
10452 wifi_dbg_printf("\nFunc=%s\n", __func__);
10453 if (NULL == color)
10454 return RETURN_ERR;
10455
10456 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10457 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10458
10459 if(strlen(buf) > 0) {
10460 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10461 } else {
10462 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10463 }
10464
10465 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10466 wifi_dbg_printf("\noutput_string=%s\n", color);
10467
10468 return RETURN_OK;
10469}
10470
developer06a01d92022-09-07 16:32:39 +080010471/* multi-psk support */
10472INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10473{
10474 char cmd[256];
10475
10476 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10477 AP_PREFIX,
10478 apIndex,
10479 mac[0],
10480 mac[1],
10481 mac[2],
10482 mac[3],
10483 mac[4],
10484 mac[5]
10485 );
10486 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10487 _syscmd(cmd, key->wifi_keyId, 64);
10488
10489
10490 return RETURN_OK;
10491}
10492
10493INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10494{
10495 FILE *fd = NULL;
10496 char fname[100];
10497 char cmd[128] = {0};
10498 char out[64] = {0};
10499 wifi_key_multi_psk_t * key = NULL;
10500 if(keysNumber < 0)
10501 return RETURN_ERR;
10502
10503 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10504 fd = fopen(fname, "w");
10505 if (!fd) {
10506 return RETURN_ERR;
10507 }
10508 key= (wifi_key_multi_psk_t *) keys;
10509 for(int i=0; i<keysNumber; ++i, key++) {
10510 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10511 }
10512 fclose(fd);
10513
10514 //reload file
10515 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10516 _syscmd(cmd, out, 64);
10517 return RETURN_OK;
10518}
10519
10520INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10521{
10522 FILE *fd = NULL;
10523 char fname[100];
10524 char * line = NULL;
10525 char * pos = NULL;
10526 size_t len = 0;
10527 ssize_t read = 0;
10528 INT ret = RETURN_OK;
10529 wifi_key_multi_psk_t *keys_it = NULL;
10530
10531 if (keysNumber < 1) {
10532 return RETURN_ERR;
10533 }
10534
10535 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10536 fd = fopen(fname, "r");
10537 if (!fd) {
10538 return RETURN_ERR;
10539 }
10540
10541 if (keys == NULL) {
10542 ret = RETURN_ERR;
10543 goto close;
10544 }
10545
10546 keys_it = keys;
10547 while ((read = getline(&line, &len, fd)) != -1) {
10548 //Strip trailing new line if present
10549 if (read > 0 && line[read-1] == '\n') {
10550 line[read-1] = '\0';
10551 }
10552
10553 if(strcmp(line,"keyid=")) {
10554 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10555 if (!(pos = index(line, ' '))) {
10556 ret = RETURN_ERR;
10557 goto close;
10558 }
10559 pos++;
10560 //Here should be 00:00:00:00:00:00
10561 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10562 printf("Not supported MAC: %s\n", pos);
10563 }
10564 if (!(pos = index(pos, ' '))) {
10565 ret = RETURN_ERR;
10566 goto close;
10567 }
10568 pos++;
10569
10570 //The rest is PSK
10571 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10572 keys_it++;
10573
10574 if(--keysNumber <= 0)
10575 break;
10576 }
10577 }
10578
10579close:
10580 free(line);
10581 fclose(fd);
10582 return ret;
10583}
10584/* end of multi-psk support */
10585
10586INT wifi_setNeighborReports(UINT apIndex,
10587 UINT numNeighborReports,
10588 wifi_NeighborReport_t *neighborReports)
10589{
10590 char cmd[256] = { 0 };
10591 char hex_bssid[13] = { 0 };
10592 char bssid[18] = { 0 };
10593 char nr[256] = { 0 };
10594 char ssid[256];
10595 char hex_ssid[256];
10596 INT ret;
10597
10598 /*rmeove all neighbors*/
10599 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10600 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);
10601 system(cmd);
10602
10603 for(unsigned int i = 0; i < numNeighborReports; i++)
10604 {
10605 memset(ssid, 0, sizeof(ssid));
10606 ret = wifi_getSSIDName(apIndex, ssid);
10607 if (ret != RETURN_OK)
10608 return RETURN_ERR;
10609
10610 memset(hex_ssid, 0, sizeof(hex_ssid));
10611 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10612 sprintf(hex_ssid + k,"%02x", ssid[j]);
10613
10614 snprintf(hex_bssid, sizeof(hex_bssid),
10615 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10616 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10617 snprintf(bssid, sizeof(bssid),
10618 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10619 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10620
10621 snprintf(nr, sizeof(nr),
10622 "%s" // bssid
10623 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10624 "%02hhx" // operclass
10625 "%02hhx" // channel
10626 "%02hhx", // phy_mode
10627 hex_bssid,
10628 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10629 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10630 neighborReports[i].opClass,
10631 neighborReports[i].channel,
10632 neighborReports[i].phyTable);
10633
10634 snprintf(cmd, sizeof(cmd),
10635 "hostapd_cli set_neighbor "
10636 "%s " // bssid
10637 "ssid=%s " // ssid
10638 "nr=%s " // nr
10639 "-i %s%d",
10640 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10641
10642 if (WEXITSTATUS(system(cmd)) != 0)
10643 {
10644 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10645 }
10646 }
10647
10648 return RETURN_OK;
10649}
10650
10651INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10652{
10653 return RETURN_OK;
10654}
10655
10656#ifdef _WIFI_HAL_TEST_
10657int main(int argc,char **argv)
10658{
10659 int index;
10660 INT ret=0;
10661 char buf[1024]="";
10662
10663 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10664 if(argc<3)
10665 {
10666 if(argc==2)
10667 {
10668 if(!strcmp(argv[1], "init"))
10669 return wifi_init();
10670 if(!strcmp(argv[1], "reset"))
10671 return wifi_reset();
10672 if(!strcmp(argv[1], "wifi_getHalVersion"))
10673 {
10674 char buffer[64];
10675 if(wifi_getHalVersion(buffer)==RETURN_OK)
10676 printf("Version: %s\n", buffer);
10677 else
10678 printf("Error in wifi_getHalVersion\n");
10679 return RETURN_OK;
10680 }
10681 }
10682 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10683 exit(-1);
10684 }
10685
10686 index = atoi(argv[2]);
10687 if(strstr(argv[1], "wifi_getApName")!=NULL)
10688 {
10689 wifi_getApName(index,buf);
10690 printf("Ap name is %s \n",buf);
10691 return 0;
10692 }
10693 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
10694 {
10695 BOOL b = FALSE;
10696 BOOL *output_bool = &b;
10697 wifi_getRadioAutoChannelEnable(index,output_bool);
10698 printf("Channel enabled = %d \n",b);
10699 return 0;
10700 }
10701 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
10702 {
10703 wifi_getApWpaEncryptionMode(index,buf);
10704 printf("encryption enabled = %s\n",buf);
10705 return 0;
10706 }
10707 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
10708 {
10709 BOOL b = FALSE;
10710 BOOL *output_bool = &b;
10711 wifi_getApSsidAdvertisementEnable(index,output_bool);
10712 printf("advertisment enabled = %d\n",b);
10713 return 0;
10714 }
10715 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
10716 {
10717 if(argc <= 3 )
10718 {
10719 printf("Insufficient arguments \n");
10720 exit(-1);
10721 }
10722
10723 char sta[20] = {'\0'};
10724 ULLONG handle= 0;
10725 strcpy(sta,argv[3]);
10726 mac_address_t st;
10727 mac_addr_aton(st,sta);
10728
10729 wifi_associated_dev_tid_stats_t tid_stats;
10730 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
10731 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
10732 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);
10733 }
10734
10735 if(strstr(argv[1], "getApEnable")!=NULL) {
10736 BOOL enable;
10737 ret=wifi_getApEnable(index, &enable);
10738 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10739 }
10740 else if(strstr(argv[1], "setApEnable")!=NULL) {
10741 BOOL enable = atoi(argv[3]);
10742 ret=wifi_setApEnable(index, enable);
10743 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10744 }
10745 else if(strstr(argv[1], "getApStatus")!=NULL) {
10746 char status[64];
10747 ret=wifi_getApStatus(index, status);
10748 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
10749 }
10750 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
10751 {
10752 wifi_getSSIDNameStatus(index,buf);
10753 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
10754 return 0;
10755 }
10756 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
10757 wifi_ssidTrafficStats2_t stats={0};
10758 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
10759 printf("%s %d: returns %d\n", argv[1], index, ret);
10760 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
10761 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
10762 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
10763 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
10764 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
10765 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
10766 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
10767 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
10768 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
10769 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
10770 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
10771 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
10772 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
10773 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
10774 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
10775 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
10776 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
10777 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
10778 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
10779 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
10780 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
10781 }
10782 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
10783 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
10784 UINT array_size=0;
10785 UINT i=0;
10786 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
10787 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10788 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
10789 printf(" neighbor %d:\n", i);
10790 printf(" ap_SSID =%s\n", pt->ap_SSID);
10791 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
10792 printf(" ap_Mode =%s\n", pt->ap_Mode);
10793 printf(" ap_Channel =%d\n", pt->ap_Channel);
10794 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
10795 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10796 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
10797 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
10798 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
10799 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
10800 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10801 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
10802 printf(" ap_Noise =%d\n", pt->ap_Noise);
10803 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
10804 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
10805 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
10806 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
10807 }
10808 if(neighbor_ap_array)
10809 free(neighbor_ap_array); //make sure to free the list
10810 }
10811 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
10812 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
10813 UINT array_size=0;
10814 UINT i=0;
10815 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
10816 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10817 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
10818 printf(" associated_dev %d:\n", i);
10819 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
10820 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
10821 printf(" cli_SNR =%d\n", pt->cli_SNR);
10822 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
10823 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
10824 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
10825 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
10826 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
10827 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
10828 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
10829 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
10830 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
10831 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
10832 }
10833 if(associated_dev_array)
10834 free(associated_dev_array); //make sure to free the list
10835 }
10836
10837 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
10838 {
10839#define MAX_ARRAY_SIZE 64
10840 int i, array_size;
10841 char *p, *ch_str;
10842 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
10843
10844 if(argc != 5)
10845 {
10846 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
10847 exit(-1);
10848 }
10849 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
10850
10851 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
10852 {
10853 strtok_r(ch_str, ",", &p);
10854 input_output_channelStats_array[i].ch_number = atoi(ch_str);
10855 }
10856 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
10857 if(!array_size)
10858 array_size=1;//Need to print current channel statistics
10859 for(i=0; i<array_size; i++)
10860 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
10861 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
10862 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
10863 input_output_channelStats_array[i].ch_number,\
10864 input_output_channelStats_array[i].ch_noise,\
10865 input_output_channelStats_array[i].ch_utilization_busy_rx,\
10866 input_output_channelStats_array[i].ch_utilization_busy_tx,\
10867 input_output_channelStats_array[i].ch_utilization_busy,\
10868 input_output_channelStats_array[i].ch_utilization_busy_ext,\
10869 input_output_channelStats_array[i].ch_utilization_total);
10870 }
10871
10872 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
10873 {
10874 if(argc <= 3 )
10875 {
10876 printf("Insufficient arguments \n");
10877 exit(-1);
10878 }
10879 char mac_addr[20] = {'\0'};
10880 wifi_device_t output_struct;
10881 int dev_index = atoi(argv[3]);
10882
10883 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
10884 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
10885 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);
10886 }
10887
10888 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
10889 {
10890 if (argc <= 3)
10891 {
10892 printf("Insufficient arguments\n");
10893 exit(-1);
10894 }
10895 char args[256];
10896 wifi_NeighborReport_t *neighborReports;
10897
10898 neighborReports = calloc(argc - 2, sizeof(neighborReports));
10899 if (!neighborReports)
10900 {
10901 printf("Failed to allocate memory");
10902 exit(-1);
10903 }
10904
10905 for (int i = 3; i < argc; ++i)
10906 {
10907 char *val;
10908 int j = 0;
10909 memset(args, 0, sizeof(args));
10910 strncpy(args, argv[i], sizeof(args));
10911 val = strtok(args, ";");
10912 while (val != NULL)
10913 {
10914 if (j == 0)
10915 {
10916 mac_addr_aton(neighborReports[i - 3].bssid, val);
10917 } else if (j == 1)
10918 {
10919 neighborReports[i - 3].info = strtol(val, NULL, 16);
10920 } else if (j == 2)
10921 {
10922 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
10923 } else if (j == 3)
10924 {
10925 neighborReports[i - 3].channel = strtol(val, NULL, 16);
10926 } else if (j == 4)
10927 {
10928 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
10929 } else {
10930 printf("Insufficient arguments]n\n");
10931 exit(-1);
10932 }
10933 val = strtok(NULL, ";");
10934 j++;
10935 }
10936 }
10937
10938 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
10939 if (ret != RETURN_OK)
10940 {
10941 printf("wifi_setNeighborReports ret = %d", ret);
10942 exit(-1);
10943 }
10944 }
10945 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
10946 {
10947 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
10948 printf("%s.\n", buf);
10949 else
10950 printf("Error returned\n");
10951 }
10952 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
10953 {
10954 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
10955 printf("%s.\n", buf);
10956 else
10957 printf("Error returned\n");
10958 }
10959 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
10960 {
10961 if (argc <= 2)
10962 {
10963 printf("Insufficient arguments\n");
10964 exit(-1);
10965 }
10966 char buf[64]= {'\0'};
10967 wifi_getRadioOperatingChannelBandwidth(index,buf);
10968 printf("Current bandwidth is %s \n",buf);
10969 return 0;
10970 }
10971 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
10972 {
10973 if (argc <= 5)
10974 {
10975 printf("Insufficient arguments\n");
10976 exit(-1);
10977 }
10978 UINT channel = atoi(argv[3]);
10979 UINT width = atoi(argv[4]);
10980 UINT beacon = atoi(argv[5]);
10981 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
10982 printf("Result = %d", ret);
10983 }
10984
10985 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10986 return 0;
10987}
10988
10989#endif
10990
10991#ifdef WIFI_HAL_VERSION_3
10992
developer1e5aa162022-09-13 16:06:24 +080010993INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
10994{
10995 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10996 if (bitMap & WIFI_BITRATE_1MBPS)
10997 strcat(BasicRate, "1,");
10998 if (bitMap & WIFI_BITRATE_2MBPS)
10999 strcat(BasicRate, "2,");
11000 if (bitMap & WIFI_BITRATE_5_5MBPS)
11001 strcat(BasicRate, "5.5,");
11002 if (bitMap & WIFI_BITRATE_6MBPS)
11003 strcat(BasicRate, "6,");
11004 if (bitMap & WIFI_BITRATE_9MBPS)
11005 strcat(BasicRate, "9,");
11006 if (bitMap & WIFI_BITRATE_11MBPS)
11007 strcat(BasicRate, "11,");
11008 if (bitMap & WIFI_BITRATE_12MBPS)
11009 strcat(BasicRate, "12,");
11010 if (bitMap & WIFI_BITRATE_18MBPS)
11011 strcat(BasicRate, "18,");
11012 if (bitMap & WIFI_BITRATE_24MBPS)
11013 strcat(BasicRate, "24,");
11014 if (bitMap & WIFI_BITRATE_36MBPS)
11015 strcat(BasicRate, "36,");
11016 if (bitMap & WIFI_BITRATE_48MBPS)
11017 strcat(BasicRate, "48,");
11018 if (bitMap & WIFI_BITRATE_54MBPS)
11019 strcat(BasicRate, "54,");
11020 if (strlen(BasicRate) != 0) // remove last comma
11021 BasicRate[strlen(BasicRate) - 1] = '\0';
11022 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11023 return RETURN_OK;
11024}
11025
11026INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11027{
11028 UINT BitMap = 0;
11029 char *rate;
11030
11031 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11032 rate = strtok(BasicRatesList, ",");
11033 while(rate != NULL)
11034 {
11035 if (strcmp(rate, "1") == 0)
11036 BitMap |= WIFI_BITRATE_1MBPS;
11037 else if (strcmp(rate, "2") == 0)
11038 BitMap |= WIFI_BITRATE_2MBPS;
11039 else if (strcmp(rate, "5.5") == 0)
11040 BitMap |= WIFI_BITRATE_5_5MBPS;
11041 else if (strcmp(rate, "6") == 0)
11042 BitMap |= WIFI_BITRATE_6MBPS;
11043 else if (strcmp(rate, "9") == 0)
11044 BitMap |= WIFI_BITRATE_9MBPS;
11045 else if (strcmp(rate, "11") == 0)
11046 BitMap |= WIFI_BITRATE_11MBPS;
11047 else if (strcmp(rate, "12") == 0)
11048 BitMap |= WIFI_BITRATE_12MBPS;
11049 else if (strcmp(rate, "18") == 0)
11050 BitMap |= WIFI_BITRATE_18MBPS;
11051 else if (strcmp(rate, "24") == 0)
11052 BitMap |= WIFI_BITRATE_24MBPS;
11053 else if (strcmp(rate, "36") == 0)
11054 BitMap |= WIFI_BITRATE_36MBPS;
11055 else if (strcmp(rate, "48") == 0)
11056 BitMap |= WIFI_BITRATE_48MBPS;
11057 else if (strcmp(rate, "54") == 0)
11058 BitMap |= WIFI_BITRATE_54MBPS;
11059 rate = strtok(NULL, ",");
11060 }
11061 *basicRateBitMap = BitMap;
11062 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11063 return RETURN_OK;
11064}
11065
11066// 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 +080011067INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11068{
developer1e5aa162022-09-13 16:06:24 +080011069 char buf[128] = {0};
11070 char cmd[128] = {0};
11071 char config_file[64] = {0};
11072 int bandwidth;
11073 int set_mode;
11074 wifi_radio_operationParam_t current_param;
11075
11076 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11077
11078 multiple_set = TRUE;
11079 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11080 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11081 return RETURN_ERR;
11082 }
11083 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11084 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11085 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11086 return RETURN_ERR;
11087 }
11088 }
11089 if (current_param.channelWidth != operationParam->channelWidth || (current_param.channel != operationParam->channel && !operationParam->autoChannelEnabled)) {
11090 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11091 bandwidth = 20;
11092 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11093 bandwidth = 40;
11094 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11095 bandwidth = 80;
11096 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11097 bandwidth = 160;
11098 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11099 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11100 return RETURN_ERR;
11101 }
11102 }
11103 if (current_param.variant != operationParam->variant) {
11104 // Two different definition bit map, so need to check every bit.
11105 if (operationParam->variant & WIFI_80211_VARIANT_A)
11106 set_mode |= WIFI_MODE_A;
11107 if (operationParam->variant & WIFI_80211_VARIANT_B)
11108 set_mode |= WIFI_MODE_B;
11109 if (operationParam->variant & WIFI_80211_VARIANT_G)
11110 set_mode |= WIFI_MODE_G;
11111 if (operationParam->variant & WIFI_80211_VARIANT_N)
11112 set_mode |= WIFI_MODE_N;
11113 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11114 set_mode |= WIFI_MODE_AC;
11115 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11116 set_mode |= WIFI_MODE_AX;
11117 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11118 memset(buf, 0, sizeof(buf));
11119 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11120 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11121 return RETURN_ERR;
11122 }
11123 }
11124 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11125 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11126 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11127 return RETURN_ERR;
11128 }
11129 }
11130 if (current_param.beaconInterval != operationParam->beaconInterval) {
11131 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11132 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11133 return RETURN_ERR;
11134 }
11135 }
11136 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11137 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11138 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11139 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11140 return RETURN_ERR;
11141 }
11142 }
11143 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11144 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11145 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11146 return RETURN_ERR;
11147 }
11148 }
11149 if (current_param.guardInterval != operationParam->guardInterval) {
11150 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11151 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11152 return RETURN_ERR;
11153 }
11154 }
11155 if (current_param.transmitPower != operationParam->transmitPower) {
11156 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11157 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11158 return RETURN_ERR;
11159 }
11160 }
11161 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11162 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11163 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11164 return RETURN_ERR;
11165 }
11166 }
11167 if (current_param.obssCoex != operationParam->obssCoex) {
11168 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11169 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11170 return RETURN_ERR;
11171 }
11172 }
11173 if (current_param.stbcEnable != operationParam->stbcEnable) {
11174 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11175 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11176 return RETURN_ERR;
11177 }
11178 }
11179 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11180 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11181 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11182 return RETURN_ERR;
11183 }
11184 }
11185
11186 // if enable is true, then restart the radio
11187 wifi_setRadioEnable(index, FALSE);
11188 if (operationParam->enable == TRUE)
11189 wifi_setRadioEnable(index, TRUE);
11190 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11191
developer06a01d92022-09-07 16:32:39 +080011192 return RETURN_OK;
11193}
11194
11195INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11196{
developer1e5aa162022-09-13 16:06:24 +080011197 char band[64] = {0};
11198 char buf[256] = {0};
11199 char config_file[64] = {0};
11200 char cmd[128] = {0};
11201 int ret = RETURN_ERR;
11202 int mode = 0;
11203 ULONG channel = 0;
11204 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011205
11206 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11207 printf("Entering %s index = %d\n", __func__, (int)index);
11208
developer1e5aa162022-09-13 16:06:24 +080011209 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11210 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11211 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011212 {
developer1e5aa162022-09-13 16:06:24 +080011213 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011214 return RETURN_ERR;
11215 }
11216 operationParam->enable = enabled;
11217
11218 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011219 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011220 {
developer1e5aa162022-09-13 16:06:24 +080011221 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011222 return RETURN_ERR;
11223 }
11224
11225 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011226 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011227 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011228 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011229 else if (!strcmp(band, "6GHz"))
11230 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011231 else
11232 {
developer1e5aa162022-09-13 16:06:24 +080011233 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011234 band);
11235 }
11236
developer1e5aa162022-09-13 16:06:24 +080011237 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11238 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11239 operationParam->channel = 0;
11240 operationParam->autoChannelEnabled = TRUE;
11241 } else {
11242 operationParam->channel = strtol(buf, NULL, 10);
11243 operationParam->autoChannelEnabled = FALSE;
11244 }
11245
developer06a01d92022-09-07 16:32:39 +080011246 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011247 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11248 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11249 return RETURN_ERR;
11250 }
developer06a01d92022-09-07 16:32:39 +080011251 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11252 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11253 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer1e5aa162022-09-13 16:06:24 +080011254 else if (!strcmp(buf, "160")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11255 else if (!strcmp(buf, "80+80")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011256 else
11257 {
developer1e5aa162022-09-13 16:06:24 +080011258 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11259 return false;
developer06a01d92022-09-07 16:32:39 +080011260 }
11261
developer1e5aa162022-09-13 16:06:24 +080011262 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11263 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11264 return RETURN_ERR;
11265 }
11266 // Two different definition bit map, so need to check every bit.
11267 if (mode & WIFI_MODE_A)
11268 operationParam->variant |= WIFI_80211_VARIANT_A;
11269 if (mode & WIFI_MODE_B)
11270 operationParam->variant |= WIFI_80211_VARIANT_B;
11271 if (mode & WIFI_MODE_G)
11272 operationParam->variant |= WIFI_80211_VARIANT_G;
11273 if (mode & WIFI_MODE_N)
11274 operationParam->variant |= WIFI_80211_VARIANT_N;
11275 if (mode & WIFI_MODE_AC)
11276 operationParam->variant |= WIFI_80211_VARIANT_AC;
11277 if (mode & WIFI_MODE_AX)
11278 operationParam->variant |= WIFI_80211_VARIANT_AX;
11279 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11280 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11281 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011282 }
developer1e5aa162022-09-13 16:06:24 +080011283 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11284 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11285 return RETURN_ERR;
11286 }
11287 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11288 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11289 return RETURN_ERR;
11290 }
developer06a01d92022-09-07 16:32:39 +080011291
developer1e5aa162022-09-13 16:06:24 +080011292 memset(buf, 0, sizeof(buf));
11293 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11294 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11295 return RETURN_ERR;
11296 }
11297 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11298
11299 memset(buf, 0, sizeof(buf));
11300 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11301 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11302 return RETURN_ERR;
11303 }
11304 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11305
11306 memset(buf, 0, sizeof(buf));
11307 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11308 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11309
11310 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11311 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11312 return RETURN_ERR;
11313 }
11314 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11315 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11316 return RETURN_ERR;
11317 }
11318
11319 memset(buf, 0, sizeof(buf));
11320 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11321 if (strcmp(buf, "-1") == 0) {
11322 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11323 operationParam->ctsProtection = FALSE;
11324 } else {
11325 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11326 operationParam->ctsProtection = TRUE;
11327 }
11328
11329 memset(buf, 0, sizeof(buf));
11330 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11331 if (strcmp(buf, "0") == 0)
11332 operationParam->obssCoex = FALSE;
11333 else
11334 operationParam->obssCoex = TRUE;
11335
11336 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11337 _syscmd(cmd, buf, sizeof(buf));
11338 if (strlen(buf) != 0)
11339 operationParam->stbcEnable = TRUE;
11340 else
11341 operationParam->stbcEnable = FALSE;
11342
11343 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11344 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11345 return RETURN_ERR;
11346 }
11347
11348 // Below value is hardcoded
11349
11350 operationParam->numSecondaryChannels = 0;
11351 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11352 operationParam->channelSecondary[i] = 0;
11353 }
11354 operationParam->csa_beacon_count = 15;
11355 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011356
11357 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11358 return RETURN_OK;
11359}
11360
11361static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11362{
11363 if (radioIndex != 0 && radioIndex != 1)
11364 {
11365 printf("%s: Wrong radio index (%d)\n", __func__, index);
11366 return -1;
11367 }
11368
11369 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
11370 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
11371
11372 return (arrayIndex * 2) + radioIndex;
11373}
11374
11375INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11376{
11377 INT ret;
11378 int i;
11379 BOOL enabled = false;
11380 char buf[256];
11381 wifi_secur_list *secur_item;
11382 int vap_index;
11383 INT mode;
11384 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
11385
11386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11387 printf("Entering %s index = %d\n", __func__, (int)index);
11388
11389 map->vap_array[index].radio_index = index;
11390 for (i = 0; i < 5; i++)
11391 {
11392 vap_index = array_index_to_vap_index(index, i);
11393 if (vap_index < 0)
11394 {
11395 return RETURN_ERR;
11396 }
11397
11398 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
11399
11400 map->vap_array[i].vap_index = vap_index;
11401
11402 memset(buf, 0, sizeof(buf));
11403 wifi_getApName(vap_index, buf); // XXX: error handling
11404 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
11405
11406 ret = wifi_getSSIDEnable(vap_index, &enabled);
11407 if (ret != RETURN_OK)
11408 {
11409 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
11410 return RETURN_ERR;
11411 }
11412 map->vap_array[i].u.bss_info.enabled = enabled;
11413
11414 memset(buf, 0, sizeof(buf));
11415 wifi_getBaseBSSID(vap_index, buf);
11416 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11417 &map->vap_array[i].u.bss_info.bssid[0],
11418 &map->vap_array[i].u.bss_info.bssid[1],
11419 &map->vap_array[i].u.bss_info.bssid[2],
11420 &map->vap_array[i].u.bss_info.bssid[3],
11421 &map->vap_array[i].u.bss_info.bssid[4],
11422 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
11423
11424 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
11425 map->vap_array[i].u.bss_info.showSsid = enabled;
11426
11427 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
11428 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
11429 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
11430
11431 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11432 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
11433
11434 memset(buf, 0, sizeof(buf));
11435 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
11436 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
11437
11438 wifi_getApSecurityModeEnabled(vap_index, buf);
11439
11440 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
11441 {
11442 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
11443 return RETURN_ERR;
11444 }
11445 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
11446
11447 memset(buf, 0, sizeof(buf));
11448 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
11449 strncpy(map->vap_array[i].u.bss_info.security.u.key.key, buf, sizeof(map->vap_array[i].u.bss_info.security.u.key.key) - 1);
11450
11451 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
11452 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
11453
11454 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
11455 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
11456
11457 wifi_getApIsolationEnable(vap_index, &enabled);
11458 map->vap_array[i].u.bss_info.isolation = enabled;
11459 }
11460 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11461 return RETURN_OK;
11462}
11463
11464INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11465{
11466 unsigned int i;
11467 wifi_vap_info_t *vap_info = NULL;
11468 int acl_mode;
11469 char *sec_str = NULL;
11470
11471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11472 printf("Entering %s index = %d\n", __func__, (int)index);
11473 for (i = 0; i < map->num_vaps; i++)
11474 {
11475 vap_info = &map->vap_array[i];
11476 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11477
11478 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11479 else
11480 {
11481 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11482 else acl_mode = 1;
11483 }
11484 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11485 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11486 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11487
11488 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11489 if (sec_str)
11490 {
11491 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11492 }
11493 else
11494 {
11495 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11496 }
11497
11498 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11499 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11500
11501 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11502 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11503
11504 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11505
11506 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11507 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11508 }
11509 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11510 return RETURN_OK;
11511}
11512
11513int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11514{
11515 char *token, *next;
11516 const char s[2] = ",";
11517 int count =0;
11518
11519 /* get the first token */
11520 token = strtok_r(pchannels, s, &next);
11521
11522 /* walk through other tokens */
11523 while( token != NULL && count < MAX_CHANNELS) {
11524 chlistptr->channels_list[count++] = atoi(token);
11525 token = strtok_r(NULL, s, &next);
11526 }
11527
11528 return count;
11529}
11530
11531static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11532{
11533 INT status;
11534 wifi_channels_list_t *chlistp;
11535 CHAR output_string[64];
11536 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011537 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011538
11539 if(rcap == NULL)
11540 {
11541 return RETURN_ERR;
11542 }
11543
11544 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011545 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011546
developer1e5aa162022-09-13 16:06:24 +080011547 if (band == band_2_4)
11548 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11549 else if (band == band_5)
11550 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11551 else if (band == band_6)
11552 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011553
11554 chlistp = &(rcap->channel_list[0]);
11555 memset(pchannels, 0, sizeof(pchannels));
11556
11557 /* possible number of radio channels */
11558 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11559 {
11560 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11561 }
11562 /* Number of channels and list*/
11563 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11564
11565 /* autoChannelSupported */
11566 /* always ON with wifi_getRadioAutoChannelSupported */
11567 rcap->autoChannelSupported = TRUE;
11568
11569 /* DCSSupported */
11570 /* always ON with wifi_getRadioDCSSupported */
11571 rcap->DCSSupported = TRUE;
11572
11573 /* zeroDFSSupported - TBD */
11574 rcap->zeroDFSSupported = FALSE;
11575
11576 /* Supported Country List*/
11577 memset(output_string, 0, sizeof(output_string));
11578 status = wifi_getRadioCountryCode(radioIndex, output_string);
11579 if( status != 0 ) {
11580 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11581 return RETURN_ERR;
11582 } else {
11583 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11584 }
11585 if(!strcmp(output_string,"US")){
11586 rcap->countrySupported[0] = wifi_countrycode_US;
11587 rcap->countrySupported[1] = wifi_countrycode_CA;
11588 } else if (!strcmp(output_string,"CA")) {
11589 rcap->countrySupported[0] = wifi_countrycode_CA;
11590 rcap->countrySupported[1] = wifi_countrycode_US;
11591 } else {
11592 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
11593 }
11594
11595 rcap->numcountrySupported = 2;
11596
11597 /* csi */
11598 rcap->csi.maxDevices = 8;
11599 rcap->csi.soudingFrameSupported = TRUE;
11600
11601 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
11602
11603 /* channelWidth - all supported bandwidths */
11604 int i=0;
11605 rcap->channelWidth[i] = 0;
11606 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11607 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11608 WIFI_CHANNELBANDWIDTH_40MHZ);
11609
11610 }
developer1e5aa162022-09-13 16:06:24 +080011611 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080011612 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11613 WIFI_CHANNELBANDWIDTH_40MHZ |
11614 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
11615 }
11616
11617
11618 /* mode - all supported variants */
11619 // rcap->mode[i] = WIFI_80211_VARIANT_H;
11620 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011621 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 +080011622 }
11623 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011624 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
11625 }
11626 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
11627 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080011628 }
11629 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
11630 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
11631
11632 /* supportedBitRate - all supported bitrates */
11633 rcap->supportedBitRate[i] = 0;
11634 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11635 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11636 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
11637 }
developer1e5aa162022-09-13 16:06:24 +080011638 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080011639 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11640 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
11641 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
11642 }
11643
11644
11645 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
11646 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
11647 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
11648 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
11649 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
11650 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
11651 rcap->cipherSupported = 0;
11652 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
11653 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
11654
11655 return RETURN_OK;
11656}
11657
11658INT wifi_getHalCapability(wifi_hal_capability_t *cap)
11659{
11660 INT status, radioIndex;
11661 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
11662 int iter = 0;
11663 unsigned int j;
11664 wifi_interface_name_idex_map_t *iface_info;
11665
11666 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11667
11668 memset(cap, 0, sizeof(wifi_hal_capability_t));
11669
11670 /* version */
11671 cap->version.major = WIFI_HAL_MAJOR_VERSION;
11672 cap->version.minor = WIFI_HAL_MINOR_VERSION;
11673
11674 /* number of radios platform property */
11675 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
11676 _syscmd(cmd, output, sizeof(output));
11677 cap->wifi_prop.numRadios = atoi(output);
11678
11679 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
11680 {
11681 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
11682 if (status != 0) {
11683 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
11684 return RETURN_ERR;
11685 }
11686
11687 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
11688 {
11689 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
11690 {
11691 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
11692 return RETURN_ERR;
11693 }
11694 iface_info = &cap->wifi_prop.interface_map[iter];
11695 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
11696 iface_info->rdk_radio_index = radioIndex;
11697 memset(output, 0, sizeof(output));
11698 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
11699 {
11700 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
11701 }
11702 // TODO: bridge name
11703 // TODO: vlan id
11704 // TODO: primary
11705 iface_info->index = array_index_to_vap_index(radioIndex, j);
11706 memset(output, 0, sizeof(output));
11707 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
11708 {
11709 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
11710 }
11711 iter++;
11712 }
11713 }
11714
11715 cap->BandSteeringSupported = FALSE;
11716 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11717 return RETURN_OK;
11718}
11719
11720INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
11721{
developer587c1b62022-09-27 15:58:59 +080011722 char buf[128] = {0};
11723 char config_file[128] = {0};
11724 char password[64] = {0};
11725 char mfp[32] = {0};
11726 char wpa_mode[32] = {0};
11727 struct params params = {0};
11728
11729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11730
11731 multiple_set = TRUE;
11732 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
11733 if (security->mode == wifi_security_mode_none) {
11734 strcpy(wpa_mode, "None");
11735 } else if (security->mode == wifi_security_mode_wpa_personal)
11736 strcpy(wpa_mode, "WPA-Personal");
11737 else if (security->mode == wifi_security_mode_wpa2_personal)
11738 strcpy(wpa_mode, "WPA2-Personal");
11739 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
11740 strcpy(wpa_mode, "WPA-WPA2-Personal");
11741 else if (security->mode == wifi_security_mode_wpa_enterprise)
11742 strcpy(wpa_mode, "WPA-Enterprise");
11743 else if (security->mode == wifi_security_mode_wpa2_enterprise)
11744 strcpy(wpa_mode, "WPA2-Enterprise");
11745 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
11746 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
11747 else if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
11748 strcpy(wpa_mode, "WPA3-Personal");
11749 else if (security->mode == wifi_security_mode_wpa3_enterprise)
11750 strcpy(wpa_mode, "WPA3-Enterprise");
11751
11752 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
11753
11754 strncpy(password, security->u.key.key, 63);
11755 password[63] = '\0';
11756 wifi_setApSecurityKeyPassphrase(ap_index, password);
11757
11758 if (security->mode != wifi_security_mode_none) {
11759 memset(&params, 0, sizeof(params));
11760 params.name = "wpa_pairwise";
11761 if (security->encr == wifi_encryption_tkip)
11762 params.value = "TKIP";
11763 else if (security->encr == wifi_encryption_aes)
11764 params.value = "CCMP";
11765 else if (security->encr == wifi_encryption_aes_tkip)
11766 params.value = "TKIP CCMP";
11767 wifi_hostapdWrite(config_file, &params, 1);
11768 }
11769
11770 if (security->mfp == wifi_mfp_cfg_disabled)
11771 strcpy(mfp, "Disable");
11772 else if (security->mfp == wifi_mfp_cfg_optional)
11773 strcpy(mfp, "Optional");
11774 else if (security->mfp == wifi_mfp_cfg_required)
11775 strcpy(mfp, "Required");
11776 wifi_setApSecurityMFPConfig(ap_index, mfp);
11777
11778 memset(&params, 0, sizeof(params));
11779 params.name = "transition_disable";
11780 if (security->wpa3_transition_disable == TRUE)
11781 params.value = "0x01";
11782 else
11783 params.value = "0x00";
11784 wifi_hostapdWrite(config_file, &params, 1);
11785
11786 memset(&params, 0, sizeof(params));
11787 params.name = "wpa_group_rekey";
11788 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
11789 params.value = buf;
11790 wifi_hostapdWrite(config_file, &params, 1);
11791
11792 memset(&params, 0, sizeof(params));
11793 params.name = "wpa_strict_rekey";
11794 params.value = security->strict_rekey?"1":"0";
11795 wifi_hostapdWrite(config_file, &params, 1);
11796
11797 memset(&params, 0, sizeof(params));
11798 params.name = "wpa_pairwise_update_count";
11799 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
11800 params.value = buf;
11801 wifi_hostapdWrite(config_file, &params, 1);
11802
11803 memset(&params, 0, sizeof(params));
11804 params.name = "disable_pmksa_caching";
11805 params.value = security->disable_pmksa_caching?"1":"0";
11806 wifi_hostapdWrite(config_file, &params, 1);
11807
11808 wifi_setApEnable(ap_index, FALSE);
11809 wifi_setApEnable(ap_index, TRUE);
11810
11811 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11812
developer06a01d92022-09-07 16:32:39 +080011813 return RETURN_OK;
11814}
11815
11816INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
11817{
developer587c1b62022-09-27 15:58:59 +080011818 char buf[128] = {0};
11819 char config_file[128] = {0};
11820 int disable = 0;
11821 // struct params params = {0};
11822
11823 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11824 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
11825 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
11826 security->mode = wifi_security_mode_none;
11827 if (strlen(buf) != 0) {
11828 if (strcmp(buf, "WPA-Personal"))
11829 security->mode = wifi_security_mode_wpa_personal;
11830 else if (strcmp(buf, "WPA2-Personal"))
11831 security->mode = wifi_security_mode_wpa2_personal;
11832 else if (strcmp(buf, "WPA-WPA2-Personal"))
11833 security->mode = wifi_security_mode_wpa_wpa2_personal;
11834 else if (strcmp(buf, "WPA-Enterprise"))
11835 security->mode = wifi_security_mode_wpa_enterprise;
11836 else if (strcmp(buf, "WPA2-Enterprise"))
11837 security->mode = wifi_security_mode_wpa2_enterprise;
11838 else if (strcmp(buf, "WPA-WPA2-Enterprise"))
11839 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
11840 else if (strcmp(buf, "WPA3-Personal"))
11841 security->mode = wifi_security_mode_wpa3_personal;
11842 else if (strcmp(buf, "WPA3-Transition"))
11843 security->mode = wifi_security_mode_wpa3_transition;
11844 else if (strcmp(buf, "WPA3-Enterprise"))
11845 security->mode = wifi_security_mode_wpa3_enterprise;
11846 }
11847
11848 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
11849 if (security->mode == wifi_security_mode_none)
11850 security->encr = wifi_encryption_none;
11851 else {
11852 if (strcmp(buf, "TKIP") == 0)
11853 security->encr = wifi_encryption_tkip;
11854 else if (strcmp(buf, "CCMP") == 0)
11855 security->encr = wifi_encryption_aes;
11856 else
11857 security->encr = wifi_encryption_aes_tkip;
11858 }
11859
11860 memset(buf, 0, sizeof(buf));
11861 wifi_getApSecurityMFPConfig(ap_index, buf);
11862 if (strcmp(buf, "Disabled") == 0)
11863 security->mfp = wifi_mfp_cfg_disabled;
11864 else if (strcmp(buf, "Optional") == 0)
11865 security->mfp = wifi_mfp_cfg_optional;
11866 else if (strcmp(buf, "Required") == 0)
11867 security->mfp = wifi_mfp_cfg_required;
11868
11869 memset(buf, 0, sizeof(buf));
11870 security->wpa3_transition_disable = FALSE;
11871 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
11872 disable = strtol(buf, NULL, 16);
11873 if (disable != 0)
11874 security->wpa3_transition_disable = TRUE;
11875
11876 memset(buf, 0, sizeof(buf));
11877 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
11878 if (strlen(buf) == 0)
11879 security->rekey_interval = 86400;
11880 else
11881 security->rekey_interval = strtol(buf, NULL, 10);
11882
11883 memset(buf, 0, sizeof(buf));
11884 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
11885 if (strlen(buf) == 0)
11886 security->strict_rekey = 1;
11887 else
11888 security->strict_rekey = strtol(buf, NULL, 10);
11889
11890 memset(buf, 0, sizeof(buf));
11891 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
11892 if (strlen(buf) == 0)
11893 security->eapol_key_retries = 4;
11894 else
11895 security->eapol_key_retries = strtol(buf, NULL, 10);
11896
11897 memset(buf, 0, sizeof(buf));
11898 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
11899 if (strlen(buf) == 0)
11900 security->disable_pmksa_caching = FALSE;
11901 else
11902 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
11903
11904 /* TODO
11905 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
11906 */
11907 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
11908 security->eap_identity_req_timeout = 0;
11909 security->eap_identity_req_retries = 0;
11910 security->eap_req_timeout = 0;
11911 security->eap_req_retries = 0;
11912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080011913 return RETURN_OK;
11914}
11915
11916#endif /* WIFI_HAL_VERSION_3 */
11917
11918#ifdef WIFI_HAL_VERSION_3_PHASE2
11919INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
11920{
developer13df9332022-09-27 16:53:22 +080011921 char cmd[128] = {0};
11922 char buf[128] = {0};
11923 char *mac_addr = NULL;
11924 BOOL status = FALSE;
11925 size_t len = 0;
11926
11927 if(ap_index > MAX_APS)
11928 return RETURN_ERR;
11929
11930 *output_numDevices = 0;
11931 wifi_getApEnable(ap_index, &status);
11932 if (status == FALSE)
11933 return RETURN_OK;
11934
11935 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
11936 _syscmd(cmd, buf, sizeof(buf));
11937
11938 mac_addr = strtok(buf, "\n");
11939 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
11940 *output_numDevices = i + 1;
11941 fprintf(stderr, "mac_addr: %s\n", mac_addr);
11942 addr_ptr = output_deviceMacAddressArray[i];
11943 mac_addr_aton(addr_ptr, mac_addr);
11944 mac_addr = strtok(NULL, "\n");
11945 }
11946
11947 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080011948}
11949#else
11950INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
11951{
11952 char cmd[128];
11953 BOOL status = false;
11954
11955 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
11956 return RETURN_ERR;
11957
11958 output_buf[0] = '\0';
11959
11960 wifi_getApEnable(ap_index,&status);
11961 if (!status)
11962 return RETURN_OK;
11963
11964 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
11965 _syscmd(cmd, output_buf, output_buf_size);
11966
11967 return RETURN_OK;
11968}
11969#endif
developer2f513ab2022-09-13 14:26:06 +080011970
11971INT wifi_getProxyArp(INT apIndex, BOOL *enable)
11972{
11973 char output[16]={'\0'};
11974 char config_file[MAX_BUF_SIZE] = {0};
11975
11976 if (!enable)
11977 return RETURN_ERR;
11978
11979 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
11980 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
11981
11982 if (strlen(output) == 0)
11983 *enable = FALSE;
11984 else if (strncmp(output, "1", 1) == 0)
11985 *enable = TRUE;
11986 else
11987 *enable = FALSE;
11988
11989 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
11990 return RETURN_OK;
11991}
developer2d9c30f2022-09-13 15:06:14 +080011992
11993INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
11994{
11995 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
11996 return RETURN_ERR;
11997 *output_enable=TRUE;
11998 return RETURN_OK;
11999}
developerfd7d2892022-09-13 16:44:53 +080012000
12001INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12002{
12003 char cmd[128] = {0};
12004 char buf[128] = {0};
12005 char line[128] = {0};
12006 size_t len = 0;
12007 ssize_t read = 0;
12008 FILE *f = NULL;
12009 int index = 0;
12010 int exp = 0;
12011 int mantissa = 0;
12012 int duration = 0;
12013 int radio_index = 0;
12014 int max_radio_num = 0;
12015 uint twt_wake_interval = 0;
12016
12017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12018
12019 wifi_getMaxRadioNumber(&max_radio_num);
12020 radio_index = ap_index % max_radio_num;
12021 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12022 _syscmd(cmd, buf, sizeof(buf));
12023 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12024 if (*numSessionReturned > maxNumberSessions)
12025 *numSessionReturned = maxNumberSessions;
12026 else if (*numSessionReturned < 1) {
12027 *numSessionReturned = 0;
12028 return RETURN_OK;
12029 }
12030
12031 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12032 if ((f = popen(cmd, "r")) == NULL) {
12033 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12034 return RETURN_ERR;
12035 }
12036
12037 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12038 while((read = fgets(line, sizeof(line), f)) != NULL) {
12039 char *tmp = NULL;
12040 strcpy(buf, line);
12041 tmp = strtok(buf, " ");
12042 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12043 tmp = strtok(NULL, " ");
12044 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12045 tmp = strtok(NULL, " ");
12046 if (strstr(tmp, "t")) {
12047 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12048 }
12049 if (strstr(tmp, "a")) {
12050 twtSessions[index].twtParameters.operation.announced = TRUE;
12051 }
12052 tmp = strtok(NULL, " ");
12053 exp = strtol(tmp, NULL, 10);
12054 tmp = strtok(NULL, " ");
12055 mantissa = strtol(tmp, NULL, 10);
12056 tmp = strtok(NULL, " ");
12057 duration = strtol(tmp, NULL, 10);
12058
12059 // only implicit supported
12060 twtSessions[index].twtParameters.operation.implicit = TRUE;
12061 // only individual agreement supported
12062 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12063
12064 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12065 twt_wake_interval = mantissa * (1 << exp);
12066 if (twt_wake_interval/mantissa != (1 << exp)) {
12067 // Overflow handling
12068 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12069 } else {
12070 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12071 }
12072 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12073 index++;
12074 }
12075
12076 pclose(f);
12077 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12078 return RETURN_OK;
12079}