blob: d3089188bd7f2c0668728af7ee02341018724fdb [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"
developer247302b2022-10-06 15:03:00 +080077#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
developera748dcf2022-09-13 15:56:48 +080078#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080079#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080080#define VLAN_FILE "/nvram/hostapd.vlan"
developer8d583982022-09-20 11:28:22 +080081#define PSK_FILE "/tmp/hostapd"
developer2de97692022-09-26 14:00:03 +080082#define CHAIN_MASK_FILE "/tmp/chain_mask"
developer54e6b9f2022-09-28 14:41:20 +080083#define AMSDU_FILE "/tmp/AMSDU"
developerf49437e2022-09-29 19:58:21 +080084#define MCS_FILE "/tmp/MCS"
developer6daeb3f2022-09-30 13:36:39 +080085#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080086
developer06a01d92022-09-07 16:32:39 +080087#define DRIVER_2GHZ "ath9k"
88#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080089#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080090
91/*
92 MAX_APS - Number of all AP available in system
93 2x Home AP
94 2x Backhaul AP
95 2x Guest AP
96 2x Secure Onboard AP
97 2x Service AP
98
99*/
developer06a01d92022-09-07 16:32:39 +0800100
developer033b37b2022-10-18 11:27:46 +0800101
developer804c64f2022-10-19 13:54:40 +0800102#define MAX_APS MAX_NUM_RADIOS*5
developer06a01d92022-09-07 16:32:39 +0800103#ifndef AP_PREFIX
104#define AP_PREFIX "wifi"
105#endif
106
107#ifndef RADIO_PREFIX
108#define RADIO_PREFIX "wlan"
109#endif
110
111#define MAX_BUF_SIZE 128
112#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800113#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800114
115//Uncomment to enable debug logs
116//#define WIFI_DEBUG
117
118#ifdef WIFI_DEBUG
119#define wifi_dbg_printf printf
120#define WIFI_ENTRY_EXIT_DEBUG printf
121#else
122#define wifi_dbg_printf(format, args...) printf("")
123#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
124#endif
125
126#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
127#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
128#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
129#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
130#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
131#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
132#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
133#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
134#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
135#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
136
developer4fb0b922022-09-30 14:29:09 +0800137#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800138
139#define BW_FNAME "/nvram/bw_file.txt"
140
141#define PS_MAX_TID 16
142
143static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
144 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
145 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
148 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
150 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
152 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
153 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
154 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
155 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
156 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
157 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
158 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
159 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
160};
161
162typedef unsigned long long u64;
163
164/* Enum to define WiFi Bands */
165typedef enum
166{
167 band_invalid = -1,
168 band_2_4 = 0,
169 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800170 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800171} wifi_band;
172
developerdb744382022-09-13 15:34:54 +0800173typedef enum {
174 WIFI_MODE_A = 0x01,
175 WIFI_MODE_B = 0x02,
176 WIFI_MODE_G = 0x04,
177 WIFI_MODE_N = 0x08,
178 WIFI_MODE_AC = 0x10,
179 WIFI_MODE_AX = 0x20,
180} wifi_ieee80211_Mode;
181
developer06a01d92022-09-07 16:32:39 +0800182#ifdef WIFI_HAL_VERSION_3
183
184// Return number of elements in array
185#ifndef ARRAY_SIZE
186#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
187#endif /* ARRAY_SIZE */
188
189#ifndef ARRAY_AND_SIZE
190#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
191#endif /* ARRAY_AND_SIZE */
192
193#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
194
195typedef struct {
196 int32_t value;
197 int32_t param;
198 intptr_t key;
199 intptr_t data;
200} wifi_secur_list;
201
202wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
203wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
204char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800205static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800206
207static wifi_secur_list map_security[] =
208{
209 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
210 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
211 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
216 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
developerc0830312022-10-13 13:22:36 +0800217 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
218 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
developer4a359672022-10-13 15:30:46 +0800219 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
developerc0830312022-10-13 13:22:36 +0800220 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
developer06a01d92022-09-07 16:32:39 +0800221};
222
223wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
224{
225 wifi_secur_list *item;
226 int i;
227
228 for (item = list,i = 0;i < list_sz; item++, i++) {
229 if ((int)(item->key) == key) {
230 return item;
231 }
232 }
233
234 return NULL;
235}
236
237char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
238{
239 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
240
241 if (!item) {
242 return "";
243 }
244
245 return (char *)(item->data);
246}
247
248wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
249{
250 wifi_secur_list *item;
251 int i;
252
253 for (item = list,i = 0;i < list_sz; item++, i++) {
254 if (strcmp((char *)(item->data), str) == 0) {
255 return item;
256 }
257 }
258
259 return NULL;
260}
261#endif /* WIFI_HAL_VERSION_3 */
262
263#ifdef HAL_NETLINK_IMPL
264typedef struct {
265 int id;
266 struct nl_sock* socket;
267 struct nl_cb* cb;
268} Netlink;
269
270static int mac_addr_aton(unsigned char *mac_addr, char *arg)
271{
272 unsigned int mac_addr_int[6]={};
developer1d57d002022-10-12 18:03:15 +0800273 sscanf(arg, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
developer06a01d92022-09-07 16:32:39 +0800274 mac_addr[0] = mac_addr_int[0];
275 mac_addr[1] = mac_addr_int[1];
276 mac_addr[2] = mac_addr_int[2];
277 mac_addr[3] = mac_addr_int[3];
278 mac_addr[4] = mac_addr_int[4];
279 mac_addr[5] = mac_addr_int[5];
280 return 0;
281}
282
283static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
284{
285 unsigned int mac_addr_int[6]={};
286 mac_addr_int[0] = arg[0];
287 mac_addr_int[1] = arg[1];
288 mac_addr_int[2] = arg[2];
289 mac_addr_int[3] = arg[3];
290 mac_addr_int[4] = arg[4];
291 mac_addr_int[5] = arg[5];
developer1d57d002022-10-12 18:03:15 +0800292 snprintf(mac_addr, 20, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
developer06a01d92022-09-07 16:32:39 +0800293 return;
294}
295
296static int ieee80211_frequency_to_channel(int freq)
297{
developerf5745ee2022-10-05 16:09:53 +0800298 /* see 802.11-2007 17.3.8.3.2 and Annex J */
developer06a01d92022-09-07 16:32:39 +0800299 if (freq == 2484)
300 return 14;
developerf5745ee2022-10-05 16:09:53 +0800301 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
302 else if (freq == 5935)
303 return 2;
developer06a01d92022-09-07 16:32:39 +0800304 else if (freq < 2484)
305 return (freq - 2407) / 5;
306 else if (freq >= 4910 && freq <= 4980)
307 return (freq - 4000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800308 else if (freq < 5950)
developer06a01d92022-09-07 16:32:39 +0800309 return (freq - 5000) / 5;
developerf5745ee2022-10-05 16:09:53 +0800310 else if (freq <= 45000) /* DMG band lower limit */
311 /* see 802.11ax D6.1 27.3.23.2 */
312 return (freq - 5950) / 5;
313 else if (freq >= 58320 && freq <= 70200)
developer06a01d92022-09-07 16:32:39 +0800314 return (freq - 56160) / 2160;
315 else
316 return 0;
317}
318
319static int initSock80211(Netlink* nl) {
320 nl->socket = nl_socket_alloc();
321 if (!nl->socket) {
322 fprintf(stderr, "Failing to allocate the sock\n");
323 return -ENOMEM;
324 }
325
326 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
327
328 if (genl_connect(nl->socket)) {
329 fprintf(stderr, "Failed to connect\n");
330 nl_close(nl->socket);
331 nl_socket_free(nl->socket);
332 return -ENOLINK;
333 }
334
335 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
336 if (nl->id< 0) {
337 fprintf(stderr, "interface not found.\n");
338 nl_close(nl->socket);
339 nl_socket_free(nl->socket);
340 return -ENOENT;
341 }
342
343 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
344 if ((!nl->cb)) {
345 fprintf(stderr, "Failed to allocate netlink callback.\n");
346 nl_close(nl->socket);
347 nl_socket_free(nl->socket);
348 return ENOMEM;
349 }
350
351 return nl->id;
352}
353
354static int nlfree(Netlink *nl)
355{
356 nl_cb_put(nl->cb);
357 nl_close(nl->socket);
358 nl_socket_free(nl->socket);
359 return 0;
360}
361
362static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
363 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
364 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
365 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
366};
367
368static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
369};
370
371static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
372};
373
374typedef struct _wifi_channelStats_loc {
375 INT array_size;
376 INT ch_number;
377 BOOL ch_in_pool;
378 INT ch_noise;
379 BOOL ch_radar_noise;
380 INT ch_max_80211_rssi;
381 INT ch_non_80211_noise;
382 INT ch_utilization;
383 ULLONG ch_utilization_total;
384 ULLONG ch_utilization_busy;
385 ULLONG ch_utilization_busy_tx;
386 ULLONG ch_utilization_busy_rx;
387 ULLONG ch_utilization_busy_self;
388 ULLONG ch_utilization_busy_ext;
389} wifi_channelStats_t_loc;
390
391typedef struct wifi_device_info {
392 INT wifi_devIndex;
393 UCHAR wifi_devMacAddress[6];
394 CHAR wifi_devIPAddress[64];
395 BOOL wifi_devAssociatedDeviceAuthentiationState;
396 INT wifi_devSignalStrength;
397 INT wifi_devTxRate;
398 INT wifi_devRxRate;
399} wifi_device_info_t;
400
401#endif
402
403//For 5g Alias Interfaces
404static BOOL priv_flag = TRUE;
405static BOOL pub_flag = TRUE;
406static BOOL Radio_flag = TRUE;
407//wifi_setApBeaconRate(1, beaconRate);
408
developer1e5aa162022-09-13 16:06:24 +0800409BOOL multiple_set = FALSE;
410
developer06a01d92022-09-07 16:32:39 +0800411struct params
412{
413 char * name;
414 char * value;
415};
416
417static int _syscmd(char *cmd, char *retBuf, int retBufSize)
418{
419 FILE *f;
420 char *ptr = retBuf;
421 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
422
423 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
424 if((f = popen(cmd, "r")) == NULL) {
425 fprintf(stderr,"\npopen %s error\n", cmd);
426 return RETURN_ERR;
427 }
428
429 while(!feof(f))
430 {
431 *ptr = 0;
432 if(bufSize>=128) {
433 bufbytes=128;
434 } else {
435 bufbytes=bufSize-1;
436 }
437
438 fgets(ptr,bufbytes,f);
439 readbytes=strlen(ptr);
440
441 if(!readbytes)
442 break;
443
444 bufSize-=readbytes;
445 ptr += readbytes;
446 }
447 cmd_ret = pclose(f);
448 retBuf[retBufSize-1]=0;
449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
450
451 return cmd_ret >> 8;
452}
453
developer033b37b2022-10-18 11:27:46 +0800454INT radio_index_to_phy(int radioIndex)
455{
456 char cmd[128] = {0};
457 char buf[64] = {0};
458 int phyIndex = 0;
459 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
460 _syscmd(cmd, buf, sizeof(buf));
461
462 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
463 fprintf(stderr, "%s: failed to get phy index\n", __func__);
464 return RETURN_ERR;
465 }
466 sscanf(buf, "phy%d", &phyIndex);
467
468 return phyIndex;
469}
developer026ac9e2022-11-07 13:46:24 +0800470
471wifi_band wifi_index_to_band(int radioIndex)
developerc707e972022-09-13 15:38:02 +0800472{
473 char cmd[128] = {0};
474 char buf[64] = {0};
developer026ac9e2022-11-07 13:46:24 +0800475 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800476 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800477 int phyIndex = 0;
developerc707e972022-09-13 15:38:02 +0800478 wifi_band band = band_invalid;
479
480 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800481
482 phyIndex = radio_index_to_phy(radioIndex);
developer5884e982022-10-06 10:52:50 +0800483 while(i < 10){
developer026ac9e2022-11-07 13:46:24 +0800484 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
developer5884e982022-10-06 10:52:50 +0800485 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800486 nl80211_band = strtol(buf, NULL, 10);
487 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800488 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800489 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800490 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800491 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800492 band = band_6;
493
494 if(band != band_invalid)
495 break;
496
497 i++;
498 sleep(1);
499 }
developerc707e972022-09-13 15:38:02 +0800500
501 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
502 return band;
503}
504
developer06a01d92022-09-07 16:32:39 +0800505static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
506{
507 char cmd[MAX_CMD_SIZE]={'\0'};
508 char buf[MAX_BUF_SIZE]={'\0'};
509 int ret = 0;
510
511 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
512 ret = _syscmd(cmd, buf, sizeof(buf));
513 if ((ret != 0) && (strlen(buf) == 0))
514 return -1;
515 snprintf(output, output_size, "%s", buf);
516
517 return 0;
518}
519
520static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
521{
522 char cmd[MAX_CMD_SIZE]={'\0'};
523 char buf[MAX_BUF_SIZE]={'\0'};
524
525 for(int i=0;i<item_count;i++)
526 {
527 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
528 if (strlen(buf) == 0) //Insert
529 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
530 else //Update
531 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
developer5884e982022-10-06 10:52:50 +0800532
developer06a01d92022-09-07 16:32:39 +0800533 if(_syscmd(cmd, buf, sizeof(buf)))
534 return -1;
535 }
536
537 return 0;
538}
539
540static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
541{
developer1e5aa162022-09-13 16:06:24 +0800542 if (multiple_set == TRUE)
543 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800544 char cmd[MAX_CMD_SIZE]="", output[32]="";
545 FILE *fp;
546 int i;
547 //NOTE RELOAD should be done in ApplySSIDSettings
548
549 for(i=0; i<item_count; i++, list++)
550 {
551 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
552 if((fp = popen(cmd, "r"))==NULL)
553 {
554 perror("popen failed");
555 return -1;
556 }
557 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
558 {
559 pclose(fp);
560 perror("fgets failed");
561 return -1;
562 }
563 pclose(fp);
564 }
565 return 0;
566}
567
568static int wifi_reloadAp(int apIndex)
569{
developer1e5aa162022-09-13 16:06:24 +0800570 if (multiple_set == TRUE)
571 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800572 char cmd[MAX_CMD_SIZE]="";
573 char buf[MAX_BUF_SIZE]="";
574
575 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
576 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
577 return RETURN_ERR;
578
579 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
580 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
581 return RETURN_ERR;
582
583 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
584 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
585 return RETURN_ERR;
586
587 return RETURN_OK;
588}
589
590
591//For Getting Current Interface Name from corresponding hostapd configuration
592void GetInterfaceName(char *interface_name, char *conf_file)
593{
594 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
595 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
596 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
597}
598
599INT File_Reading(CHAR *file, char *Value)
600{
601 FILE *fp = NULL;
602 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
603 int count = 0;
604
605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
606 fp = popen(file,"r");
607 if(fp == NULL)
608 return RETURN_ERR;
609
610 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
611 {
612 for(count=0;buf[count]!='\n';count++)
613 copy_buf[count]=buf[count];
614 copy_buf[count]='\0';
615 }
616 strcpy(Value,copy_buf);
617 pclose(fp);
618 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
619
620 return RETURN_OK;
621}
622
623void wifi_RestartHostapd_2G()
624{
625 int Public2GApIndex = 4;
626
627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
628 wifi_setApEnable(Public2GApIndex, FALSE);
629 wifi_setApEnable(Public2GApIndex, TRUE);
630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
631}
632
633void wifi_RestartHostapd_5G()
634{
635 int Public5GApIndex = 5;
636
637 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
638 wifi_setApEnable(Public5GApIndex, FALSE);
639 wifi_setApEnable(Public5GApIndex, TRUE);
640 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
641}
642
643void wifi_RestartPrivateWifi_2G()
644{
645 int PrivateApIndex = 0;
646
647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
648 wifi_setApEnable(PrivateApIndex, FALSE);
649 wifi_setApEnable(PrivateApIndex, TRUE);
650 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
651}
652
653void wifi_RestartPrivateWifi_5G()
654{
655 int Private5GApIndex = 1;
656
657 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
658 wifi_setApEnable(Private5GApIndex, FALSE);
659 wifi_setApEnable(Private5GApIndex, TRUE);
660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
661}
662
663static int writeBandWidth(int radioIndex,char *bw_value)
664{
665 char buf[MAX_BUF_SIZE];
666 char cmd[MAX_CMD_SIZE];
667
668 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
669 if(_syscmd(cmd, buf, sizeof(buf)))
670 {
671 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
672 _syscmd(cmd, buf, sizeof(buf));
673 return RETURN_OK;
674 }
675
676 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
677 _syscmd(cmd,buf,sizeof(buf));
678 return RETURN_OK;
679}
680
681static int readBandWidth(int radioIndex,char *bw_value)
682{
developer30423732022-12-01 16:17:49 +0800683 char buf[MAX_BUF_SIZE] = {0};
684 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800685 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
686 _syscmd(cmd,buf,sizeof(buf));
687 if(NULL!=strstr(buf,"20MHz"))
688 {
689 strcpy(bw_value,"20MHz");
690 }
691 else if(NULL!=strstr(buf,"40MHz"))
692 {
693 strcpy(bw_value,"40MHz");
694 }
695 else if(NULL!=strstr(buf,"80MHz"))
696 {
697 strcpy(bw_value,"80MHz");
698 }
699 else
700 {
701 return RETURN_ERR;
702 }
703 return RETURN_OK;
704}
705
developer39a5efb2022-09-13 16:09:06 +0800706INT wifi_getMaxRadioNumber(INT *max_radio_num)
707{
708 char cmd[64] = {0};
709 char buf[4] = {0};
710
711 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
712
713 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
714 _syscmd(cmd, buf, sizeof(buf));
developer804c64f2022-10-19 13:54:40 +0800715 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
developer39a5efb2022-09-13 16:09:06 +0800716
717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
718
719 return RETURN_OK;
720}
721
developer264159b2022-11-02 09:41:35 +0800722// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800723INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
724{
developer5f222492022-09-13 15:21:52 +0800725 struct params params={'\0'};
726 char config_file[MAX_BUF_SIZE] = {0};
727 char buf[MAX_BUF_SIZE] = {'\0'};
728
729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800730 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800731 if (strlen (beaconRate) >= 5) {
732 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
733 buf[strlen(beaconRate) - 4] = '\0';
734 } else if (strlen(beaconRate) > 0)
735 strcpy(buf, beaconRate);
736 else
737 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800738
739 params.name = "beacon_rate";
740 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
741 if (strncmp(buf, "5.5", 3) == 0) {
742 snprintf(buf, sizeof(buf), "55");
743 params.value = buf;
744 } else {
745 strcat(buf, "0");
746 params.value = buf;
747 }
748
749 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
750 wifi_hostapdWrite(config_file, &params, 1);
751 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
752 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
753
754 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800755}
756
757INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
758{
developer1d57d002022-10-12 18:03:15 +0800759 char config_file[128] = {'\0'};
760 char temp_output[128] = {'\0'};
761 char buf[128] = {'\0'};
762 char cmd[128] = {'\0'};
763 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800764 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800765
766 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
767 if (NULL == beaconRate)
768 return RETURN_ERR;
769
770 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
771 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800772 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800773 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
774 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800775 if (strncmp(buf, "55", 2) == 0)
776 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
777 else {
778 rate = strtol(buf, NULL, 10)/10;
779 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
780 }
developer5f222492022-09-13 15:21:52 +0800781 } else {
developer1d57d002022-10-12 18:03:15 +0800782 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800783 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
developer1d57d002022-10-12 18:03:15 +0800784 _syscmd(cmd, buf, sizeof(buf));
785 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800786 }
787 strncpy(beaconRate, temp_output, sizeof(temp_output));
788 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
789
790 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800791}
792
793INT wifi_setLED(INT radioIndex, BOOL enable)
794{
795 return 0;
796}
797INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
798{
799 return RETURN_OK;
800}
801/**********************************************************************************
802 *
803 * Wifi Subsystem level function prototypes
804 *
805**********************************************************************************/
806//---------------------------------------------------------------------------------------------------
807//Wifi system api
808//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
809INT wifi_getHalVersion(CHAR *output_string) //RDKB
810{
811 if(!output_string)
812 return RETURN_ERR;
813 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
814
815 return RETURN_OK;
816}
817
818
819/* wifi_factoryReset() function */
820/**
821* @description Clears internal variables to implement a factory reset of the Wi-Fi
822* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
823*
824* @param None
825*
826* @return The status of the operation.
827* @retval RETURN_OK if successful.
828* @retval RETURN_ERR if any error is detected
829*
830* @execution Synchronous
831* @sideeffect None
832*
833* @note This function must not suspend and must not invoke any blocking system
834* calls. It should probably just send a message to a driver event handler task.
835*
836*/
837INT wifi_factoryReset()
838{
839 char cmd[128];
840
841 /*delete running hostapd conf files*/
842 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
843 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
844 system(cmd);
845 system("systemctl restart hostapd.service");
846
847 return RETURN_OK;
848}
849
850/* wifi_factoryResetRadios() function */
851/**
852* @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.
853*
854* @param None
855* @return The status of the operation
856* @retval RETURN_OK if successful
857* @retval RETURN_ERR if any error is detected
858*
859* @execution Synchronous
860*
861* @sideeffect None
862*
863* @note This function must not suspend and must not invoke any blocking system
864* calls. It should probably just send a message to a driver event handler task.
865*
866*/
867INT wifi_factoryResetRadios()
868{
869 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
870 return RETURN_OK;
871
872 return RETURN_ERR;
873}
874
875
876/* wifi_factoryResetRadio() function */
877/**
878* @description Restore selected radio parameters without touching access point parameters
879*
880* @param radioIndex - Index of Wi-Fi Radio channel
881*
882* @return The status of the operation.
883* @retval RETURN_OK if successful.
884* @retval RETURN_ERR if any error is detected
885*
886* @execution Synchronous.
887* @sideeffect None.
888*
889* @note This function must not suspend and must not invoke any blocking system
890* calls. It should probably just send a message to a driver event handler task.
891*
892*/
893INT wifi_factoryResetRadio(int radioIndex) //RDKB
894{
developer5ff7f5f2022-09-13 15:12:16 +0800895 system("systemctl stop hostapd.service");
896
developer06a01d92022-09-07 16:32:39 +0800897 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
898 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800899 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800900 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800901 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800902 else
903 return RETURN_ERR;
904
developer5ff7f5f2022-09-13 15:12:16 +0800905 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800906 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
907 return RETURN_OK;
908}
909
910/* wifi_initRadio() function */
911/**
912* Description: This function call initializes the specified radio.
913* Implementation specifics may dictate the functionality since
914* different hardware implementations may have different initilization requirements.
915* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
916*
917* @return The status of the operation.
918* @retval RETURN_OK if successful.
919* @retval RETURN_ERR if any error is detected
920*
921* @execution Synchronous.
922* @sideeffect None.
923*
924* @note This function must not suspend and must not invoke any blocking system
925* calls. It should probably just send a message to a driver event handler task.
926*
927*/
928INT wifi_initRadio(INT radioIndex)
929{
930 //TODO: Initializes the wifi subsystem (for specified radio)
931 return RETURN_OK;
932}
933void macfilter_init()
934{
935 char count[4]={'\0'};
936 char buf[253]={'\0'};
937 char tmp[19]={'\0'};
938 int dev_count,block,mac_entry=0;
939 char res[4]={'\0'};
940 char acl_file_path[64] = {'\0'};
941 FILE *fp = NULL;
942 int index=0;
943 char iface[10]={'\0'};
944 char config_file[MAX_BUF_SIZE] = {0};
945
946
947 sprintf(acl_file_path,"/tmp/mac_filter.sh");
948
949 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800950 if (fp == NULL) {
951 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
952 return RETURN_ERR;
953 }
developer06a01d92022-09-07 16:32:39 +0800954 sprintf(buf,"#!/bin/sh \n");
955 fprintf(fp,"%s\n",buf);
956
957 system("chmod 0777 /tmp/mac_filter.sh");
958
959 for(index=0;index<=1;index++)
960 {
961 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
962 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
963 sprintf(buf,"syscfg get %dcountfilter",index);
964 _syscmd(buf,count,sizeof(count));
965 mac_entry=atoi(count);
966
967 sprintf(buf,"syscfg get %dblockall",index);
968 _syscmd(buf,res,sizeof(res));
969 block = atoi(res);
970
971 //Allow only those macs mentioned in ACL
972 if(block==1)
973 {
974 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
975 fprintf(fp,"%s\n",buf);
976 for(dev_count=1;dev_count<=mac_entry;dev_count++)
977 {
978 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
979 _syscmd(buf,tmp,sizeof(tmp));
980 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
981 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
982 fprintf(fp,"%s\n",buf);
983 }
984 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
985 fprintf(fp,"%s\n",buf);
986 }
987
988 //Block all the macs mentioned in ACL
989 else if(block==2)
990 {
991 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
992 fprintf(fp,"%s\n",buf);
993
994 for(dev_count=1;dev_count<=mac_entry;dev_count++)
995 {
996 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
997 _syscmd(buf,tmp,sizeof(tmp));
998 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
999 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1000 fprintf(fp,"%s\n",buf);
1001 }
1002 }
1003 }
1004 fclose(fp);
1005}
1006
1007// Initializes the wifi subsystem (all radios)
1008INT wifi_init() //RDKB
1009{
1010 char interface[MAX_BUF_SIZE]={'\0'};
1011 char bridge_name[MAX_BUF_SIZE]={'\0'};
1012 INT len=0;
1013
1014 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1015 //Not intitializing macfilter for Turris-Omnia Platform for now
1016 //macfilter_init();
1017
1018 system("/usr/sbin/iw reg set US");
1019 system("systemctl start hostapd.service");
1020 sleep(2);//sleep to wait for hostapd to start
1021
1022 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1023
1024 return RETURN_OK;
1025}
1026
1027/* wifi_reset() function */
1028/**
1029* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1030* Implementation specifics may dictate what is actualy reset since
1031* different hardware implementations may have different requirements.
1032* Parameters : None
1033*
1034* @return The status of the operation.
1035* @retval RETURN_OK if successful.
1036* @retval RETURN_ERR if any error is detected
1037*
1038* @execution Synchronous.
1039* @sideeffect None.
1040*
1041* @note This function must not suspend and must not invoke any blocking system
1042* calls. It should probably just send a message to a driver event handler task.
1043*
1044*/
1045INT wifi_reset()
1046{
1047 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001048 system("systemctl stop hostapd.service");
1049 sleep(2);
1050 system("systemctl start hostapd.service");
1051 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001052 return RETURN_OK;
1053}
1054
1055/* wifi_down() function */
1056/**
1057* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1058* Implementation specifics may dictate some functionality since
1059* different hardware implementations may have different requirements.
1060*
1061* @param None
1062*
1063* @return The status of the operation
1064* @retval RETURN_OK if successful
1065* @retval RETURN_ERR if any error is detected
1066*
1067* @execution Synchronous
1068* @sideeffect None
1069*
1070* @note This function must not suspend and must not invoke any blocking system
1071* calls. It should probably just send a message to a driver event handler task.
1072*
1073*/
1074INT wifi_down()
1075{
1076 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001077 system("systemctl stop hostapd.service");
1078 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001079 return RETURN_OK;
1080}
1081
1082
1083/* wifi_createInitialConfigFiles() function */
1084/**
1085* @description This function creates wifi configuration files. The format
1086* and content of these files are implementation dependent. This function call is
1087* used to trigger this task if necessary. Some implementations may not need this
1088* function. If an implementation does not need to create config files the function call can
1089* do nothing and return RETURN_OK.
1090*
1091* @param None
1092*
1093* @return The status of the operation
1094* @retval RETURN_OK if successful
1095* @retval RETURN_ERR if any error is detected
1096*
1097* @execution Synchronous
1098* @sideeffect None
1099*
1100* @note This function must not suspend and must not invoke any blocking system
1101* calls. It should probably just send a message to a driver event handler task.
1102*
1103*/
1104INT wifi_createInitialConfigFiles()
1105{
1106 //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)
1107 return RETURN_OK;
1108}
1109
1110// outputs the country code to a max 64 character string
1111INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1112{
developer7543b3b2022-09-13 13:47:17 +08001113 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001114 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001115 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001116
1117 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1118 _syscmd(cmd, buf, sizeof(buf));
1119 if(strlen(buf) > 0)
1120 snprintf(output_string, 64, "%s", buf);
1121 else
1122 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001123
1124 return RETURN_OK;
1125}
1126
1127INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1128{
1129 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001130 char str[MAX_BUF_SIZE]={'\0'};
1131 char cmd[MAX_CMD_SIZE]={'\0'};
1132 struct params params;
1133 char config_file[MAX_BUF_SIZE] = {0};
1134
1135 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1136 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1137 return RETURN_ERR;
1138
developerb86c6f32022-10-07 14:34:58 +08001139 if (strlen(CountryCode) == 0)
1140 strcpy(CountryCode, "US");
1141
developer7543b3b2022-09-13 13:47:17 +08001142 params.name = "country_code";
1143 params.value = CountryCode;
1144 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1145 int ret = wifi_hostapdWrite(config_file, &params, 1);
1146 if (ret) {
1147 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1148 ,__func__, ret);
1149 }
1150
1151 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1152 if (ret) {
1153 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1154 ,__func__, ret);
1155 }
developer7543b3b2022-09-13 13:47:17 +08001156 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1157
developer06a01d92022-09-07 16:32:39 +08001158 return RETURN_OK;
1159}
1160
developera748dcf2022-09-13 15:56:48 +08001161INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1162{
1163 char channel_util_file[64] = {0};
1164 char cmd[128] = {0};
1165 char buf[128] = {0};
1166 char line[128] = {0};
1167 char *param = NULL, *value = NULL;
1168 int read = 0;
1169 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1170 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1171 size_t len = 0;
1172 FILE *f = NULL;
1173
1174 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1175
1176 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1177 _syscmd(cmd, buf, sizeof(buf));
1178 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1179
1180 memset(cmd, 0, sizeof(cmd));
1181 memset(buf, 0, sizeof(buf));
1182 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1183 if ((f = popen(cmd, "r")) == NULL) {
1184 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1185 return RETURN_ERR;
1186 }
1187
1188 read = getline(&line, &len, f);
1189 while (read != -1) {
1190 param = strtok(line, ":\t");
1191 value = strtok(NULL, " ");
1192 if(strstr(param, "frequency") != NULL) {
1193 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1194 }
1195 if(strstr(param, "noise") != NULL) {
1196 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1197 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1198 }
1199 if(strstr(param, "channel active time") != NULL) {
1200 ActiveTime = strtol(value, NULL, 10);
1201 }
1202 if(strstr(param, "channel busy time") != NULL) {
1203 BusyTime = strtol(value, NULL, 10);
1204 }
1205 if(strstr(param, "channel transmit time") != NULL) {
1206 TransmitTime = strtol(value, NULL, 10);
1207 }
1208 read = getline(&line, &len, f);
1209 }
1210 pclose(f);
1211
1212 // The file should store the last active, busy and transmit time
1213 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1214 f = fopen(channel_util_file, "r");
1215 if (f != NULL) {
1216 read = getline(&line, &len, f);
1217 preActiveTime = strtol(line, NULL, 10);
1218 read = getline(&line, &len, f);
1219 preBusyTime = strtol(line, NULL, 10);
1220 read = getline(&line, &len, f);
1221 preTransmitTime = strtol(line, NULL, 10);
1222 fclose(f);
1223 }
1224
1225 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1226 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1227
1228 f = fopen(channel_util_file, "w");
1229 if (f != NULL) {
1230 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1231 fclose(f);
1232 }
1233 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1234 return RETURN_OK;
1235}
1236
developer06a01d92022-09-07 16:32:39 +08001237/**********************************************************************************
1238 *
1239 * Wifi radio level function prototypes
1240 *
1241**********************************************************************************/
1242
1243//Get the total number of radios in this wifi subsystem
1244INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1245{
1246 if (NULL == output)
1247 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001248 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001249
1250 return RETURN_OK;
1251}
1252
1253//Get the total number of SSID entries in this wifi subsystem
1254INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1255{
1256 if (NULL == output)
1257 return RETURN_ERR;
1258 *output = MAX_APS;
1259
1260 return RETURN_OK;
1261}
1262
1263//Get the Radio enable config parameter
1264INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1265{
1266 char interface_path[MAX_CMD_SIZE] = {0};
1267 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001268 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001269
1270 if (NULL == output_bool)
1271 return RETURN_ERR;
1272
1273 *output_bool = FALSE;
developer804c64f2022-10-19 13:54:40 +08001274 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
developer06a01d92022-09-07 16:32:39 +08001275 return RETURN_ERR;
1276
developer033b37b2022-10-18 11:27:46 +08001277 phyId = radio_index_to_phy(radioIndex);
1278
1279 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001280 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001281 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001282 {
developercf48e482022-09-13 14:49:50 +08001283 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001284 }
1285 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001286 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1287 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1288 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001289
developercf48e482022-09-13 14:49:50 +08001290 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1291 *output_bool = TRUE;
1292 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001293 return RETURN_OK;
1294}
1295
1296INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1297{
1298 char cmd[MAX_CMD_SIZE] = {0};
1299 char buf[MAX_CMD_SIZE] = {0};
1300 int apIndex, ret;
1301 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001302 int max_radio_num = 0;
1303 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001304
1305 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001306
1307 phyId = radio_index_to_phy(radioIndex);
1308
1309 wifi_getMaxRadioNumber(&max_radio_num);
1310
developer06a01d92022-09-07 16:32:39 +08001311 if(enable==FALSE)
1312 {
developer033b37b2022-10-18 11:27:46 +08001313 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001314 {
1315 //Detaching %s%d from hostapd daemon
1316 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1317 _syscmd(cmd, buf, sizeof(buf));
1318 if(strncmp(buf, "OK", 2))
1319 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1320 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1321 _syscmd(cmd, buf, sizeof(buf));
1322 }
developer033b37b2022-10-18 11:27:46 +08001323 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001324 _syscmd(cmd, buf, sizeof(buf));
1325 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001326 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001327 }
1328 else
1329 {
developer033b37b2022-10-18 11:27:46 +08001330 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001331 _syscmd(cmd, buf, sizeof(buf));
1332 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001333 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001334 sleep(1);
developer033b37b2022-10-18 11:27:46 +08001335
1336 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001337 {
developer033b37b2022-10-18 11:27:46 +08001338 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, phyId, AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08001339 ret = _syscmd(cmd, buf, sizeof(buf));
1340 if ( ret == RETURN_ERR)
1341 {
1342 fprintf(stderr, "VAP interface creation failed\n");
1343 continue;
1344 }
1345 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1346 _syscmd(cmd, buf, sizeof(buf));
1347 if(*buf == '1')
1348 {
1349 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001350 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001351 _syscmd(cmd, buf, sizeof(buf));
1352 if(strncmp(buf, "OK", 2))
1353 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1354 }
1355 }
1356 }
1357
1358 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1359 return RETURN_OK;
1360}
1361
1362//Get the Radio enable status
1363INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1364{
1365 if (NULL == output_bool)
1366 return RETURN_ERR;
1367
1368 return wifi_getRadioEnable(radioIndex, output_bool);
1369}
1370
1371//Get the Radio Interface name from platform, eg "wlan0"
1372INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1373{
developer033b37b2022-10-18 11:27:46 +08001374 int phyId = 0;
developer804c64f2022-10-19 13:54:40 +08001375 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001376 return RETURN_ERR;
developer033b37b2022-10-18 11:27:46 +08001377 phyId = radio_index_to_phy(radioIndex);
1378 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001379
1380 return RETURN_OK;
1381}
1382
1383//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1384//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.
1385INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1386{
developerbcc556a2022-09-22 20:02:45 +08001387 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1388 // For max bit rate, we should always choose the best MCS
1389 char mode[64] = {0};
1390 char channel_bandwidth_str[16] = {0};
1391 char *tmp = NULL;
1392 UINT mode_map = 0;
1393 UINT num_subcarrier = 0;
1394 UINT code_bits = 0;
1395 float code_rate = 0; // use max code rate
1396 int NSS = 0;
1397 UINT Symbol_duration = 0;
1398 UINT GI_duration = 0;
1399 wifi_band band = band_invalid;
1400 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1401 BOOL enable = FALSE;
1402 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001403
1404 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1405 if (NULL == output_string)
1406 return RETURN_ERR;
1407
developerbcc556a2022-09-22 20:02:45 +08001408 wifi_getRadioEnable(radioIndex, &enable);
1409 if (enable == FALSE) {
1410 snprintf(output_string, 64, "0 Mb/s");
1411 return RETURN_OK;
1412 }
1413
1414 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1415 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1416 return RETURN_ERR;
1417 }
1418
1419 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1420 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1421 return RETURN_ERR;
1422 }
1423
1424 if (gi == wifi_guard_interval_3200)
1425 GI_duration = 32;
1426 else if (gi == wifi_guard_interval_1600)
1427 GI_duration = 16;
1428 else if (gi == wifi_guard_interval_800)
1429 GI_duration = 8;
1430 else // auto, 400
1431 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001432
developerbcc556a2022-09-22 20:02:45 +08001433 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1434 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1435 return RETURN_ERR;
1436 }
1437
1438 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1439 strcpy(channel_bandwidth_str, "160");
1440
1441 if (mode_map & WIFI_MODE_AX) {
1442 if (strstr(channel_bandwidth_str, "160") != NULL)
1443 num_subcarrier = 1960;
1444 else if (strstr(channel_bandwidth_str, "80") != NULL)
1445 num_subcarrier = 980;
1446 else if (strstr(channel_bandwidth_str, "40") != NULL)
1447 num_subcarrier = 468;
1448 else if (strstr(channel_bandwidth_str, "20") != NULL)
1449 num_subcarrier = 234;
1450 code_bits = 10;
1451 code_rate = (float)5/6;
1452 Symbol_duration = 128;
1453 } else if (mode_map & WIFI_MODE_AC) {
1454 if (strstr(channel_bandwidth_str, "160") != NULL)
1455 num_subcarrier = 468;
1456 else if (strstr(channel_bandwidth_str, "80") != NULL)
1457 num_subcarrier = 234;
1458 else if (strstr(channel_bandwidth_str, "40") != NULL)
1459 num_subcarrier = 108;
1460 else if (strstr(channel_bandwidth_str, "20") != NULL)
1461 num_subcarrier = 52;
1462 code_bits = 8;
1463 code_rate = (float)5/6;
1464 Symbol_duration = 32;
1465 } else if (mode_map & WIFI_MODE_N) {
1466 if (strstr(channel_bandwidth_str, "160") != NULL)
1467 num_subcarrier = 468;
1468 else if (strstr(channel_bandwidth_str, "80") != NULL)
1469 num_subcarrier = 234;
1470 else if (strstr(channel_bandwidth_str, "40") != NULL)
1471 num_subcarrier = 108;
1472 else if (strstr(channel_bandwidth_str, "20") != NULL)
1473 num_subcarrier = 52;
1474 code_bits = 6;
1475 code_rate = (float)3/4;
1476 Symbol_duration = 32;
1477 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1478 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1479 snprintf(output_string, 64, "65 Mb/s");
1480 return RETURN_OK;
1481 } else {
1482 snprintf(output_string, 64, "0 Mb/s");
1483 return RETURN_OK;
1484 }
developer06a01d92022-09-07 16:32:39 +08001485
developerbcc556a2022-09-22 20:02:45 +08001486 // Spatial streams
1487 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1488 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1489 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001490 }
developerbcc556a2022-09-22 20:02:45 +08001491
1492 // multiple 10 is to align duration unit (0.1 us)
1493 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1494 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1495
developer06a01d92022-09-07 16:32:39 +08001496 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1497
1498 return RETURN_OK;
1499}
1500#if 0
1501INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1502{
1503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1504 char cmd[64];
1505 char buf[1024];
1506 int apIndex;
1507
1508 if (NULL == output_string)
1509 return RETURN_ERR;
1510
1511 apIndex=(radioIndex==0)?0:1;
1512
1513 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1514 _syscmd(cmd,buf, sizeof(buf));
1515
1516 snprintf(output_string, 64, "%s", buf);
1517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1518 return RETURN_OK;
1519}
1520#endif
1521
1522
1523//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1524//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.
1525INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1526{
developer963da0c2022-09-13 15:58:27 +08001527 wifi_band band = band_invalid;
1528
developer06a01d92022-09-07 16:32:39 +08001529 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1530 if (NULL == output_string)
1531 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001532
1533 band = wifi_index_to_band(radioIndex);
1534
1535 memset(output_string, 0, 10);
1536 if (band == band_2_4)
1537 strcpy(output_string, "2.4GHz");
1538 else if (band == band_5)
1539 strcpy(output_string, "5GHz");
1540 else if (band == band_6)
1541 strcpy(output_string, "6GHz");
1542 else
1543 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001544 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1545
1546 return RETURN_OK;
1547#if 0
1548 char buf[MAX_BUF_SIZE]={'\0'};
1549 char str[MAX_BUF_SIZE]={'\0'};
1550 char cmd[MAX_CMD_SIZE]={'\0'};
1551 char *ch=NULL;
1552 char *ch2=NULL;
1553
1554 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1555 if (NULL == output_string)
1556 return RETURN_ERR;
1557
1558
1559 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1560
1561 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1562 {
1563 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1564 return RETURN_ERR;
1565 }
1566 ch=strchr(buf,'\n');
1567 *ch='\0';
1568 ch=strchr(buf,'=');
1569 if(ch==NULL)
1570 return RETURN_ERR;
1571
1572
1573 ch++;
1574
1575 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1576 strcpy(buf,"0");
1577 if(strlen(ch) == 1)
1578 ch=strcat(buf,ch);
1579
1580
1581 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1582
1583 if(_syscmd(cmd,str,64) == RETURN_ERR)
1584 {
1585 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1586 return RETURN_ERR;
1587 }
1588
1589
1590 ch2=strchr(str,'\n');
1591 //replace \n with \0
1592 *ch2='\0';
1593 ch2=strchr(str,'=');
1594 if(ch2==NULL)
1595 {
1596 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1597 return RETURN_ERR;
1598 }
1599 else
1600 wifi_dbg_printf("%s",ch2+1);
1601
1602
1603 ch2++;
1604
1605
1606 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1607
1608 memset(buf,'\0',sizeof(buf));
1609 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1610 {
1611 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1612 return RETURN_ERR;
1613 }
1614 if (strstr(buf,"2.4") != NULL )
1615 strcpy(output_string,"2.4GHz");
1616 else if(strstr(buf,"5.") != NULL )
1617 strcpy(output_string,"5GHz");
1618 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1619
1620 return RETURN_OK;
1621#endif
1622}
1623
1624//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1625//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.
1626INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1627{
developerb7593de2022-10-18 09:51:57 +08001628 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1630 if (NULL == output_string)
1631 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001632 band = wifi_index_to_band(radioIndex);
1633
1634 if (band == band_2_4)
1635 snprintf(output_string, 64, "2.4GHz");
1636 else if (band == band_5)
1637 snprintf(output_string, 64, "5GHz");
1638 else if (band == band_6)
1639 snprintf(output_string, 64, "6GHz");
1640
developer06a01d92022-09-07 16:32:39 +08001641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1642
1643 return RETURN_OK;
1644#if 0
1645 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1646 char buf[MAX_BUF_SIZE]={'\0'};
1647 char str[MAX_BUF_SIZE]={'\0'};
1648 char cmd[MAX_CMD_SIZE]={'\0'};
1649 char *ch=NULL;
1650 char *ch2=NULL;
1651 char ch1[5]="0";
1652
1653 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1654
1655 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1656 {
1657 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1658 return RETURN_ERR;
1659 }
1660
1661 ch=strchr(buf,'\n');
1662 *ch='\0';
1663 ch=strchr(buf,'=');
1664 if(ch==NULL)
1665 return RETURN_ERR;
1666 ch++;
1667
1668 if(strlen(ch)==1)
1669 {
1670 strcat(ch1,ch);
1671
1672 }
1673 else
1674 {
1675 strcpy(ch1,ch);
1676 }
1677
1678
1679
1680 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1681 if(_syscmd(cmd,str,64) == RETURN_ERR)
1682 {
1683 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1684 return RETURN_ERR;
1685 }
1686
1687
1688 ch2=strchr(str,'\n');
1689 //replace \n with \0
1690 *ch2='\0';
1691 ch2=strchr(str,'=');
1692 if(ch2==NULL)
1693 {
1694 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1695 return RETURN_ERR;
1696 }
1697 else
1698 wifi_dbg_printf("%s",ch2+1);
1699 ch2++;
1700
1701
1702 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1703 memset(buf,'\0',sizeof(buf));
1704 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1705 {
1706 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1707 return RETURN_ERR;
1708 }
1709
1710
1711 if(strstr(buf,"2.4")!=NULL)
1712 {
1713 strcpy(output_string,"2.4GHz");
1714 }
1715 if(strstr(buf,"5.")!=NULL)
1716 {
1717 strcpy(output_string,"5GHz");
1718 }
1719 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1720 return RETURN_OK;
1721#endif
1722}
1723
1724//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1725//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.
1726INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1727{
developer963da0c2022-09-13 15:58:27 +08001728 char cmd[128]={0};
1729 char buf[128]={0};
1730 char temp_output[128] = {0};
1731 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001732 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001733
1734 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001735 if (NULL == output_string)
1736 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001737
1738 band = wifi_index_to_band(radioIndex);
1739 if (band == band_2_4) {
1740 strcat(temp_output, "b,g,");
1741 } else if (band == band_5) {
1742 strcat(temp_output, "a,");
1743 }
developer033b37b2022-10-18 11:27:46 +08001744 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001745 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001746 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001747 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001748 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001749 strcat(temp_output, "n,");
1750 }
developer06a01d92022-09-07 16:32:39 +08001751
developer963da0c2022-09-13 15:58:27 +08001752 // vht capabilities
1753 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001754 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001755 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001756 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001757 strcat(temp_output, "ac,");
1758 }
1759 }
1760
1761 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001762 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
developer963da0c2022-09-13 15:58:27 +08001763 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001764 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001765 strcat(temp_output, "ax,");
1766 }
1767
1768 // Remove the last comma
1769 if (strlen(temp_output) != 0)
1770 temp_output[strlen(temp_output)-1] = '\0';
1771 strncpy(output_string, temp_output, strlen(temp_output));
1772 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001773 return RETURN_OK;
1774}
1775
1776//Get the radio operating mode, and pure mode flag. eg: "ac"
1777//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.
1778INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1779{
1780 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1781 if (NULL == output_string)
1782 return RETURN_ERR;
1783
1784 if (radioIndex == 0) {
1785 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1786 *gOnly = FALSE;
1787 *nOnly = TRUE;
1788 *acOnly = FALSE;
1789 } else {
1790 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1791 *gOnly = FALSE;
1792 *nOnly = FALSE;
1793 *acOnly = FALSE;
1794 }
1795 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1796
1797 return RETURN_OK;
1798#if 0
1799 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1800 char buf[64] = {0};
1801 char config_file[MAX_BUF_SIZE] = {0};
1802
1803 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1804 return RETURN_ERR;
1805
1806 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1807 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1808
1809 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1810 if (strlen(buf) == 0)
1811 {
1812 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1813 return RETURN_ERR;
1814 }
1815 if(strcmp(buf,"g")==0)
1816 {
1817 wifi_dbg_printf("\nG\n");
1818 *gOnly=TRUE;
1819 *nOnly=FALSE;
1820 *acOnly=FALSE;
1821 }
1822 else if(strcmp(buf,"n")==0)
1823 {
1824 wifi_dbg_printf("\nN\n");
1825 *gOnly=FALSE;
1826 *nOnly=TRUE;
1827 *acOnly=FALSE;
1828 }
1829 else if(strcmp(buf,"ac")==0)
1830 {
1831 wifi_dbg_printf("\nac\n");
1832 *gOnly=FALSE;
1833 *nOnly=FALSE;
1834 *acOnly=TRUE;
1835 }
1836 /* hostapd-5G.conf has "a" as hw_mode */
1837 else if(strcmp(buf,"a")==0)
1838 {
1839 wifi_dbg_printf("\na\n");
1840 *gOnly=FALSE;
1841 *nOnly=FALSE;
1842 *acOnly=FALSE;
1843 }
1844 else
1845 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1846
1847 //for a,n mode
1848 if(radioIndex == 1)
1849 {
1850 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1851 if(strcmp(buf,"1")==0)
1852 {
1853 strncpy(output_string, "n", 1);
1854 *nOnly=FALSE;
1855 }
1856 }
1857
1858 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1859 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1860 return RETURN_OK;
1861#endif
1862}
1863
developerdb744382022-09-13 15:34:54 +08001864INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1865{
1866 char cmd[128] = {0};
1867 char buf[64] = {0};
1868 char config_file[64] = {0};
1869 wifi_band band;
1870
1871 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1872 if(NULL == output_string || NULL == pureMode)
1873 return RETURN_ERR;
1874
1875 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001876 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerdb744382022-09-13 15:34:54 +08001877 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1878 _syscmd(cmd, buf, sizeof(buf));
1879
1880 band = wifi_index_to_band(radioIndex);
1881 // puremode is a bit map
1882 *pureMode = 0;
1883 if (band == band_2_4) {
1884 strcat(output_string, "b,g");
1885 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1886 if (strstr(buf, "n") != NULL) {
1887 strcat(output_string, ",n");
1888 *pureMode |= WIFI_MODE_N;
1889 }
1890 if (strstr(buf, "ax") != NULL) {
1891 strcat(output_string, ",ax");
1892 *pureMode |= WIFI_MODE_AX;
1893 }
1894 } else if (band == band_5) {
1895 strcat(output_string, "a");
1896 *pureMode |= WIFI_MODE_A;
1897 if (strstr(buf, "n") != NULL) {
1898 strcat(output_string, ",n");
1899 *pureMode |= WIFI_MODE_N;
1900 }
1901 if (strstr(buf, "ac") != NULL) {
1902 strcat(output_string, ",ac");
1903 *pureMode |= WIFI_MODE_AC;
1904 }
1905 if (strstr(buf, "ax") != NULL) {
1906 strcat(output_string, ",ax");
1907 *pureMode |= WIFI_MODE_AX;
1908 }
1909 } else if (band == band_6) {
1910 if (strstr(buf, "ax") != NULL) {
1911 strcat(output_string, "ax");
1912 *pureMode |= WIFI_MODE_AX;
1913 }
1914 }
1915
1916 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1917 return RETURN_OK;
1918}
1919
1920// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001921INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1922{
1923 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1924 if (strcmp (channelMode,"11A") == 0)
1925 {
1926 writeBandWidth(radioIndex,"20MHz");
1927 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1928 printf("\nChannel Mode is 802.11a (5GHz)\n");
1929 }
1930 else if (strcmp (channelMode,"11NAHT20") == 0)
1931 {
1932 writeBandWidth(radioIndex,"20MHz");
1933 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1934 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1935 }
1936 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1937 {
1938 writeBandWidth(radioIndex,"40MHz");
1939 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1940 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1941 }
1942 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1943 {
1944 writeBandWidth(radioIndex,"40MHz");
1945 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1946 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1947 }
1948 else if (strcmp (channelMode,"11ACVHT20") == 0)
1949 {
1950 writeBandWidth(radioIndex,"20MHz");
1951 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1952 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1953 }
1954 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1955 {
1956 writeBandWidth(radioIndex,"40MHz");
1957 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1958 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1959 }
1960 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1961 {
1962 writeBandWidth(radioIndex,"40MHz");
1963 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1964 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1965 }
1966 else if (strcmp (channelMode,"11ACVHT80") == 0)
1967 {
1968 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1969 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1970 }
1971 else if (strcmp (channelMode,"11ACVHT160") == 0)
1972 {
1973 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1974 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1975 }
1976 else if (strcmp (channelMode,"11B") == 0)
1977 {
1978 writeBandWidth(radioIndex,"20MHz");
1979 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1980 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1981 }
1982 else if (strcmp (channelMode,"11G") == 0)
1983 {
1984 writeBandWidth(radioIndex,"20MHz");
1985 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1986 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1987 }
1988 else if (strcmp (channelMode,"11NGHT20") == 0)
1989 {
1990 writeBandWidth(radioIndex,"20MHz");
1991 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1992 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1993 }
1994 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1995 {
1996 writeBandWidth(radioIndex,"40MHz");
1997 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1998 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1999 }
2000 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2001 {
2002 writeBandWidth(radioIndex,"40MHz");
2003 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2004 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2005 }
2006 else
2007 {
2008 return RETURN_ERR;
2009 }
2010 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2011
2012 return RETURN_OK;
2013}
2014
developerdb744382022-09-13 15:34:54 +08002015// Set the radio operating mode, and pure mode flag.
2016INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2017{
2018 int num_hostapd_support_mode = 3; // n, ac, ax
2019 struct params list[num_hostapd_support_mode];
2020 char config_file[64] = {0};
2021 char bandwidth[16] = {0};
2022 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08002023
developerdb744382022-09-13 15:34:54 +08002024
2025 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2026 // Set radio mode
2027 list[0].name = "ieee80211n";
2028 list[1].name = "ieee80211ac";
2029 list[2].name = "ieee80211ax";
2030 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2031
2032 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002033 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002034 list[0].value = "1";
2035 else
2036 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002037 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002038 list[1].value = "1";
2039 else
2040 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002041 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002042 list[2].value = "1";
2043 else
2044 list[2].value = "0";
2045 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2046
2047 if (channelMode == NULL || strlen(channelMode) == 0)
2048 return RETURN_OK;
2049 // Set bandwidth
2050 if (strstr(channelMode, "40") != NULL)
2051 strcpy(bandwidth, "40MHz");
2052 else if (strstr(channelMode, "80") != NULL)
2053 strcpy(bandwidth, "80MHz");
2054 else if (strstr(channelMode, "160") != NULL)
2055 strcpy(bandwidth, "160MHz");
2056 else // 11A, 11B, 11G....
2057 strcpy(bandwidth, "20MHz");
2058
2059 writeBandWidth(radioIndex, bandwidth);
2060 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2061
2062 wifi_reloadAp(radioIndex);
2063 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2064
2065 return RETURN_OK;
2066}
2067
developer1d12ebf2022-10-04 15:13:38 +08002068INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2069
2070 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002071 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002072 struct params params = {0};
2073 wifi_band band = band_invalid;
2074
2075 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2076
2077 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002078
2079 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002080 return RETURN_ERR;
2081 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2082 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002083 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2084 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002085
2086 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2087 params.name = "hw_mode";
2088 params.value = hw_mode;
2089 wifi_hostapdWrite(config_file, &params, 1);
2090 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2091
developeref938762022-10-19 17:21:01 +08002092 if (band == band_2_4) {
2093 if (strncmp(hw_mode, "b", 1) == 0) {
2094 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2095 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2096 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2097 snprintf(buf, sizeof(buf), "%s", "1,2");
2098 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2099 } else {
2100 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2101
2102 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2103 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2104 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2105 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2106 }
2107 }
2108
developer1d12ebf2022-10-04 15:13:38 +08002109 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2110 return RETURN_OK;
2111}
2112
developere8988ba2022-10-18 17:42:30 +08002113INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2114{
2115 char config_file[64] = {0};
2116 struct params params = {0};
2117 wifi_band band = band_invalid;
2118
2119 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2120
2121 band = wifi_index_to_band(radioIndex);
developer30423732022-12-01 16:17:49 +08002122 if (band != band_2_4)
2123 return RETURN_OK;
developere8988ba2022-10-18 17:42:30 +08002124
2125 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2126 params.name = "noscan";
2127 params.value = noscan;
2128 wifi_hostapdWrite(config_file, &params, 1);
2129 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2130
2131 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2132 return RETURN_OK;
2133}
2134
developer06a01d92022-09-07 16:32:39 +08002135//Get the list of supported channel. eg: "1-11"
2136//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.
2137INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2138{
developer6318ed52022-09-13 15:17:58 +08002139 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002140 if (NULL == output_string)
2141 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002142 char cmd[256] = {0};
2143 char buf[128] = {0};
2144 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002145 int phyId = 0;
2146
developer6318ed52022-09-13 15:17:58 +08002147 // Parse possible channel number and separate them with commas.
2148 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002149 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002150 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002151 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002152 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer6318ed52022-09-13 15:17:58 +08002153 else
developer033b37b2022-10-18 11:27:46 +08002154 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar\\|no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer6318ed52022-09-13 15:17:58 +08002155
2156 _syscmd(cmd,buf,sizeof(buf));
2157 strncpy(output_string, buf, sizeof(buf));
2158
2159 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2160 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002161}
2162
2163//Get the list for used channel. eg: "1,6,9,11"
2164//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.
2165INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2166{
developerf5745ee2022-10-05 16:09:53 +08002167 char cmd[128] = {0};
2168 char buf[128] = {0};
2169 char config_file[64] = {0};
2170 int channel = 0;
2171 int freq = 0;
2172 int bandwidth = 0;
2173 int center_freq = 0;
2174 int center_channel = 0;
2175 int channel_delta = 0;
2176 wifi_band band = band_invalid;
2177
2178 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2179
developer06a01d92022-09-07 16:32:39 +08002180 if (NULL == output_string)
2181 return RETURN_ERR;
2182
developerf5745ee2022-10-05 16:09:53 +08002183 sprintf(cmd, "iw %s%d info | grep channel | sed -e 's/[^0-9 ]//g'", AP_PREFIX, radioIndex);
2184 _syscmd(cmd, buf, sizeof(buf));
2185 if (strlen(buf) == 0) {
2186 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2187 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002188 }
developerf5745ee2022-10-05 16:09:53 +08002189 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2190
2191 if (bandwidth == 20) {
2192 snprintf(output_string, 256, "%d", channel);
2193 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002194 }
developerf5745ee2022-10-05 16:09:53 +08002195
2196 center_channel = ieee80211_frequency_to_channel(center_freq);
2197
2198 band = wifi_index_to_band(radioIndex);
2199 if (band == band_2_4 && bandwidth == 40) {
2200 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2201 memset(buf, 0, sizeof(buf));
2202 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2203
2204 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel") == 0) && channel < 10) {
2205 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2206 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel") == 0) && channel > 4) {
2207 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2208 } else {
2209 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2210 return RETURN_ERR;
2211 }
2212 } else if (band == band_5 || band == band_6){
2213 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2214 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2215 channel_delta = (bandwidth-20)/10;
2216 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2217 } else
2218 return RETURN_ERR;
2219
2220 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002221 return RETURN_OK;
2222}
2223
2224//Get the running channel number
2225INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2226{
developer5b398df2022-11-17 20:39:48 +08002227 char channel_str[16] = {0};
2228 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002229
developer5b398df2022-11-17 20:39:48 +08002230 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002231 return RETURN_ERR;
2232
developer5b398df2022-11-17 20:39:48 +08002233 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2234 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002235
developer5b398df2022-11-17 20:39:48 +08002236 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002237
developer06a01d92022-09-07 16:32:39 +08002238 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002239}
2240
2241
2242INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2243{
2244 char cmd[1024] = {0}, buf[5] = {0};
2245 char interface_name[50] = {0};
2246
2247 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2248 if (NULL == output_ulong)
2249 return RETURN_ERR;
2250
2251 wifi_getApName(apIndex,interface_name);
2252 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2253 _syscmd(cmd,buf,sizeof(buf));
2254 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2255 if (*output_ulong == 0) {
2256 return RETURN_ERR;
2257 }
2258
2259 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2260 return RETURN_OK;
2261}
2262
2263//Storing the previous channel value
2264INT wifi_storeprevchanval(INT radioIndex)
2265{
2266 char buf[256] = {0};
2267 char output[4]={'\0'};
2268 char config_file[MAX_BUF_SIZE] = {0};
2269 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2270 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2271 if(radioIndex == 0)
2272 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2273 else if(radioIndex == 1)
2274 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2275 system(buf);
2276 Radio_flag = FALSE;
2277 return RETURN_OK;
2278}
2279
2280//Set the running channel number
2281INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2282{
developer76989232022-10-04 14:13:19 +08002283 // We only write hostapd config here
2284 char str_channel[8]={0};
2285 char *list_channel;
2286 char config_file[128] = {0};
2287 char possible_channels[256] = {0};
2288 int max_radio_num = 0;
2289 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002290
developer76989232022-10-04 14:13:19 +08002291 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002292
developer76989232022-10-04 14:13:19 +08002293 // Check valid
2294 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002295
developer76989232022-10-04 14:13:19 +08002296 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2297 list_channel = strtok(possible_channels, ",");
2298 while(true)
developer06a01d92022-09-07 16:32:39 +08002299 {
developer76989232022-10-04 14:13:19 +08002300 if(list_channel == NULL) { // input not in the list
2301 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2302 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002303 }
developer76989232022-10-04 14:13:19 +08002304 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2305 break;
2306 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002307 }
2308
developer76989232022-10-04 14:13:19 +08002309 list.name = "channel";
2310 list.value = str_channel;
2311 wifi_getMaxRadioNumber(&max_radio_num);
2312 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002313 {
developer76989232022-10-04 14:13:19 +08002314 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2315 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002316 }
2317
developer76989232022-10-04 14:13:19 +08002318 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002319 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002320}
developer06a01d92022-09-07 16:32:39 +08002321
2322INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2323{
developer76989232022-10-04 14:13:19 +08002324 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002325 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002326 char config_file[64];
2327 int max_num_radios = 0;
2328 wifi_band band = band_invalid;
2329
2330 band = wifi_index_to_band(radioIndex);
2331 if (band == band_2_4)
2332 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002333
developer30423732022-12-01 16:17:49 +08002334 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002335 list[0].name = "vht_oper_centr_freq_seg0_idx";
2336 list[0].value = str_idx;
2337 list[1].name = "he_oper_centr_freq_seg0_idx";
2338 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002339
developer76989232022-10-04 14:13:19 +08002340 wifi_getMaxRadioNumber(&max_num_radios);
2341 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002342 {
developer76989232022-10-04 14:13:19 +08002343 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2344 if (band == band_6)
2345 wifi_hostapdWrite(config_file, &list[1], 1);
2346 else
2347 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002348 }
2349
2350 return RETURN_OK;
2351}
2352
2353//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2354//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2355INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2356{
2357 //Set to wifi config only. Wait for wifi reset to apply.
2358 char buf[256] = {0};
2359 char str_channel[256] = {0};
2360 int count = 0;
2361 ULONG Value = 0;
2362 FILE *fp = NULL;
2363 if(enable == TRUE)
2364 {
developer06a01d92022-09-07 16:32:39 +08002365 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002366 }
developer5884e982022-10-06 10:52:50 +08002367 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002368}
2369
developer0b246d12022-09-30 15:24:20 +08002370INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2371{
2372 if (output_bool == NULL)
2373 return RETURN_ERR;
2374
2375 *output_bool = TRUE;
2376
2377 return RETURN_OK;
2378}
2379
developer06a01d92022-09-07 16:32:39 +08002380INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2381{
2382 if (NULL == output_bool)
2383 return RETURN_ERR;
2384 *output_bool=FALSE;
2385 return RETURN_OK;
2386}
2387
2388INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2389{
2390 if (NULL == output_bool)
2391 return RETURN_ERR;
2392 *output_bool=FALSE;
2393 return RETURN_OK;
2394}
2395
2396INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2397{
2398 //Set to wifi config only. Wait for wifi reset to apply.
2399 return RETURN_OK;
2400}
2401
2402INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2403{
2404 return RETURN_OK;
2405}
2406
2407INT wifi_factoryResetAP(int apIndex)
2408{
developer838cca92022-10-03 13:19:57 +08002409 char ap_config_file[64] = {0};
2410 char cmd[128] = {0};
2411
developer06a01d92022-09-07 16:32:39 +08002412 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002413
2414 wifi_setApEnable(apIndex, FALSE);
2415 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2416 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2417 wifi_setApEnable(apIndex, TRUE);
2418
developer06a01d92022-09-07 16:32:39 +08002419 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002420
developer06a01d92022-09-07 16:32:39 +08002421 return RETURN_OK;
2422}
2423
2424//To set Band Steering AP group
2425//To-do
2426INT wifi_setBandSteeringApGroup(char *ApGroup)
2427{
2428 return RETURN_OK;
2429}
2430
developer1e5aa162022-09-13 16:06:24 +08002431INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2432{
2433 char config_file[128] = {'\0'};
2434 char buf[128] = {'\0'};
2435
2436 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2437 if (dtimInterval == NULL)
2438 return RETURN_ERR;
2439
2440 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2441 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2442
2443 if (strlen(buf) == 0) {
2444 *dtimInterval = 2;
2445 } else {
2446 *dtimInterval = strtoul(buf, NULL, 10);
2447 }
2448
2449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2450 return RETURN_OK;
2451}
2452
developer06a01d92022-09-07 16:32:39 +08002453INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2454{
developer5f222492022-09-13 15:21:52 +08002455 struct params params={0};
2456 char config_file[MAX_BUF_SIZE] = {'\0'};
2457 char buf[MAX_BUF_SIZE] = {'\0'};
2458
2459 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2460 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002461 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002462 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002463 }
2464
2465 params.name = "dtim_period";
2466 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2467 params.value = buf;
2468
2469 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2470 wifi_hostapdWrite(config_file, &params, 1);
2471 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2472
2473 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2474 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002475}
2476
2477//Check if the driver support the Dfs
2478INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2479{
developer78a15382022-11-02 10:57:40 +08002480 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002481 if (NULL == output_bool)
2482 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002483 *output_bool=FALSE;
2484
2485 band = wifi_index_to_band(radioIndex);
2486 if (band == band_5)
2487 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002488 return RETURN_OK;
2489}
2490
2491//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.
2492//The value of this parameter is a comma seperated list of channel number
2493INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2494{
2495 if (NULL == output_pool)
2496 return RETURN_ERR;
2497 if (radioIndex==1)
2498 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2499 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2500
2501 return RETURN_OK;
2502}
2503
2504INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2505{
2506 //Set to wifi config. And apply instantly.
2507 return RETURN_OK;
2508}
2509
2510INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2511{
2512 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2513 return RETURN_ERR;
2514 *output_interval_seconds=1800;
2515 *output_dwell_milliseconds=40;
2516
2517 return RETURN_OK;
2518}
2519
2520INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2521{
2522 //Set to wifi config. And apply instantly.
2523 return RETURN_OK;
2524}
2525
developerbfc18512022-10-05 17:54:28 +08002526INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2527{
2528 if (output_bool == NULL)
2529 return RETURN_ERR;
2530 *output_bool = true;
2531 return RETURN_OK;
2532}
2533
2534INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2535{
2536 return RETURN_OK;
2537}
2538
developer06a01d92022-09-07 16:32:39 +08002539//Get the Dfs enable status
2540INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2541{
developer9964b5b2022-09-13 15:59:34 +08002542 char buf[16] = {0};
2543 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002544
2545 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2546
developer30423732022-12-01 16:17:49 +08002547 if (output_bool == NULL)
2548 return RETURN_ERR;
2549
developer9964b5b2022-09-13 15:59:34 +08002550 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002551 if (NULL == output_bool)
2552 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002553
developer9964b5b2022-09-13 15:59:34 +08002554 f = fopen(DFS_ENABLE_FILE, "r");
2555 if (f != NULL) {
2556 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002557 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002558 *output_bool = FALSE;
2559 fclose(f);
2560 }
2561 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002562 return RETURN_OK;
2563}
2564
2565//Set the Dfs enable status
2566INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2567{
developer9964b5b2022-09-13 15:59:34 +08002568 char config_file[128] = {0};
2569 FILE *f = NULL;
2570 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002571
2572 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2573
developer9964b5b2022-09-13 15:59:34 +08002574 f = fopen(DFS_ENABLE_FILE, "w");
2575 if (f == NULL)
2576 return RETURN_ERR;
2577 fprintf(f, "%d", enable);
2578 fclose(f);
2579
2580 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002581 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002582 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2583 wifi_hostapdWrite(config_file, &params, 1);
2584 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2585
2586 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2587
developer9964b5b2022-09-13 15:59:34 +08002588 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002589 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002590}
2591
2592//Check if the driver support the AutoChannelRefreshPeriod
2593INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2594{
2595 if (NULL == output_bool)
2596 return RETURN_ERR;
2597 *output_bool=FALSE; //not support
2598
2599 return RETURN_OK;
2600}
2601
2602//Get the ACS refresh period in seconds
2603INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2604{
2605 if (NULL == output_ulong)
2606 return RETURN_ERR;
2607 *output_ulong=300;
2608
2609 return RETURN_OK;
2610}
2611
2612//Set the ACS refresh period in seconds
2613INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2614{
2615 return RETURN_ERR;
2616}
2617
2618//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2619//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.
2620INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2621{
developer70490032022-09-13 15:45:20 +08002622 char cmd[128] = {0}, buf[64] = {0};
2623 char interface_name[64] = {0};
2624 int ret = 0, len=0;
2625 BOOL radio_enable = FALSE;
2626
2627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2628
developer06a01d92022-09-07 16:32:39 +08002629 if (NULL == output_string)
2630 return RETURN_ERR;
2631
developer70490032022-09-13 15:45:20 +08002632 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2633 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002634
developer70490032022-09-13 15:45:20 +08002635 if (radio_enable != TRUE)
2636 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002637
developer70490032022-09-13 15:45:20 +08002638 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002639 ret = _syscmd(cmd, buf, sizeof(buf));
2640 len = strlen(buf);
2641 if((ret != 0) || (len == 0))
2642 {
2643 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2644 return RETURN_ERR;
2645 }
2646
2647 buf[len-1] = '\0';
2648 snprintf(output_string, 64, "%sMHz", buf);
2649 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2650
2651#if 0
2652 //TODO: revisit below implementation
2653 char output_buf[8]={0};
2654 char bw_value[10];
2655 char config_file[MAX_BUF_SIZE] = {0};
2656
2657 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2658 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2659 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2660 readBandWidth(radioIndex,bw_value);
2661
2662 if(strstr (output_buf,"0") != NULL )
2663 {
2664 strcpy(output_string,bw_value);
2665 }
2666 else if (strstr (output_buf,"1") != NULL)
2667 {
2668 strcpy(output_string,"80MHz");
2669 }
2670 else if (strstr (output_buf,"2") != NULL)
2671 {
2672 strcpy(output_string,"160MHz");
2673 }
2674 else if (strstr (output_buf,"3") != NULL)
2675 {
2676 strcpy(output_string,"80+80");
2677 }
2678 else
2679 {
2680 strcpy(output_string,"Auto");
2681 }
2682 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2683#endif
2684
2685 return RETURN_OK;
2686}
2687
2688//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002689INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002690{
developerf7a466e2022-09-29 11:55:56 +08002691 char config_file[128];
2692 char set_value[16];
2693 struct params params[2];
2694 int max_radio_num = 0;
2695
developer06a01d92022-09-07 16:32:39 +08002696 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002697
developerf7a466e2022-09-29 11:55:56 +08002698 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002699 return RETURN_ERR;
2700
developerf7a466e2022-09-29 11:55:56 +08002701 if(strstr(bandwidth,"80+80") != NULL)
2702 strcpy(set_value, "3");
2703 else if(strstr(bandwidth,"160") != NULL)
2704 strcpy(set_value, "2");
2705 else if(strstr(bandwidth,"80") != NULL)
2706 strcpy(set_value, "1");
2707 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2708 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002709 else
2710 {
developerf7a466e2022-09-29 11:55:56 +08002711 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002712 return RETURN_ERR;
2713 }
2714
developerf7a466e2022-09-29 11:55:56 +08002715 params[0].name = "vht_oper_chwidth";
2716 params[0].value = set_value;
2717 params[1].name = "he_oper_chwidth";
2718 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002719
developerf7a466e2022-09-29 11:55:56 +08002720 wifi_getMaxRadioNumber(&max_radio_num);
2721 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002722 {
developerf7a466e2022-09-29 11:55:56 +08002723 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2724 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002725 }
2726
2727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2728 return RETURN_OK;
2729}
2730
2731//Getting current radio extension channel
2732INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2733{
2734 CHAR buf[150] = {0};
2735 CHAR cmd[150] = {0};
2736 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2737 _syscmd(cmd, buf, sizeof(buf));
2738 if(NULL != strstr(buf,"HT40+"))
2739 strcpy(Value,"AboveControlChannel");
2740 else if(NULL != strstr(buf,"HT40-"))
2741 strcpy(Value,"BelowControlChannel");
2742 return RETURN_OK;
2743}
2744
2745//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2746//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.
2747INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2748{
2749 if (NULL == output_string)
2750 return RETURN_ERR;
2751
2752 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2753#if 0
2754 CHAR Value[100] = {0};
2755 if (NULL == output_string)
2756 return RETURN_ERR;
2757 if(radioIndex == 0)
2758 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2759 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2760 {
2761 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2762 if(strcmp(Value,"40MHz") == 0)
2763 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2764 else
2765 strcpy(Value,"Auto");
2766 }
2767 strcpy(output_string,Value);
2768#endif
2769
2770 return RETURN_OK;
2771}
2772
2773//Set the extension channel.
2774INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2775{
2776 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2777 struct params params={'\0'};
2778 char config_file[MAX_BUF_SIZE] = {0};
2779 char ext_channel[127]={'\0'};
developer033b37b2022-10-18 11:27:46 +08002780 int max_radio_num =0;
developer06a01d92022-09-07 16:32:39 +08002781 params.name = "ht_capab";
2782
developer033b37b2022-10-18 11:27:46 +08002783 if(NULL!= strstr(string,"Above"))
2784 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
2785 else if(NULL!= strstr(string,"Below"))
2786 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
2787 else
2788 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
2789
developer06a01d92022-09-07 16:32:39 +08002790
2791 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002792
2793 wifi_getMaxRadioNumber(&max_radio_num);
2794 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002795 {
developer033b37b2022-10-18 11:27:46 +08002796 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002797 wifi_hostapdWrite(config_file, &params, 1);
2798 }
2799
2800 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2801 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2802 return RETURN_OK;
2803}
2804
2805//Get the guard interval value. eg "400nsec" or "800nsec"
2806//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.
2807INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2808{
developer454b9462022-09-13 15:29:16 +08002809 wifi_guard_interval_t GI;
2810
2811 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2812
2813 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002814 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002815
2816 if (GI == wifi_guard_interval_400)
2817 strcpy(output_string, "400nsec");
2818 else if (GI == wifi_guard_interval_800)
2819 strcpy(output_string, "800nsec");
2820 else if (GI == wifi_guard_interval_1600)
2821 strcpy(output_string, "1600nsec");
2822 else if (GI == wifi_guard_interval_3200)
2823 strcpy(output_string, "3200nsec");
2824 else
developer78a15382022-11-02 10:57:40 +08002825 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08002826
developer454b9462022-09-13 15:29:16 +08002827 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002828 return RETURN_OK;
2829}
2830
2831//Set the guard interval value.
2832INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2833{
developer454b9462022-09-13 15:29:16 +08002834 wifi_guard_interval_t GI;
2835 int ret = 0;
2836
2837 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2838
2839 if (strcmp(string, "400nsec") == 0)
2840 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002841 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002842 GI = wifi_guard_interval_800;
2843 else if (strcmp(string , "1600nsec") == 0)
2844 GI = wifi_guard_interval_1600;
2845 else if (strcmp(string , "3200nsec") == 0)
2846 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002847 else
2848 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002849
2850 ret = wifi_setGuardInterval(radioIndex, GI);
2851
2852 if (ret == RETURN_ERR) {
2853 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2854 return RETURN_ERR;
2855 }
2856
2857 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2858 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002859}
2860
2861//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2862INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2863{
developerf49437e2022-09-29 19:58:21 +08002864 char buf[32]={0};
2865 char mcs_file[64] = {0};
2866 char cmd[64] = {0};
2867 int mode_bitmap = 0;
2868
2869 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2870 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002871 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002872 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2873
2874 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2875 _syscmd(cmd, buf, sizeof(buf));
2876 if (strlen(buf) > 0)
2877 *output_int = strtol(buf, NULL, 10);
2878 else {
2879 // output the max MCS for the current radio mode
2880 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2881 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2882 return RETURN_ERR;
2883 }
2884 if (mode_bitmap & WIFI_MODE_AX) {
2885 *output_int = 11;
2886 } else if (mode_bitmap & WIFI_MODE_AC) {
2887 *output_int = 9;
2888 } else if (mode_bitmap & WIFI_MODE_N) {
2889 *output_int = 7;
2890 }
2891 }
2892 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002893
2894 return RETURN_OK;
2895}
2896
2897//Set the Modulation Coding Scheme index
2898INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2899{
developerf49437e2022-09-29 19:58:21 +08002900 // Only HE mode can specify MCS capability. We don't support MCS in HT mode, because that would be ambiguous (MCS code 8~11 refer to 2 NSS in HT but 1 NSS in HE adn VHT).
2901 char config_file[64] = {0};
2902 char set_value[16] = {0};
2903 char mcs_file[32] = {0};
2904 wifi_band band = band_invalid;
2905 struct params set_config = {0};
2906 FILE *f = NULL;
2907
2908 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2909
2910 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2911
developer78a15382022-11-02 10:57:40 +08002912 // -1 means auto
2913 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08002914 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2915 return RETURN_ERR;
2916 }
2917
developer78a15382022-11-02 10:57:40 +08002918 if (MCS > 9 || MCS == -1)
2919 strcpy(set_value, "2");
2920 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08002921 strcpy(set_value, "1");
2922 else
developer78a15382022-11-02 10:57:40 +08002923 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08002924
2925 set_config.name = "he_basic_mcs_nss_set";
2926 set_config.value = set_value;
2927
2928 wifi_hostapdWrite(config_file, &set_config, 1);
2929 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2930
2931 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2932 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2933 f = fopen(mcs_file, "w");
2934 if (f == NULL) {
2935 fprintf(stderr, "%s: fopen failed\n", __func__);
2936 return RETURN_ERR;
2937 }
2938 fprintf(f, "%d", MCS);
2939 fclose(f);
2940
2941 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2942 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002943}
2944
2945//Get supported Transmit Power list, eg : "0,25,50,75,100"
2946//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.
2947INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2948{
2949 if (NULL == output_list)
2950 return RETURN_ERR;
2951 snprintf(output_list, 64,"0,25,50,75,100");
2952 return RETURN_OK;
2953}
2954
developera5005b62022-09-13 15:43:35 +08002955//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002956//The transmite power level is in units of full power for this radio.
2957INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2958{
2959 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002960 char buf[16]={0};
2961 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002962
developera5005b62022-09-13 15:43:35 +08002963 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002964 return RETURN_ERR;
2965
developera5005b62022-09-13 15:43:35 +08002966 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 +08002967 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002968
developera5005b62022-09-13 15:43:35 +08002969 *output_ulong = strtol(buf, NULL, 10);
2970
2971 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002972 return RETURN_OK;
2973}
2974
2975//Set Transmit Power
2976//The transmite power level is in units of full power for this radio.
2977INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2978{
developera5005b62022-09-13 15:43:35 +08002979 char *support;
developer06a01d92022-09-07 16:32:39 +08002980 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002981 char buf[128]={0};
2982 char txpower_str[64] = {0};
2983 int txpower = 0;
2984 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08002985 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08002986
2987 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002988
developera5005b62022-09-13 15:43:35 +08002989 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 +08002990 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002991 maximum_tx = strtol(buf, NULL, 10);
2992
2993 // Get the Tx power supported list and check that is the input in the list
2994 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2995 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2996 support = strtok(buf, ",");
2997 while(true)
2998 {
2999 if(support == NULL) { // input not in the list
3000 wifi_dbg_printf("Input value is invalid.\n");
3001 return RETURN_ERR;
3002 }
3003 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3004 break;
3005 }
3006 support = strtok(NULL, ",");
3007 }
3008 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003009 phyId = radio_index_to_phy(radioIndex);
3010 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003011 _syscmd(cmd, buf, sizeof(buf));
3012 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003013
3014 return RETURN_OK;
3015}
3016
3017//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3018INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3019{
3020 if (NULL == Supported)
3021 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003022 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003023
3024 return RETURN_OK;
3025}
3026
3027//Get 80211h feature enable
3028INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3029{
developer3885fec2022-09-13 15:13:47 +08003030 char buf[64]={'\0'};
3031 char config_file[64] = {'\0'};
3032
3033 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3034 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003035 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003036
3037 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3038 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003039
developer3885fec2022-09-13 15:13:47 +08003040 if (strncmp(buf, "1", 1) == 0)
3041 *enable = TRUE;
3042 else
3043 *enable = FALSE;
3044
3045 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003046 return RETURN_OK;
3047}
3048
3049//Set 80211h feature enable
3050INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3051{
developer3885fec2022-09-13 15:13:47 +08003052 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3053 struct params params={'\0'};
3054 char config_file[MAX_BUF_SIZE] = {0};
3055
3056 params.name = "ieee80211h";
3057
3058 if (enable) {
3059 params.value = "1";
3060 } else {
3061 params.value = "0";
3062 }
3063
3064 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3065 wifi_hostapdWrite(config_file, &params, 1);
3066
3067 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3068 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3069 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003070}
3071
3072//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.
3073INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3074{
3075 if (NULL == output)
3076 return RETURN_ERR;
3077 *output=100;
3078
3079 return RETURN_OK;
3080}
3081
3082//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.
3083INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3084{
3085 if (NULL == output)
3086 return RETURN_ERR;
3087 *output = -99;
3088
3089 return RETURN_OK;
3090}
3091
3092INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3093{
3094 return RETURN_ERR;
3095}
3096
3097
3098//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3099INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3100{
developer5f222492022-09-13 15:21:52 +08003101 char cmd[MAX_BUF_SIZE]={'\0'};
3102 char buf[MAX_CMD_SIZE]={'\0'};
3103
3104 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3105 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003106 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003107
3108 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3109 _syscmd(cmd, buf, sizeof(buf));
3110 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003111
developer5f222492022-09-13 15:21:52 +08003112 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003113 return RETURN_OK;
3114}
3115
3116INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3117{
developer5f222492022-09-13 15:21:52 +08003118 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3119 struct params params={'\0'};
3120 char buf[MAX_BUF_SIZE] = {'\0'};
3121 char config_file[MAX_BUF_SIZE] = {'\0'};
3122
developer5b398df2022-11-17 20:39:48 +08003123 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3124 return RETURN_ERR;
3125
developer5f222492022-09-13 15:21:52 +08003126 params.name = "beacon_int";
3127 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3128 params.value = buf;
3129
3130 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3131 wifi_hostapdWrite(config_file, &params, 1);
3132
3133 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3134 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3135 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003136}
3137
3138//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.
3139INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3140{
developer06a01d92022-09-07 16:32:39 +08003141 //TODO: need to revisit below implementation
3142 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003143 char temp_output[128] = {0};
3144 char temp_TransmitRates[64] = {0};
3145 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003146
3147 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3148 if (NULL == output)
3149 return RETURN_ERR;
3150 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003151 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3152
3153 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3154 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3155 } else {
3156 temp = strtok(temp_TransmitRates," ");
3157 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003158 {
developere9d0abd2022-09-13 15:40:57 +08003159 // Convert 100 kbps to Mbps
3160 temp[strlen(temp)-1]=0;
3161 if((temp[0]=='5') && (temp[1]=='\0'))
3162 {
3163 temp="5.5";
3164 }
3165 strcat(temp_output,temp);
3166 temp = strtok(NULL," ");
3167 if(temp!=NULL)
3168 {
3169 strcat(temp_output,",");
3170 }
developer06a01d92022-09-07 16:32:39 +08003171 }
developere9d0abd2022-09-13 15:40:57 +08003172 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003173 }
developer06a01d92022-09-07 16:32:39 +08003174 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003175 return RETURN_OK;
3176}
3177
3178INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3179{
3180 char *temp;
3181 char temp1[128];
3182 char temp_output[128];
3183 char temp_TransmitRates[128];
3184 char set[128];
3185 char sub_set[128];
3186 int set_count=0,subset_count=0;
3187 int set_index=0,subset_index=0;
3188 char *token;
3189 int flag=0, i=0;
3190 struct params params={'\0'};
3191 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003192 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003193
3194 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3195 if(NULL == TransmitRates)
3196 return RETURN_ERR;
3197 strcpy(sub_set,TransmitRates);
3198
3199 //Allow only supported Data transmit rate to be set
3200 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3201 token = strtok(sub_set,",");
3202 while( token != NULL ) /* split the basic rate to be set, by comma */
3203 {
3204 sub_set[subset_count]=atoi(token);
3205 subset_count++;
3206 token=strtok(NULL,",");
3207 }
3208 token=strtok(set,",");
3209 while(token!=NULL) /* split the supported rate by comma */
3210 {
3211 set[set_count]=atoi(token);
3212 set_count++;
3213 token=strtok(NULL,",");
3214 }
3215 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3216 {
3217 for(set_index=0;set_index < set_count;set_index++)
3218 {
3219 flag=0;
3220 if(sub_set[subset_index]==set[set_index])
3221 break;
3222 else
3223 flag=1; /* No match found */
3224 }
3225 if(flag==1)
3226 return RETURN_ERR; //If value not found return Error
3227 }
3228 strcpy(temp_TransmitRates,TransmitRates);
3229
3230 for(i=0;i<strlen(temp_TransmitRates);i++)
3231 {
3232 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003233 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003234 {
3235 continue;
3236 }
3237 else
3238 {
3239 return RETURN_ERR;
3240 }
3241 }
3242 strcpy(temp_output,"");
3243 temp = strtok(temp_TransmitRates,",");
3244 while(temp!=NULL)
3245 {
3246 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003247 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003248 {
developeref938762022-10-19 17:21:01 +08003249 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003250 {
3251 return RETURN_ERR;
3252 }
3253 }
3254
3255 if(strcmp(temp,"5.5")==0)
3256 {
3257 strcpy(temp1,"55");
3258 }
3259 else
3260 {
3261 strcat(temp1,"0");
3262 }
3263 strcat(temp_output,temp1);
3264 temp = strtok(NULL,",");
3265 if(temp!=NULL)
3266 {
3267 strcat(temp_output," ");
3268 }
3269 }
3270 strcpy(TransmitRates,temp_output);
3271
3272 params.name= "basic_rates";
3273 params.value =TransmitRates;
3274
3275 wifi_dbg_printf("\n%s:",__func__);
3276 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3277 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3278 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3279 wifi_hostapdWrite(config_file,&params,1);
3280 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3281 return RETURN_OK;
3282}
3283
3284//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3285INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3286{
3287 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3288 FILE *fp = NULL;
3289 char path[256] = {0}, output_string[256] = {0};
3290 int count = 0;
3291 char *interface = NULL;
3292
3293 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3294 if (fp == NULL)
3295 {
3296 printf("Failed to run command in Function %s\n", __FUNCTION__);
3297 return RETURN_ERR;
3298 }
3299 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3300 {
3301 interface = strchr(path, '=');
3302
3303 if (interface != NULL)
3304 {
3305 strcpy(output_string, interface + 1);
3306 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3307 interface_name[count] = output_string[count];
3308
3309 interface_name[count] = '\0';
3310 }
3311 }
3312 pclose(fp);
3313 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3314 return RETURN_OK;
3315}
3316
3317INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3318{
3319 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3320 output_struct->radio_BytesSent = 0;
3321 output_struct->radio_BytesReceived = 0;
3322 output_struct->radio_PacketsSent = 0;
3323 output_struct->radio_PacketsReceived = 0;
3324 output_struct->radio_ErrorsSent = 0;
3325 output_struct->radio_ErrorsReceived = 0;
3326 output_struct->radio_DiscardPacketsSent = 0;
3327 output_struct->radio_DiscardPacketsReceived = 0;
3328 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3329 return RETURN_OK;
3330}
3331
3332
3333INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3334{
3335 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3336 CHAR buf[MAX_CMD_SIZE] = {0};
3337 CHAR Value[MAX_BUF_SIZE] = {0};
3338 FILE *fp = NULL;
3339
3340 if (ifname == NULL || strlen(ifname) <= 1)
3341 return RETURN_OK;
3342
3343 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3344 system(buf);
3345
3346 fp = fopen("/tmp/Radio_Stats.txt", "r");
3347 if(fp == NULL)
3348 {
3349 printf("/tmp/Radio_Stats.txt not exists \n");
3350 return RETURN_ERR;
3351 }
3352 fclose(fp);
3353
3354 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3355 File_Reading(buf, Value);
3356 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3357
3358 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3359 File_Reading(buf, Value);
3360 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3361
3362 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3363 File_Reading(buf, Value);
3364 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3365
3366 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3367 File_Reading(buf, Value);
3368 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3369
3370 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3371 File_Reading(buf, Value);
3372 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3373
3374 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3375 File_Reading(buf, Value);
3376 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3377
3378 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3379 File_Reading(buf, Value);
3380 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3381
3382 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3383 File_Reading(buf, Value);
3384 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3385
3386 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3387 return RETURN_OK;
3388}
3389
3390INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3391{
3392 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3393 CHAR buf[MAX_CMD_SIZE] = {0};
3394 FILE *fp = NULL;
3395 INT count = 0;
3396
3397 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3398 {
3399 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3400 File_Reading(buf, status);
3401 }
3402 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3403 return RETURN_OK;
3404}
3405
3406//Get detail radio traffic static info
3407INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3408{
3409
3410#if 0
3411 //ifconfig radio_x
3412 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3413 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3414 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3415 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3416
3417 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3418 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3419 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.
3420 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.
3421
3422 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3423 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].
3424 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3425 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.
3426 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
3427 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
3428 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
3429 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
3430 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
3431
3432 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
3433 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
3434 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
3435 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.
3436
3437 return RETURN_OK;
3438#endif
3439
developera91d99f2022-09-29 15:59:10 +08003440 CHAR interface_name[64] = {0};
3441 CHAR config_path[64] = {0};
3442 BOOL iface_status = FALSE;
3443 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003444
3445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3446 if (NULL == output_struct)
3447 return RETURN_ERR;
3448
developera91d99f2022-09-29 15:59:10 +08003449 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3450 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003451
developera91d99f2022-09-29 15:59:10 +08003452 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003453
developera91d99f2022-09-29 15:59:10 +08003454 if (iface_status == TRUE)
3455 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3456 else
3457 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003458
developera91d99f2022-09-29 15:59:10 +08003459 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3460 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3461 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3462 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3463 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3464 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3465 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3466 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003467
3468 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3469 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].
3470 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3471 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.
3472 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
3473 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
3474 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
3475 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
3476 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
3477
3478 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
3479 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
3480 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
3481 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.
3482
3483 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3484
3485 return RETURN_OK;
3486}
3487
3488//Set radio traffic static Measureing rules
3489INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3490{
3491 //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
3492 // Else, save the MeasuringRate and MeasuringInterval for future usage
3493
3494 return RETURN_OK;
3495}
3496
3497//To start or stop RadioTrafficStats
3498INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3499{
3500 //zqiu: If the RadioTrafficStats process running
3501 // if(enable)
3502 // return RETURN_OK.
3503 // else
3504 // Stop RadioTrafficStats process
3505 // Else
3506 // if(enable)
3507 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3508 // else
3509 // return RETURN_OK.
3510
3511 return RETURN_OK;
3512}
3513
3514//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
3515INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3516{
3517 //zqiu: Please ignor signalIndex.
3518 if (NULL == SignalLevel)
3519 return RETURN_ERR;
3520 *SignalLevel=(radioIndex==0)?-19:-19;
3521
3522 return RETURN_OK;
3523}
3524
3525//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3526INT wifi_applyRadioSettings(INT radioIndex)
3527{
3528 return RETURN_OK;
3529}
3530
3531//Get the radio index assocated with this SSID entry
3532INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3533{
developer5b398df2022-11-17 20:39:48 +08003534 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003535 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003536 int max_radio_num = 0;
3537 wifi_getMaxRadioNumber(&max_radio_num);
3538 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003539 return RETURN_OK;
3540}
3541
3542//Device.WiFi.SSID.{i}.Enable
3543//Get SSID enable configuration parameters (not the SSID enable status)
3544INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3545{
3546 if (NULL == output_bool)
3547 return RETURN_ERR;
3548
developer06a01d92022-09-07 16:32:39 +08003549 return wifi_getApEnable(ssidIndex, output_bool);
3550}
3551
3552//Device.WiFi.SSID.{i}.Enable
3553//Set SSID enable configuration parameters
3554INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3555{
developer06a01d92022-09-07 16:32:39 +08003556 return wifi_setApEnable(ssidIndex, enable);
3557}
3558
3559//Device.WiFi.SSID.{i}.Status
3560//Get the SSID enable status
3561INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3562{
3563 char cmd[MAX_CMD_SIZE]={0};
3564 char buf[MAX_BUF_SIZE]={0};
3565 BOOL output_bool;
3566
3567 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3568 if (NULL == output_string)
3569 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003570
developer06a01d92022-09-07 16:32:39 +08003571 wifi_getApEnable(ssidIndex,&output_bool);
3572 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3573
3574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3575 return RETURN_OK;
3576}
3577
3578// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3579INT wifi_getSSIDName(INT apIndex, CHAR *output)
3580{
3581 char config_file[MAX_BUF_SIZE] = {0};
3582
3583 if (NULL == output)
3584 return RETURN_ERR;
3585
3586 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3587 wifi_hostapdRead(config_file,"ssid",output,32);
3588
3589 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3590 return RETURN_OK;
3591}
3592
3593// Set a max 32 byte string and sets an internal variable to the SSID name
3594INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3595{
3596 char str[MAX_BUF_SIZE]={'\0'};
3597 char cmd[MAX_CMD_SIZE]={'\0'};
3598 struct params params;
3599 char config_file[MAX_BUF_SIZE] = {0};
3600
3601 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3602 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3603 return RETURN_ERR;
3604
3605 params.name = "ssid";
3606 params.value = ssid_string;
3607 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3608 wifi_hostapdWrite(config_file, &params, 1);
3609 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3611
3612 return RETURN_OK;
3613}
3614
3615//Get the BSSID
3616INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3617{
3618 char cmd[MAX_CMD_SIZE]="";
3619
3620 if (NULL == output_string)
3621 return RETURN_ERR;
3622
3623 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3624 {
developer1d57d002022-10-12 18:03:15 +08003625 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep bssid | cut -d '=' -f2 | tr -d '\n'", CONFIG_PREFIX, ssidIndex);
developer06a01d92022-09-07 16:32:39 +08003626 _syscmd(cmd, output_string, 64);
3627 return RETURN_OK;
3628 }
3629 strncpy(output_string, "\0", 1);
3630
3631 return RETURN_ERR;
3632}
3633
3634//Get the MAC address associated with this Wifi SSID
3635INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3636{
3637 wifi_getBaseBSSID(ssidIndex,output_string);
3638 return RETURN_OK;
3639}
3640
3641//Get the basic SSID traffic static info
3642//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3643//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3644INT wifi_applySSIDSettings(INT ssidIndex)
3645{
3646 BOOL status = false;
3647 char cmd[MAX_CMD_SIZE] = {0};
3648 char buf[MAX_CMD_SIZE] = {0};
3649 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003650 int max_radio_num = 0;
3651 int radioIndex = 0;
3652
3653 wifi_getMaxRadioNumber(&max_radio_num);
3654
3655 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003656
3657 wifi_getApEnable(ssidIndex,&status);
3658 // Do not apply when ssid index is disabled
3659 if (status == false)
3660 return RETURN_OK;
3661
3662 /* Doing full remove and add for ssid Index
3663 * Not all hostapd options are supported with reload
3664 * for example macaddr_acl
3665 */
3666 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3667 return RETURN_ERR;
3668
3669 ret = wifi_setApEnable(ssidIndex,true);
3670
3671 /* Workaround for hostapd issue with multiple bss definitions
3672 * when first created interface will be removed
3673 * then all vaps other vaps on same phy are removed
3674 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003675 for(int i=0; i < MAX_APS/max_radio_num; i++) {
3676 apIndex = max_radio_num*i+radioIndex;
developer06a01d92022-09-07 16:32:39 +08003677 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3678 _syscmd(cmd, buf, sizeof(buf));
3679 if(*buf == '1')
3680 wifi_setApEnable(apIndex, true);
3681 }
3682
3683 return ret;
3684}
3685
developera3c68b92022-09-13 15:27:29 +08003686struct channels_noise {
3687 int channel;
3688 int noise;
3689};
3690
3691// Return noise array for each channel
3692int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3693{
3694 FILE *f = NULL;
3695 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003696 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003697 size_t len = 0;
3698 ssize_t read = 0;
3699 int tmp = 0, arr_index = -1;
3700
3701 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3702
3703 if ((f = popen(cmd, "r")) == NULL) {
3704 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3705 return RETURN_ERR;
3706 }
developer5550e242022-09-30 09:59:32 +08003707
3708 while(fgets(line, sizeof(line), f) != NULL) {
3709 if(arr_index < channels_num){
3710 sscanf(line, "%d", &tmp);
3711 if (tmp > 0) { // channel frequency, the first line must be frequency
3712 arr_index++;
3713 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3714 } else { // noise
3715 channels_noise_arr[arr_index].noise = tmp;
3716 }
3717 }else{
3718 break;
developera3c68b92022-09-13 15:27:29 +08003719 }
3720 }
developera3c68b92022-09-13 15:27:29 +08003721 pclose(f);
3722 return RETURN_OK;
3723}
3724
developer06a01d92022-09-07 16:32:39 +08003725//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3726//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3727INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3728{
developera3c68b92022-09-13 15:27:29 +08003729 int index = -1;
3730 wifi_neighbor_ap2_t *scan_array = NULL;
3731 char cmd[256]={0};
3732 char buf[128]={0};
3733 char file_name[32] = {0};
3734 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003735 char line[256] = {0};
3736 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003737 int freq=0;
3738 FILE *f = NULL;
3739 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003740 int channels_num = 0;
3741 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003742 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003743 bool filter_enable = false;
3744 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003745 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003746
developer615510b2022-09-27 10:14:35 +08003747 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003748
3749 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3750 f = fopen(file_name, "r");
3751 if (f != NULL) {
3752 fgets(filter_SSID, sizeof(file_name), f);
3753 if (strlen(filter_SSID) != 0)
3754 filter_enable = true;
3755 fclose(f);
3756 }
3757
developer033b37b2022-10-18 11:27:46 +08003758 phyId = radio_index_to_phy(radioIndex);
3759 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003760 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003761 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003762
developer5550e242022-09-30 09:59:32 +08003763
developer06a01d92022-09-07 16:32:39 +08003764
developera3c68b92022-09-13 15:27:29 +08003765 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 +08003766 // 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 +08003767 fprintf(stderr, "cmd: %s\n", cmd);
3768 if ((f = popen(cmd, "r")) == NULL) {
3769 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3770 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003771 }
developer5550e242022-09-30 09:59:32 +08003772
3773 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3774 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3775
developer615510b2022-09-27 10:14:35 +08003776 ret = fgets(line, sizeof(line), f);
3777 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003778 if(strstr(line, "BSS") != NULL) { // new neighbor info
3779 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3780 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3781 // 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 +08003782
developera3c68b92022-09-13 15:27:29 +08003783 if (!filter_BSS) {
3784 index++;
3785 wifi_neighbor_ap2_t *tmp;
3786 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3787 if (tmp == NULL) { // no more memory to use
3788 index--;
3789 wifi_dbg_printf("%s: realloc failed\n", __func__);
3790 break;
3791 }
3792 scan_array = tmp;
3793 }
3794 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3795
3796 filter_BSS = false;
3797 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3798 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3799 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3800 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3801 } else if (strstr(line, "freq") != NULL) {
3802 sscanf(line," freq: %d", &freq);
3803 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3804
3805 if (freq >= 2412 && freq <= 2484) {
3806 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3807 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3808 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3809 }
3810 else if (freq >= 5160 && freq <= 5805) {
3811 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3812 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3813 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3814 }
3815
3816 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003817 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003818 for (int i = 0; i < channels_num; i++) {
3819 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3820 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3821 break;
3822 }
3823 }
3824 }
3825 } else if (strstr(line, "beacon interval") != NULL) {
3826 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3827 } else if (strstr(line, "signal") != NULL) {
3828 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3829 } else if (strstr(line,"SSID") != NULL) {
3830 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3831 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3832 filter_BSS = true;
3833 }
3834 } else if (strstr(line, "Supported rates") != NULL) {
3835 char SRate[80] = {0}, *tmp = NULL;
3836 memset(buf, 0, sizeof(buf));
3837 strcpy(SRate, line);
3838 tmp = strtok(SRate, ":");
3839 tmp = strtok(NULL, ":");
3840 strcpy(buf, tmp);
3841 memset(SRate, 0, sizeof(SRate));
3842
3843 tmp = strtok(buf, " \n");
3844 while (tmp != NULL) {
3845 strcat(SRate, tmp);
3846 if (SRate[strlen(SRate) - 1] == '*') {
3847 SRate[strlen(SRate) - 1] = '\0';
3848 }
3849 strcat(SRate, ",");
3850
3851 tmp = strtok(NULL, " \n");
3852 }
3853 SRate[strlen(SRate) - 1] = '\0';
3854 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3855 } else if (strstr(line, "DTIM") != NULL) {
3856 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3857 } else if (strstr(line, "VHT capabilities") != NULL) {
3858 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3859 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3860 } else if (strstr(line, "HT capabilities") != NULL) {
3861 strcat(scan_array[index].ap_SupportedStandards, ",n");
3862 strcpy(scan_array[index].ap_OperatingStandards, "n");
3863 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003864 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003865 sscanf(line," * channel width: %d", &vht_channel_width);
3866 if(vht_channel_width == 1) {
3867 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3868 } else {
3869 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3870 }
3871 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3872 continue;
3873 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003874 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003875 sscanf(line," * secondary channel offset: %s", &buf);
3876 if (!strcmp(buf, "above")) {
3877 //40Mhz +
3878 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3879 }
3880 else if (!strcmp(buf, "below")) {
3881 //40Mhz -
3882 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3883 } else {
3884 //20Mhz
3885 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3886 }
3887 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3888 continue;
3889 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003890 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3891 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3892 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003893 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3894 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003895 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003896 else
developer615510b2022-09-27 10:14:35 +08003897 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003898 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003899 if (strstr(line, "HE80/5GHz") != NULL) {
3900 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3901 ret = fgets(line, sizeof(line), f);
3902 } else
3903 continue;
developera3c68b92022-09-13 15:27:29 +08003904 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003905 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003906 }
developer615510b2022-09-27 10:14:35 +08003907 continue;
developera3c68b92022-09-13 15:27:29 +08003908 } else if (strstr(line, "WPA") != NULL) {
3909 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3910 } else if (strstr(line, "RSN") != NULL) {
3911 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3912 } else if (strstr(line, "Group cipher") != NULL) {
3913 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3914 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3915 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3916 }
3917 }
developer615510b2022-09-27 10:14:35 +08003918 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003919 }
3920
3921 if (!filter_BSS) {
3922 *output_array_size = index + 1;
3923 } else {
3924 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3925 *output_array_size = index;
3926 }
3927 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003928 pclose(f);
developer5550e242022-09-30 09:59:32 +08003929 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003930 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003931 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003932}
3933
3934//>> Deprecated: used for old RDKB code.
3935INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3936{
3937 INT status = RETURN_ERR;
3938
3939 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3940 output_struct->wifi_PLCPErrorCount = 0;
3941 output_struct->wifi_FCSErrorCount = 0;
3942 output_struct->wifi_InvalidMACCount = 0;
3943 output_struct->wifi_PacketsOtherReceived = 0;
3944 output_struct->wifi_Noise = 0;
3945 status = RETURN_OK;
3946 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3947 return status;
3948}
3949
3950INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3951{
developer30423732022-12-01 16:17:49 +08003952 char cmd[128] = {0};
3953 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08003954 char *pos = NULL;
3955
3956 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3957 if (NULL == output_struct)
3958 return RETURN_ERR;
3959
3960 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3961
3962 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3963 _syscmd(cmd, buf, sizeof(buf));
3964
3965 pos = buf;
3966 if ((pos = strstr(pos, "RX packets:")) == NULL)
3967 return RETURN_ERR;
3968 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3969
3970 if ((pos = strstr(pos, "TX packets:")) == NULL)
3971 return RETURN_ERR;
3972 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3973
3974 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3975 return RETURN_ERR;
3976 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3977
3978 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3979 return RETURN_ERR;
3980 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3981
3982 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3983 _syscmd(cmd, buf, sizeof(buf));
3984 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3985
3986#if 0
3987 //TODO: need to revisit below implementation
3988 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3989 char interface_name[MAX_BUF_SIZE] = {0};
3990 char interface_status[MAX_BUF_SIZE] = {0};
3991 char Value[MAX_BUF_SIZE] = {0};
3992 char buf[MAX_CMD_SIZE] = {0};
3993 char cmd[MAX_CMD_SIZE] = {0};
3994 FILE *fp = NULL;
3995
3996 if (NULL == output_struct) {
3997 return RETURN_ERR;
3998 }
3999
4000 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4001
4002 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4003 {
4004 if(apIndex == 0) //private_wifi for 2.4G
4005 {
4006 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4007 }
4008 else if(apIndex == 1) //private_wifi for 5G
4009 {
4010 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4011 }
4012 else if(apIndex == 4) //public_wifi for 2.4G
4013 {
4014 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4015 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4016 {
4017 return RETURN_ERR;
4018 }
4019 if(buf[0] == '#')//tp-link
4020 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4021 else//tenda
4022 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4023 }
4024 else if(apIndex == 5) //public_wifi for 5G
4025 {
4026 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4027 }
4028
4029 GetIfacestatus(interface_name, interface_status);
4030
4031 if(0 != strcmp(interface_status, "1"))
4032 return RETURN_ERR;
4033
4034 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4035 system(cmd);
4036
4037 fp = fopen("/tmp/SSID_Stats.txt", "r");
4038 if(fp == NULL)
4039 {
4040 printf("/tmp/SSID_Stats.txt not exists \n");
4041 return RETURN_ERR;
4042 }
4043 fclose(fp);
4044
4045 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4046 File_Reading(buf, Value);
4047 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4048
4049 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4050 File_Reading(buf, Value);
4051 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4052
4053 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4054 File_Reading(buf, Value);
4055 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4056
4057 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4058 File_Reading(buf, Value);
4059 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4060
4061 /* There is no specific parameter from caller to associate the value wifi_Associations */
4062 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4063 //_syscmd(cmd, buf, sizeof(buf));
4064 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4065 }
4066#endif
4067 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4068 return RETURN_OK;
4069}
4070
4071INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4072{
4073 char interface_name[MAX_BUF_SIZE] = {0};
4074 char interface_status[MAX_BUF_SIZE] = {0};
4075 char Value[MAX_BUF_SIZE] = {0};
4076 char buf[MAX_CMD_SIZE] = {0};
4077 char cmd[MAX_CMD_SIZE] = {0};
4078 FILE *fp = NULL;
4079
4080 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4081 if (NULL == output_struct)
4082 return RETURN_ERR;
4083
4084 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4085
4086 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4087 {
4088 if(apIndex == 0) //private_wifi for 2.4G
4089 {
4090 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4091 }
4092 else if(apIndex == 1) //private_wifi for 5G
4093 {
4094 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4095 }
4096 else if(apIndex == 4) //public_wifi for 2.4G
4097 {
4098 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4099 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4100 {
4101 return RETURN_ERR;
4102 }
4103 if(buf[0] == '#')
4104 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4105 else
4106 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4107 }
4108 else if(apIndex == 5) //public_wifi for 5G
4109 {
4110 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4111 }
4112
4113 GetIfacestatus(interface_name, interface_status);
4114
4115 if(0 != strcmp(interface_status, "1"))
4116 return RETURN_ERR;
4117
4118 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4119 system(cmd);
4120
4121 fp = fopen("/tmp/SSID_Stats.txt", "r");
4122 if(fp == NULL)
4123 {
4124 printf("/tmp/SSID_Stats.txt not exists \n");
4125 return RETURN_ERR;
4126 }
4127 fclose(fp);
4128
4129 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4130 File_Reading(buf, Value);
4131 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4132
4133 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4134 File_Reading(buf, Value);
4135 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4136
4137 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4138 File_Reading(buf, Value);
4139 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4140
4141 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4142 File_Reading(buf, Value);
4143 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4144 }
4145
4146 output_struct->wifi_UnicastPacketsSent = 0;
4147 output_struct->wifi_UnicastPacketsReceived = 0;
4148 output_struct->wifi_MulticastPacketsSent = 0;
4149 output_struct->wifi_MulticastPacketsReceived = 0;
4150 output_struct->wifi_BroadcastPacketsSent = 0;
4151 output_struct->wifi_BroadcastPacketsRecevied = 0;
4152 output_struct->wifi_UnknownPacketsReceived = 0;
4153
4154 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4155 return RETURN_OK;
4156}
4157
4158INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4159{
4160 INT status = RETURN_ERR;
4161
4162 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4163 //Below values should get updated from hal
4164 output_struct->wifi_RetransCount=0;
4165 output_struct->wifi_FailedRetransCount=0;
4166 output_struct->wifi_RetryCount=0;
4167 output_struct->wifi_MultipleRetryCount=0;
4168 output_struct->wifi_ACKFailureCount=0;
4169 output_struct->wifi_AggregatedPacketCount=0;
4170
4171 status = RETURN_OK;
4172 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4173
4174 return status;
4175}
4176
4177INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4178{
4179 INT status = RETURN_ERR;
4180 UINT index;
4181 wifi_neighbor_ap_t *pt=NULL;
4182
4183 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4184 *output_array_size=2;
4185 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4186 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4187 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4188 strcpy(pt->ap_Radio,"");
4189 strcpy(pt->ap_SSID,"");
4190 strcpy(pt->ap_BSSID,"");
4191 strcpy(pt->ap_Mode,"");
4192 pt->ap_Channel=1;
4193 pt->ap_SignalStrength=0;
4194 strcpy(pt->ap_SecurityModeEnabled,"");
4195 strcpy(pt->ap_EncryptionMode,"");
4196 strcpy(pt->ap_OperatingFrequencyBand,"");
4197 strcpy(pt->ap_SupportedStandards,"");
4198 strcpy(pt->ap_OperatingStandards,"");
4199 strcpy(pt->ap_OperatingChannelBandwidth,"");
4200 pt->ap_BeaconPeriod=1;
4201 pt->ap_Noise=0;
4202 strcpy(pt->ap_BasicDataTransferRates,"");
4203 strcpy(pt->ap_SupportedDataTransferRates,"");
4204 pt->ap_DTIMPeriod=1;
4205 pt->ap_ChannelUtilization = 1;
4206 }
4207
4208 status = RETURN_OK;
4209 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4210
4211 return status;
4212}
4213
4214//----------------- AP HAL -------------------------------
4215
4216//>> Deprecated: used for old RDKB code.
4217INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4218{
4219 if (NULL == output_ulong || NULL == output_struct)
4220 return RETURN_ERR;
4221 *output_ulong = 0;
4222 *output_struct = NULL;
4223 return RETURN_OK;
4224}
4225
4226#ifdef HAL_NETLINK_IMPL
4227static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4228 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4229 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4230 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4231 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4232 char mac_addr[20];
4233 static int count=0;
4234 int rate=0;
4235
4236 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4237
4238 nla_parse(tb,
4239 NL80211_ATTR_MAX,
4240 genlmsg_attrdata(gnlh, 0),
4241 genlmsg_attrlen(gnlh, 0),
4242 NULL);
4243
4244 if(!tb[NL80211_ATTR_STA_INFO]) {
4245 fprintf(stderr, "sta stats missing!\n");
4246 return NL_SKIP;
4247 }
4248
4249
4250 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4251 fprintf(stderr, "failed to parse nested attributes!\n");
4252 return NL_SKIP;
4253 }
4254
4255 //devIndex starts from 1
4256 if( ++count == out->wifi_devIndex )
4257 {
4258 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4259 //Getting the mac addrress
4260 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4261
4262 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4263 fprintf(stderr, "failed to parse nested rate attributes!");
4264 return NL_SKIP;
4265 }
4266
4267 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4268 if(rinfo[NL80211_RATE_INFO_BITRATE])
4269 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4270 out->wifi_devTxRate = rate/10;
4271 }
4272
4273 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4274 fprintf(stderr, "failed to parse nested rate attributes!");
4275 return NL_SKIP;
4276 }
4277
4278 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4279 if(rinfo[NL80211_RATE_INFO_BITRATE])
4280 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4281 out->wifi_devRxRate = rate/10;
4282 }
4283 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4284 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4285
4286 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4287 count = 0; //starts the count for next cycle
4288 return NL_STOP;
4289 }
4290
4291 return NL_SKIP;
4292
4293}
4294#endif
4295
4296INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4297{
4298#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004299 Netlink nl = {0};
4300 char if_name[10] = {0};
developer06a01d92022-09-07 16:32:39 +08004301
developer30423732022-12-01 16:17:49 +08004302 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004303 info.wifi_devIndex = devIndex;
4304
4305 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4306
4307 nl.id = initSock80211(&nl);
4308
4309 if (nl.id < 0) {
4310 fprintf(stderr, "Error initializing netlink \n");
4311 return -1;
4312 }
4313
4314 struct nl_msg* msg = nlmsg_alloc();
4315
4316 if (!msg) {
4317 fprintf(stderr, "Failed to allocate netlink message.\n");
4318 nlfree(&nl);
4319 return -2;
4320 }
4321
4322 genlmsg_put(msg,
4323 NL_AUTO_PORT,
4324 NL_AUTO_SEQ,
4325 nl.id,
4326 0,
4327 NLM_F_DUMP,
4328 NL80211_CMD_GET_STATION,
4329 0);
4330
4331 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4332 nl_send_auto(nl.socket, msg);
4333 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4334 nl_recvmsgs(nl.socket, nl.cb);
4335 nlmsg_free(msg);
4336 nlfree(&nl);
4337
4338 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4339 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4340 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4341 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4342 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4343 return RETURN_OK;
4344#else
4345 //iw utility to retrieve station information
4346#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4347#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4348#define MACFILE "/tmp/wifi_AssoMac.txt"
4349#define TXRATEFILE "/tmp/wifi_txrate.txt"
4350#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4351 FILE *file = NULL;
4352 char if_name[10] = {'\0'};
4353 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004354 char line[256] = {0};
4355 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004356
4357 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4358
4359 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4360 file = popen(pipeCmd, "r");
4361
4362 if(file == NULL)
4363 return RETURN_ERR; //popen failed
4364
4365 fgets(line, sizeof line, file);
4366 device = atoi(line);
4367 pclose(file);
4368
4369 if(device == 0)
4370 return RETURN_ERR; //No devices are connected
4371
4372 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4373 system(pipeCmd);
4374
4375 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4376
4377 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4378
4379 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4380
4381 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4382
4383 //devIndex starts from 1, ++count
4384 if((file = fopen(SIGNALFILE, "r")) != NULL )
4385 {
4386 for(count =0;fgets(line, sizeof line, file) != NULL;)
4387 {
4388 if (++count == devIndex)
4389 {
4390 output_struct->wifi_devSignalStrength = atoi(line);
4391 break;
4392 }
4393 }
4394 fclose(file);
4395 }
4396 else
4397 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4398
4399 if((file = fopen(MACFILE, "r")) != NULL )
4400 {
4401 for(count =0;fgets(line, sizeof line, file) != NULL;)
4402 {
4403 if (++count == devIndex)
4404 {
4405 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]);
4406 break;
4407 }
4408 }
4409 fclose(file);
4410 }
4411 else
4412 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4413
4414 if((file = fopen(TXRATEFILE, "r")) != NULL )
4415 {
4416 for(count =0;fgets(line, sizeof line, file) != NULL;)
4417 {
4418 if (++count == devIndex)
4419 {
4420 output_struct->wifi_devTxRate = atoi(line);
4421 break;
4422 }
4423 }
4424 fclose(file);
4425 }
4426 else
4427 fprintf(stderr,"fopen wifi_txrate.txt failed");
4428
4429 if((file = fopen(RXRATEFILE, "r")) != NULL)
4430 {
4431 for(count =0;fgets(line, sizeof line, file) != NULL;)
4432 {
4433 if (++count == devIndex)
4434 {
4435 output_struct->wifi_devRxRate = atoi(line);
4436 break;
4437 }
4438 }
4439 fclose(file);
4440 }
4441 else
4442 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4443
4444 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4445
4446 return RETURN_OK;
4447#endif
4448}
4449
4450INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4451{
4452 if (NULL == device)
4453 return RETURN_ERR;
4454 return RETURN_OK;
4455}
4456//<<
4457
4458
4459//--------------wifi_ap_hal-----------------------------
4460//enables CTS protection for the radio used by this AP
4461INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4462{
4463 //save config and Apply instantly
4464 return RETURN_ERR;
4465}
4466
4467// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4468INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4469{
developer463d39a2022-09-13 15:32:51 +08004470 char config_file[64] = {'\0'};
4471 char buf[64] = {'\0'};
4472 struct params list;
4473
4474 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4475 list.name = "ht_coex";
4476 snprintf(buf, sizeof(buf), "%d", enable);
4477 list.value = buf;
4478
4479 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4480 wifi_hostapdWrite(config_file, &list, 1);
4481 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4482
4483 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4484
4485 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004486}
4487
4488//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4489INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4490{
developerea4bcce2022-09-13 15:26:13 +08004491 char config_file[MAX_BUF_SIZE] = {'\0'};
4492 char buf[MAX_BUF_SIZE] = {'\0'};
4493 struct params list;
4494
4495 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4496 if (threshold < 256 || threshold > 2346 )
4497 return RETURN_ERR;
4498 list.name = "fragm_threshold";
4499 snprintf(buf, sizeof(buf), "%d", threshold);
4500 list.value = buf;
4501
4502 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4503 wifi_hostapdWrite(config_file, &list, 1);
4504 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004505
developerea4bcce2022-09-13 15:26:13 +08004506 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004507
4508 return RETURN_OK;
4509}
4510
4511// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4512INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4513{
developer51a927d2022-09-13 15:42:22 +08004514 char config_file[64] = {'\0'};
4515 char cmd[128] = {'\0'};
4516 char buf[64] = {'\0'};
4517 char stbc_config[16] = {'\0'};
4518 wifi_band band;
4519 int iterator = 0;
4520 BOOL current_stbc = FALSE;
4521
4522 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4523
4524 band = wifi_index_to_band(radioIndex);
4525 if (band == band_invalid)
4526 return RETURN_ERR;
4527
4528 if (band == band_2_4)
4529 iterator = 1;
4530 else if (band == band_5)
4531 iterator = 2;
4532 else
4533 return RETURN_OK;
4534
4535 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4536
4537 // set ht and vht config
4538 for (int i = 0; i < iterator; i++) {
4539 memset(stbc_config, 0, sizeof(stbc_config));
4540 memset(cmd, 0, sizeof(cmd));
4541 memset(buf, 0, sizeof(buf));
4542 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4543 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4544 _syscmd(cmd, buf, sizeof(buf));
4545 if (strlen(buf) != 0)
4546 current_stbc = TRUE;
4547 if (current_stbc == STBC_Enable)
4548 continue;
4549
4550 if (STBC_Enable == TRUE) {
4551 // Append the STBC flags in capab config
4552 memset(cmd, 0, sizeof(cmd));
4553 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004554 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004555 else
developer6372c2b2022-10-27 17:39:51 +08004556 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004557 _syscmd(cmd, buf, sizeof(buf));
4558 } else if (STBC_Enable == FALSE) {
4559 // Remove the STBC flags and remain other flags in capab
4560 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004561 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004562 _syscmd(cmd, buf, sizeof(buf));
4563 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004564 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004565 _syscmd(cmd, buf, sizeof(buf));
4566 }
4567 }
4568
4569 wifi_reloadAp(radioIndex);
4570
4571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4572 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004573}
4574
4575// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4576INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4577{
developer54e6b9f2022-09-28 14:41:20 +08004578 char AMSDU_file_path[64] = {0};
4579
4580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4581
4582 if(output_bool == NULL)
4583 return RETURN_ERR;
4584
4585 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4586
4587 if (access(AMSDU_file_path, F_OK) == 0)
4588 *output_bool = TRUE;
4589 else
4590 *output_bool = FALSE;
4591
4592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4593 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004594}
4595
4596// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4597INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4598{
developer54e6b9f2022-09-28 14:41:20 +08004599 char cmd[64]={0};
4600 char buf[64]={0};
4601 char AMSDU_file_path[64] = {0};
4602
4603 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4604
4605 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4606 _syscmd(cmd, buf, sizeof(buf));
4607
4608 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4609 memset(cmd, 0, sizeof(cmd));
4610 if (amsduEnable == TRUE)
4611 sprintf(cmd, "touch %s", AMSDU_file_path);
4612 else
4613 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4614 _syscmd(cmd, buf, sizeof(buf));
4615
4616 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4617 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004618}
4619
4620//P2 // outputs the number of Tx streams
4621INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4622{
developer2de97692022-09-26 14:00:03 +08004623 char buf[8] = {0};
4624 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004625 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004626
4627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4628
4629 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4630 _syscmd(cmd, buf, sizeof(buf));
4631
developer033b37b2022-10-18 11:27:46 +08004632 phyId = radio_index_to_phy(radioIndex);
developer2de97692022-09-26 14:00:03 +08004633 // if there is no record, output the max number of spatial streams
4634 if (strlen(buf) == 0) {
developer033b37b2022-10-18 11:27:46 +08004635 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", phyId);
developer2de97692022-09-26 14:00:03 +08004636 _syscmd(cmd, buf, sizeof(buf));
4637 }
4638
4639 *output_int = (INT)strtol(buf, NULL, 10);
4640
4641 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4642
4643 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004644}
4645
4646//P2 // sets the number of Tx streams to an enviornment variable
4647INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4648{
developer2de97692022-09-26 14:00:03 +08004649 char cmd[128] = {0};
4650 char buf[128] = {0};
4651 char chain_mask_file[128] = {0};
4652 FILE *f = NULL;
developer033b37b2022-10-18 11:27:46 +08004653 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004654
4655 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4656
4657 if (numStreams == 0) {
developer30423732022-12-01 16:17:49 +08004658 fprintf(stderr, "The mask did not support 0 (auto).\n");
developer2de97692022-09-26 14:00:03 +08004659 return RETURN_ERR;
4660 }
4661 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004662
4663 phyId = radio_index_to_phy(radioIndex);
4664 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004665 _syscmd(cmd, buf, sizeof(buf));
4666
4667 if (strlen(buf) > 0) {
4668 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4669 return RETURN_ERR;
4670 }
4671 wifi_setRadioEnable(radioIndex, TRUE);
4672
4673 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4674 f = fopen(chain_mask_file, "w");
4675 if (f == NULL) {
4676 fprintf(stderr, "%s: fopen failed.\n", __func__);
4677 return RETURN_ERR;
4678 }
4679 fprintf(f, "%d", numStreams);
4680 fclose(f);
4681 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4682 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004683}
4684
4685//P2 // outputs the number of Rx streams
4686INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4687{
developer2de97692022-09-26 14:00:03 +08004688 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4689 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4690 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004691 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004692 }
4693 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004694 return RETURN_OK;
4695}
4696
4697//P2 // sets the number of Rx streams to an enviornment variable
4698INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4699{
developer2de97692022-09-26 14:00:03 +08004700 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4701 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4702 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4703 return RETURN_ERR;
4704 }
4705 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004706 return RETURN_ERR;
4707}
4708
4709//Get radio RDG enable setting
4710INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4711{
4712 if (NULL == output_bool)
4713 return RETURN_ERR;
4714 *output_bool = TRUE;
4715 return RETURN_OK;
4716}
4717
4718//Get radio RDG enable setting
4719INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4720{
4721 if (NULL == output_bool)
4722 return RETURN_ERR;
4723 *output_bool = TRUE;
4724 return RETURN_OK;
4725}
4726
4727//Set radio RDG enable setting
4728INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4729{
4730 return RETURN_ERR;
4731}
4732
4733//Get radio ADDBA enable setting
4734INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4735{
4736 if (NULL == output_bool)
4737 return RETURN_ERR;
4738 *output_bool = TRUE;
4739 return RETURN_OK;
4740}
4741
4742//Set radio ADDBA enable setting
4743INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4744{
4745 return RETURN_ERR;
4746}
4747
4748//Get radio auto block ack enable setting
4749INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4750{
4751 if (NULL == output_bool)
4752 return RETURN_ERR;
4753 *output_bool = TRUE;
4754 return RETURN_OK;
4755}
4756
4757//Set radio auto block ack enable setting
4758INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4759{
4760 return RETURN_ERR;
4761}
4762
4763//Get radio 11n pure mode enable support
4764INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4765{
4766 if (NULL == output_bool)
4767 return RETURN_ERR;
4768 *output_bool = TRUE;
4769 return RETURN_OK;
4770}
4771
4772//Get radio 11n pure mode enable setting
4773INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4774{
4775 if (NULL == output_bool)
4776 return RETURN_ERR;
4777 *output_bool = TRUE;
4778 return RETURN_OK;
4779}
4780
4781//Set radio 11n pure mode enable setting
4782INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4783{
4784 return RETURN_ERR;
4785}
4786
4787//Get radio IGMP snooping enable setting
4788INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4789{
developer81bf2ed2022-09-13 15:31:14 +08004790 char cmd[128]={0};
4791 char buf[4]={0};
4792 bool bridge = FALSE, mac80211 = FALSE;
4793 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4794
4795 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004796 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004797
4798 *output_bool = FALSE;
4799
4800 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4801 _syscmd(cmd, buf, sizeof(buf));
4802 if (strncmp(buf, "1", 1) == 0)
4803 bridge = TRUE;
4804
4805 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4806 _syscmd(cmd, buf, sizeof(buf));
4807 if (strncmp(buf, "1", 1) == 0)
4808 mac80211 = TRUE;
4809
4810 if (bridge && mac80211)
4811 *output_bool = TRUE;
4812
4813 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004814 return RETURN_OK;
4815}
4816
4817//Set radio IGMP snooping enable setting
4818INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4819{
developer81bf2ed2022-09-13 15:31:14 +08004820 char cmd[128]={0};
4821 char buf[4]={0};
developer804c64f2022-10-19 13:54:40 +08004822 int max_num_radios =0;
developer81bf2ed2022-09-13 15:31:14 +08004823 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4824
4825 // bridge
4826 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4827 _syscmd(cmd, buf, sizeof(buf));
4828
developer804c64f2022-10-19 13:54:40 +08004829 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08004830 // mac80211
developer804c64f2022-10-19 13:54:40 +08004831 for (int i = 0; i < max_num_radios; i++) {
developer81bf2ed2022-09-13 15:31:14 +08004832 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4833 _syscmd(cmd, buf, sizeof(buf));
4834 }
4835 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4836 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004837}
4838
4839//Get the Reset count of radio
4840INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4841{
4842 if (NULL == output_int)
4843 return RETURN_ERR;
4844 *output_int = (radioIndex==0)? 1: 3;
4845
4846 return RETURN_OK;
4847}
4848
4849
4850//---------------------------------------------------------------------------------------------------
4851//
4852// Additional Wifi AP level APIs used for Access Point devices
4853//
4854//---------------------------------------------------------------------------------------------------
4855
4856// creates a new ap and pushes these parameters to the hardware
4857INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4858{
4859 char buf[1024];
4860 char cmd[128];
developer033b37b2022-10-18 11:27:46 +08004861 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004862
4863 if (NULL == essid)
4864 return RETURN_ERR;
4865
developer033b37b2022-10-18 11:27:46 +08004866 phyId = radio_index_to_phy(radioIndex);
4867 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08004868 _syscmd(cmd, buf, sizeof(buf));
4869
4870 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4871 _syscmd(cmd, buf, sizeof(buf));
4872
4873 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4874
4875 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4876 _syscmd(cmd, buf, sizeof(buf));
4877
4878 return RETURN_OK;
4879}
4880
4881// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4882INT wifi_deleteAp(INT apIndex)
4883{
4884 char buf[1024];
4885 char cmd[128];
4886
4887 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4888 _syscmd(cmd, buf, sizeof(buf));
4889
4890 wifi_removeApSecVaribles(apIndex);
4891
4892 return RETURN_OK;
4893}
4894
4895// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4896INT wifi_getApName(INT apIndex, CHAR *output_string)
4897{
4898 if(NULL == output_string)
4899 return RETURN_ERR;
4900
4901 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4902 return RETURN_OK;
4903}
4904
4905// Outputs the index number in that corresponds to the SSID string
4906INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4907{
4908 CHAR *pos = NULL;
4909
4910 *output_int = -1;
4911 pos = strstr(inputSsidString, AP_PREFIX);
4912 if(pos)
4913 {
4914 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4915 return RETURN_OK;
4916 }
4917 return RETURN_ERR;
4918}
4919
4920INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4921{
4922 return wifi_getIndexFromName(inputSsidString, output_int);
4923}
4924
4925// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4926INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4927{
4928 char buf[MAX_BUF_SIZE] = {0};
4929 char cmd[MAX_CMD_SIZE] = {0};
4930 char config_file[MAX_BUF_SIZE] = {0};
4931
4932 if(NULL == output_string)
4933 return RETURN_ERR;
4934
4935 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4936 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4937 if((strcmp(buf,"3")==0))
4938 snprintf(output_string, 32, "WPAand11i");
4939 else if((strcmp(buf,"2")==0))
4940 snprintf(output_string, 32, "11i");
4941 else if((strcmp(buf,"1")==0))
4942 snprintf(output_string, 32, "WPA");
4943 else
4944 snprintf(output_string, 32, "None");
4945
4946 return RETURN_OK;
4947}
4948
4949// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4950INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4951{
4952 char config_file[MAX_BUF_SIZE] = {0};
4953 struct params list;
4954
4955 if (NULL == beaconTypeString)
4956 return RETURN_ERR;
4957 list.name = "wpa";
4958 list.value = "0";
4959
4960 if((strcmp(beaconTypeString,"WPAand11i")==0))
4961 list.value="3";
4962 else if((strcmp(beaconTypeString,"11i")==0))
4963 list.value="2";
4964 else if((strcmp(beaconTypeString,"WPA")==0))
4965 list.value="1";
4966
4967 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4968 wifi_hostapdWrite(config_file, &list, 1);
4969 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4970 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4971 return RETURN_OK;
4972}
4973
4974// sets the beacon interval on the hardware for this AP
4975INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4976{
developer5f222492022-09-13 15:21:52 +08004977 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4978 struct params params={'\0'};
4979 char buf[MAX_BUF_SIZE] = {'\0'};
4980 char config_file[MAX_BUF_SIZE] = {'\0'};
4981
4982 params.name = "beacon_int";
4983 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4984 params.value = buf;
4985
4986 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4987 wifi_hostapdWrite(config_file, &params, 1);
4988
4989 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4990 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4991 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004992}
4993
4994INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4995{
developer5b398df2022-11-17 20:39:48 +08004996 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
4997 return RETURN_ERR;
4998 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004999}
5000
5001// Get the packet size threshold supported.
5002INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5003{
5004 //save config and apply instantly
5005 if (NULL == output_bool)
5006 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005007 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005008 return RETURN_OK;
5009}
5010
5011// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5012INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5013{
developer514406b2022-12-05 17:20:21 +08005014 char buf[16] = {0};
5015 char config_file[128] = {0};
5016 struct params param = {0};
5017
5018 if (threshold > 65535) {
5019 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5020 return RETURN_ERR;
5021 }
developer06a01d92022-09-07 16:32:39 +08005022
developer514406b2022-12-05 17:20:21 +08005023 snprintf(config_file, sizeof(config_file), "%s%d.conf", AP_PREFIX, apIndex);
5024 snprintf(buf, sizeof(buf), "%u", threshold);
5025 param.name = "rts_threshold";
5026 param.value = buf;
5027 wifi_hostapdWrite(config_file, &param, 1);
5028 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5029 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005030
5031 return RETURN_OK;
5032}
5033
5034// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5035INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5036{
5037 if (NULL == output_string)
5038 return RETURN_ERR;
5039 snprintf(output_string, 32, "TKIPandAESEncryption");
5040 return RETURN_OK;
5041
5042}
5043
5044// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5045INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5046{
5047 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005048 char *param_name = NULL;
5049 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005050
5051 if(NULL == output_string)
5052 return RETURN_ERR;
5053
5054 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5055 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5056
5057 if(strcmp(buf,"0")==0)
5058 {
5059 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5060 snprintf(output_string, 32, "None");
5061 return RETURN_OK;
5062 }
5063 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5064 param_name = "rsn_pairwise";
5065 else if((strcmp(buf,"1")==0))
5066 param_name = "wpa_pairwise";
5067 else
5068 return RETURN_ERR;
5069 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005070 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005071 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5072 param_name = "wpa_pairwise";
5073 memset(output_string, '\0', 32);
5074 wifi_hostapdRead(config_file, param_name, output_string, 32);
5075 }
developer06a01d92022-09-07 16:32:39 +08005076 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5077
5078 if(strcmp(output_string,"TKIP") == 0)
5079 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5080 else if(strcmp(output_string,"CCMP") == 0)
5081 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5082 else if(strcmp(output_string,"TKIP CCMP") == 0)
5083 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5084
5085 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5086 return RETURN_OK;
5087}
5088
5089// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5090INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5091{
5092 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5093 struct params params={'\0'};
5094 char output_string[32];
5095 char config_file[MAX_BUF_SIZE] = {0};
5096
5097 memset(output_string,'\0',32);
5098 wifi_getApWpaEncryptionMode(apIndex,output_string);
5099
5100 if(strcmp(encMode, "TKIPEncryption") == 0)
5101 params.value = "TKIP";
5102 else if(strcmp(encMode,"AESEncryption") == 0)
5103 params.value = "CCMP";
5104 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5105 params.value = "TKIP CCMP";
5106
5107 if((strcmp(output_string,"WPAand11i")==0))
5108 {
5109 params.name = "wpa_pairwise";
5110 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5111 wifi_hostapdWrite(config_file, &params, 1);
5112 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5113
developer30423732022-12-01 16:17:49 +08005114 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005115 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5116 wifi_hostapdWrite(config_file, &params, 1);
5117 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5118
5119 return RETURN_OK;
5120 }
5121 else if((strcmp(output_string,"11i")==0))
5122 {
5123 params.name = "rsn_pairwise";
5124 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5125 wifi_hostapdWrite(config_file, &params, 1);
5126 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5127 return RETURN_OK;
5128 }
5129 else if((strcmp(output_string,"WPA")==0))
5130 {
5131 params.name = "wpa_pairwise";
5132 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5133 wifi_hostapdWrite(config_file, &params, 1);
5134 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5135 return RETURN_OK;
5136 }
5137
5138 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5139 return RETURN_OK;
5140}
5141
5142// deletes internal security varable settings for this ap
5143INT wifi_removeApSecVaribles(INT apIndex)
5144{
5145 //TODO: remove the entry in hostapd config file
5146 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5147 //_syscmd(cmd, buf, sizeof(buf));
5148
5149 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5150 //_syscmd(cmd, buf, sizeof(buf));
5151 return RETURN_ERR;
5152}
5153
5154// changes the hardware settings to disable encryption on this ap
5155INT wifi_disableApEncryption(INT apIndex)
5156{
5157 //Apply instantly
5158 return RETURN_ERR;
5159}
5160
5161// set the authorization mode on this ap
5162// mode mapping as: 1: open, 2: shared, 4:auto
5163INT wifi_setApAuthMode(INT apIndex, INT mode)
5164{
developeraf95c502022-09-13 16:18:22 +08005165 struct params params={0};
5166 char config_file[64] = {0};
5167 int ret;
5168
5169 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5170
5171 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5172 params.name = "auth_algs";
5173
5174 if (mode & 1 && mode & 2)
5175 params.value = "3";
5176 else if (mode & 2)
5177 params.value = "2";
5178 else if (mode & 1)
5179 params.value = "1";
5180 else
5181 params.value = "0";
5182
5183 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5184 wifi_hostapdWrite(config_file, &params, 1);
5185 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5186 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5187
5188 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005189}
5190
5191// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5192INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5193{
5194 //save to wifi config, and wait for wifi restart to apply
5195 struct params params={'\0'};
5196 char config_file[MAX_BUF_SIZE] = {0};
5197 int ret;
5198
5199 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5200 if(authMode == NULL)
5201 return RETURN_ERR;
5202
5203 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5204 params.name = "wpa_key_mgmt";
5205
5206 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5207 params.value = "WPA-PSK";
5208 else if(strcmp(authMode,"EAPAuthentication") == 0)
5209 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005210 else if (strcmp(authMode, "SAEAuthentication") == 0)
5211 params.value = "SAE";
5212 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5213 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005214 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5215 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005216 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5217 return RETURN_OK; //This is taken careof in beaconType
5218
5219 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5220 ret=wifi_hostapdWrite(config_file,&params,1);
5221 if(!ret)
5222 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5223 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5224
5225 return ret;
5226}
5227
5228// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5229INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5230{
5231 //save to wifi config, and wait for wifi restart to apply
5232 char BeaconType[50] = {0};
5233 char config_file[MAX_BUF_SIZE] = {0};
5234
5235 *authMode = 0;
5236 wifi_getApBeaconType(apIndex,BeaconType);
5237 printf("%s____%s \n",__FUNCTION__,BeaconType);
5238
5239 if(strcmp(BeaconType,"None") == 0)
5240 strcpy(authMode,"None");
5241 else
5242 {
5243 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5244 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5245 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5246 if(strcmp(authMode,"WPA-PSK") == 0)
5247 strcpy(authMode,"SharedAuthentication");
5248 else if(strcmp(authMode,"WPA-EAP") == 0)
5249 strcpy(authMode,"EAPAuthentication");
5250 }
5251
5252 return RETURN_OK;
5253}
5254
5255// Outputs the number of stations associated per AP
5256INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5257{
5258 char cmd[128]={0};
5259 char buf[128]={0};
5260 BOOL status = false;
5261
5262 if(apIndex > MAX_APS)
5263 return RETURN_ERR;
5264
5265 wifi_getApEnable(apIndex,&status);
5266 if (!status)
5267 return RETURN_OK;
5268
5269 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5270 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5271 _syscmd(cmd, buf, sizeof(buf));
5272 sscanf(buf,"%lu", output_ulong);
5273
5274 return RETURN_OK;
5275}
5276
5277// manually removes any active wi-fi association with the device specified on this ap
5278INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5279{
5280 char buf[126]={'\0'};
5281
5282 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5283 system(buf);
5284
5285 return RETURN_OK;
5286}
5287
5288// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5289INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5290{
5291 if(NULL == output_int)
5292 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005293 int max_radio_num = 0;
5294 wifi_getMaxRadioNumber(&max_radio_num);
5295 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005296 return RETURN_OK;
5297}
5298
5299// sets the radio index for the specific ap
5300INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5301{
5302 //set to config only and wait for wifi reset to apply settings
5303 return RETURN_ERR;
5304}
5305
5306// Get the ACL MAC list per AP
5307INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5308{
5309 char cmd[MAX_CMD_SIZE]={'\0'};
5310 int ret = 0;
5311
5312 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5313 ret = _syscmd(cmd,macArray,buf_size);
5314 if (ret != 0)
5315 return RETURN_ERR;
5316
5317 return RETURN_OK;
5318}
5319
developere6aafda2022-09-13 14:59:28 +08005320INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5321{
5322 char cmd[MAX_CMD_SIZE]={'\0'};
5323 int ret = 0;
5324
5325 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5326 ret = _syscmd(cmd,macArray,buf_size);
5327 if (ret != 0)
5328 return RETURN_ERR;
5329
5330 return RETURN_OK;
5331}
5332
5333
developer06a01d92022-09-07 16:32:39 +08005334// Get the list of stations associated per AP
5335INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5336{
5337 char cmd[128];
5338
5339 if(apIndex > 3) //Currently supporting apIndex upto 3
5340 return RETURN_ERR;
5341 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5342 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5343 _syscmd(cmd, macArray, buf_size);
5344
5345 return RETURN_OK;
5346}
5347
5348// adds the mac address to the filter list
5349//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5350INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5351{
5352 char cmd[MAX_CMD_SIZE]={'\0'};
5353 char buf[MAX_BUF_SIZE]={'\0'};
5354
5355#if 0
5356 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5357 if(_syscmd(cmd,buf,sizeof(buf)))
5358 return RETURN_ERR;
5359#endif
5360 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5361 if(_syscmd(cmd,buf,sizeof(buf)))
5362 return RETURN_ERR;
5363
5364 return RETURN_OK;
5365}
5366
5367// deletes the mac address from the filter list
5368//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5369INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5370{
5371 char cmd[MAX_CMD_SIZE]={'\0'};
5372 char buf[MAX_BUF_SIZE]={'\0'};
5373
5374#if 0
5375 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5376 if(_syscmd(cmd,buf,sizeof(buf)))
5377 return RETURN_ERR;
5378
5379#endif
5380 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5381 if(_syscmd(cmd,buf,sizeof(buf)))
5382 return RETURN_ERR;
5383
5384 return RETURN_OK;
5385}
5386
5387// outputs the number of devices in the filter list
5388INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5389{
developere6aafda2022-09-13 14:59:28 +08005390 char cmd[MAX_BUF_SIZE]={0};
5391 char buf[MAX_CMD_SIZE]={0};
5392
5393 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5394 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005395 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005396
5397 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5398 _syscmd(cmd, buf, sizeof(buf));
5399
5400 *output_uint = atoi(buf);
5401
5402 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5403 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005404}
5405
5406INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5407{
5408 char cmd[128]={'\0'};
5409 char buf[128]={'\0'};
5410
5411 if(strcmp(action,"DENY")==0)
5412 {
5413 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5414 system(buf);
5415 return RETURN_OK;
5416 }
5417
5418 if(strcmp(action,"ALLOW")==0)
5419 {
5420 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5421 system(buf);
5422 return RETURN_OK;
5423 }
5424
5425 return RETURN_ERR;
5426
5427}
5428
5429// enable kick for devices on acl black list
5430INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5431{
5432 char aclArray[512] = {0}, *acl = NULL;
5433 char assocArray[512] = {0}, *asso = NULL;
5434
developere6aafda2022-09-13 14:59:28 +08005435 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005436 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5437
5438 // if there are no devices connected there is nothing to do
5439 if (strlen(assocArray) < 17)
5440 return RETURN_OK;
5441
5442 if (enable == TRUE)
5443 {
5444 //kick off the MAC which is in ACL array (deny list)
5445 acl = strtok(aclArray, "\r\n");
5446 while (acl != NULL) {
5447 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5448 wifi_kickApAssociatedDevice(apIndex, acl);
5449
5450 acl = strtok(NULL, "\r\n");
5451 }
developere6aafda2022-09-13 14:59:28 +08005452 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005453 }
5454 else
5455 {
developere6aafda2022-09-13 14:59:28 +08005456 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005457 }
5458
5459#if 0
5460 //TODO: need to revisit below implementation
5461 char aclArray[512]={0}, *acl=NULL;
5462 char assocArray[512]={0}, *asso=NULL;
5463 char buf[256]={'\0'};
5464 char action[10]={'\0'};
5465 FILE *fr=NULL;
5466 char interface[10]={'\0'};
5467 char config_file[MAX_BUF_SIZE] = {0};
5468
5469 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5470 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5471 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5472 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5473
5474 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5475 system(buf);
5476 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5477 system(buf);
5478 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5479 system(buf);
5480 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5481 system(buf);
5482 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5483 system(buf);
5484
5485 if ( enable == TRUE )
5486 {
5487 int device_count=0;
5488 strcpy(action,"DENY");
5489 //kick off the MAC which is in ACL array (deny list)
5490 acl = strtok (aclArray,",");
5491 while (acl != NULL) {
5492 if(strlen(acl)>=17)
5493 {
5494 apply_rules(apIndex, acl,action,interface);
5495 device_count++;
5496 //Register mac to be blocked ,in syscfg.db persistent storage
5497 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5498 system(buf);
5499 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5500 system(buf);
5501 system("syscfg commit");
5502
5503 wifi_kickApAssociatedDevice(apIndex, acl);
5504 }
5505 acl = strtok (NULL, ",");
5506 }
5507 }
5508 else
5509 {
5510 int device_count=0;
5511 char cmdmac[20]={'\0'};
5512 strcpy(action,"ALLOW");
5513 //kick off the MAC which is not in ACL array (allow list)
5514 acl = strtok (aclArray,",");
5515 while (acl != NULL) {
5516 if(strlen(acl)>=17)
5517 {
5518 apply_rules(apIndex, acl,action,interface);
5519 device_count++;
5520 //Register mac to be Allowed ,in syscfg.db persistent storage
5521 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5522 system(buf);
5523 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5524 system(buf);
5525 sprintf(cmdmac,"%s",acl);
5526 }
5527 acl = strtok (NULL, ",");
5528 }
5529 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5530 system(buf);
5531
5532 //Disconnect the mac which is not in ACL
5533 asso = strtok (assocArray,",");
5534 while (asso != NULL) {
5535 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5536 wifi_kickApAssociatedDevice(apIndex, asso);
5537 asso = strtok (NULL, ",");
5538 }
5539 }
5540#endif
5541 return RETURN_OK;
5542}
5543
5544INT wifi_setPreferPrivateConnection(BOOL enable)
5545{
5546 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5547 char buf[1024] = {0};
5548
5549 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5550 if(enable == TRUE)
5551 {
5552 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5553 sprintf(buf,"ifconfig %s down" ,interface_name);
5554 system(buf);
5555 memset(buf,0,sizeof(buf));
5556 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5557 sprintf(buf,"ifconfig %s down" ,interface_name);
5558 system(buf);
5559 }
5560 else
5561 {
5562 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5563 if(strcmp(ssid_cur_value,"1") == 0)
5564 wifi_RestartPrivateWifi_5G();
5565 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5566 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5567 if(strcmp(ssid_cur_value,"1") == 0)
5568 wifi_RestartHostapd_2G();
5569 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5570 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5571 if(strcmp(ssid_cur_value,"1") == 0)
5572 wifi_RestartHostapd_5G();
5573 }
5574 return RETURN_OK;
5575}
5576
5577// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5578INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5579{
5580 int items = 1;
5581 struct params list[2];
5582 char buf[MAX_BUF_SIZE] = {0};
5583 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005584 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005585
5586 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005587
developer10adcc12022-09-13 14:39:17 +08005588 if (filterMode == 0) {
5589 sprintf(buf, "%d", 0);
5590 list[0].value = buf;
5591
5592 char cmd[128], rtn[128];
5593 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5594 _syscmd(cmd, rtn, sizeof(rtn));
5595 memset(cmd,0,sizeof(cmd));
5596 // Delete deny_mac_file in hostapd configuration
5597 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5598 _syscmd(cmd, rtn, sizeof(rtn));
5599 }
5600 else if (filterMode == 1) {
5601 sprintf(buf, "%d", filterMode);
5602 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005603 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5604 list[1].name = "accept_mac_file";
5605 list[1].value = acl_file;
5606 items = 2;
developer10adcc12022-09-13 14:39:17 +08005607 } else if (filterMode == 2) {
5608 //TODO: deny_mac_file
5609 sprintf(buf, "%d", 0);
5610 list[0].value = buf;
5611 list[1].name = "deny_mac_file";
5612 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5613 list[1].value = deny_file;
5614 items = 2;
5615 } else {
5616 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005617 }
developer10adcc12022-09-13 14:39:17 +08005618
developer06a01d92022-09-07 16:32:39 +08005619 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5620 wifi_hostapdWrite(config_file, list, items);
5621
5622 return RETURN_OK;
5623
5624#if 0
5625 if(apIndex==0 || apIndex==1)
5626 {
5627 //set the filtermode
5628 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5629 system(buf);
5630 system("syscfg commit");
5631
5632 if(filterMode==0)
5633 {
5634 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5635 system(buf);
5636 return RETURN_OK;
5637 }
5638 }
5639 return RETURN_OK;
5640#endif
5641}
5642
5643// 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.
5644INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5645{
5646 return RETURN_ERR;
5647}
5648
5649// gets the vlan ID for this ap from an internal enviornment variable
5650INT wifi_getApVlanID(INT apIndex, INT *output_int)
5651{
developer30423732022-12-01 16:17:49 +08005652 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08005653 {
5654 *output_int=100;
5655 return RETURN_OK;
5656 }
5657
5658 return RETURN_ERR;
5659}
5660
5661// sets the vlan ID for this ap to an internal enviornment variable
5662INT wifi_setApVlanID(INT apIndex, INT vlanId)
5663{
5664 //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)
5665 return RETURN_ERR;
5666}
5667
5668// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5669INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5670{
5671 snprintf(bridgeName, 32, "brlan0");
5672 snprintf(IP, 32, "10.0.0.1");
5673 snprintf(subnet, 32, "255.255.255.0");
5674
5675 return RETURN_OK;
5676}
5677
5678//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5679INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5680{
5681 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5682 return RETURN_ERR;
5683}
5684
5685// reset the vlan configuration for this ap
5686INT wifi_resetApVlanCfg(INT apIndex)
5687{
developerf5fef612022-09-20 19:38:26 +08005688 char original_config_file[64] = {0};
5689 char current_config_file[64] = {0};
5690 char buf[64] = {0};
5691 char cmd[64] = {0};
5692 char vlan_file[64] = {0};
5693 char vlan_tagged_interface[16] = {0};
5694 char vlan_bridge[16] = {0};
5695 char vlan_naming[16] = {0};
5696 struct params list[4] = {0};
5697 wifi_band band;
5698
5699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5700
5701 band = wifi_index_to_band(apIndex);
5702 if (band == band_2_4)
5703 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08005704 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08005705 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08005706 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08005707 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5708
5709 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5710
5711 if (strlen(vlan_file) == 0)
5712 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005713
developerf5fef612022-09-20 19:38:26 +08005714 // The file should exist or this vap would not work.
5715 if (access(vlan_file, F_OK) != 0) {
5716 sprintf(cmd, "touch %s", vlan_file);
5717 _syscmd(cmd, buf, sizeof(buf));
5718 }
5719 list[0].name = "vlan_file";
5720 list[0].value = vlan_file;
5721
5722 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5723 list[1].name = "vlan_tagged_interface";
5724 list[1].value = vlan_tagged_interface;
5725
5726 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5727 list[2].name = "vlan_bridge";
5728 list[2].value = vlan_bridge;
5729
5730 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5731 list[3].name = "vlan_naming";
5732 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005733
developerf5fef612022-09-20 19:38:26 +08005734 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5735 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005736 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005737 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005738
developerf5fef612022-09-20 19:38:26 +08005739 // restart this ap
5740 wifi_setApEnable(apIndex, FALSE);
5741 wifi_setApEnable(apIndex, TRUE);
5742
5743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5744
5745 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005746}
5747
5748// 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.
5749INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5750{
5751 return RETURN_ERR;
5752}
5753
5754// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5755INT wifi_startHostApd()
5756{
5757 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5758 system("systemctl start hostapd.service");
5759 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5760 return RETURN_OK;
5761 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5762}
5763
5764// stops hostapd
5765INT wifi_stopHostApd()
5766{
5767 char cmd[128] = {0};
5768 char buf[128] = {0};
5769
5770 sprintf(cmd,"systemctl stop hostapd");
5771 _syscmd(cmd, buf, sizeof(buf));
5772
5773 return RETURN_OK;
5774}
5775
5776// restart hostapd dummy function
5777INT wifi_restartHostApd()
5778{
5779 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5780 system("systemctl restart hostapd-global");
5781 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5782
5783 return RETURN_OK;
5784}
5785
5786static int align_hostapd_config(int index)
5787{
5788 ULONG lval;
5789 wifi_getRadioChannel(index%2, &lval);
5790 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08005791 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005792}
5793
5794// sets the AP enable status variable for the specified ap.
5795INT wifi_setApEnable(INT apIndex, BOOL enable)
5796{
5797 char config_file[MAX_BUF_SIZE] = {0};
5798 char cmd[MAX_CMD_SIZE] = {0};
5799 char buf[MAX_BUF_SIZE] = {0};
5800 BOOL status;
developer033b37b2022-10-18 11:27:46 +08005801 int max_radio_num = 0;
5802 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08005803
5804 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08005805
5806 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08005807 if (enable == status)
5808 return RETURN_OK;
5809
5810 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08005811 int radioIndex = apIndex % max_radio_num;
5812 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08005813 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5814 //Hostapd will bring up this interface
5815 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5816 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +08005817 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08005818 _syscmd(cmd, buf, sizeof(buf));
5819 }
5820 else {
5821 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5822 _syscmd(cmd, buf, sizeof(buf));
5823 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5824 _syscmd(cmd, buf, sizeof(buf));
5825 }
5826 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5827 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5828 _syscmd(cmd, buf, sizeof(buf));
5829 //Wait for wifi up/down to apply
5830 return RETURN_OK;
5831}
5832
5833// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5834INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5835{
5836 char cmd[MAX_CMD_SIZE] = {'\0'};
5837 char buf[MAX_BUF_SIZE] = {'\0'};
5838
5839 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5840 return RETURN_ERR;
5841
5842 *output_bool = 0;
5843
5844 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5845 {
developer70490032022-09-13 15:45:20 +08005846 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005847 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5848 }
5849
5850 return RETURN_OK;
5851}
5852
5853// Outputs the AP "Enabled" "Disabled" status from driver
5854INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5855{
5856 char cmd[128] = {0};
5857 char buf[128] = {0};
5858 BOOL output_bool;
5859
5860 if ( NULL == output_string)
5861 return RETURN_ERR;
5862 wifi_getApEnable(apIndex,&output_bool);
5863
5864 if(output_bool == 1)
5865 snprintf(output_string, 32, "Up");
5866 else
5867 snprintf(output_string, 32, "Disable");
5868
5869 return RETURN_OK;
5870}
5871
5872//Indicates whether or not beacons include the SSID name.
5873// outputs a 1 if SSID on the AP is enabled, else outputs 0
5874INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5875{
5876 //get the running status
5877 char config_file[MAX_BUF_SIZE] = {0};
5878 char buf[16] = {0};
5879
5880 if (!output)
5881 return RETURN_ERR;
5882
5883 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5884 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005885 // default is enable
5886 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
5887 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08005888
5889 return RETURN_OK;
5890}
5891
5892// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5893INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5894{
5895 //store the config, apply instantly
5896 char config_file[MAX_BUF_SIZE] = {0};
5897 struct params list;
5898
5899 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5900 list.name = "ignore_broadcast_ssid";
5901 list.value = enable?"0":"1";
5902
5903 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5904 wifi_hostapdWrite(config_file, &list, 1);
5905 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5906 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005907 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005908 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5909
5910 return RETURN_OK;
5911}
5912
5913//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5914INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5915{
5916 //get the running status
5917 if(!output_uint)
5918 return RETURN_ERR;
5919 *output_uint=16;
5920 return RETURN_OK;
5921}
5922
5923INT wifi_setApRetryLimit(INT apIndex, UINT number)
5924{
5925 //apply instantly
5926 return RETURN_ERR;
5927}
5928
5929//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5930INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5931{
5932 if(!output)
5933 return RETURN_ERR;
5934 *output=TRUE;
5935 return RETURN_OK;
5936}
5937
5938//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5939INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5940{
5941 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005942 char cmd[128] = {0};
5943 char buf[128] = {0};
5944 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08005945 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08005946
developer0b246d12022-09-30 15:24:20 +08005947 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005948
developer0b246d12022-09-30 15:24:20 +08005949 wifi_getMaxRadioNumber(&max_radio_num);
5950 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08005951 phyId = radio_index_to_phy(radioIndex);
5952 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08005953 _syscmd(cmd,buf, sizeof(buf));
5954
5955 if (strlen(buf) > 0)
5956 *output = true;
5957
5958 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005959
developer06a01d92022-09-07 16:32:39 +08005960 return RETURN_OK;
5961}
5962
5963//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5964INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5965{
5966 //get the running status from driver
5967 if(!output)
5968 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005969
5970 char config_file[MAX_BUF_SIZE] = {0};
5971 char buf[16] = {0};
5972
5973 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5974 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005975 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08005976 *output = TRUE;
5977 else
5978 *output = FALSE;
5979
developer06a01d92022-09-07 16:32:39 +08005980 return RETURN_OK;
5981}
5982
5983// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5984INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5985{
5986 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005987 char config_file[MAX_BUF_SIZE] = {0};
5988 struct params list;
5989
5990 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5991 list.name = "wmm_enabled";
5992 list.value = enable?"1":"0";
5993
5994 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5995 wifi_hostapdWrite(config_file, &list, 1);
5996 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5997 wifi_reloadAp(apIndex);
5998 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5999
6000 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006001}
6002
6003//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.
6004INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6005{
6006 //get the running status from driver
6007 if(!output)
6008 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006009
6010 char config_file[128] = {0};
6011 char buf[16] = {0};
6012
6013 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6014 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6015 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6016 *output = TRUE;
6017 else
6018 *output = FALSE;
6019
developer06a01d92022-09-07 16:32:39 +08006020 return RETURN_OK;
6021}
6022
6023// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6024INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6025{
6026 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006027 char config_file[MAX_BUF_SIZE] = {0};
6028 struct params list;
6029
6030 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6031 list.name = "uapsd_advertisement_enabled";
6032 list.value = enable?"1":"0";
6033
6034 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6035 wifi_hostapdWrite(config_file, &list, 1);
6036 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6037 wifi_reloadAp(apIndex);
6038 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6039
6040 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006041}
6042
developer6daeb3f2022-09-30 13:36:39 +08006043// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006044INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6045{
developer6daeb3f2022-09-30 13:36:39 +08006046 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6047 char cmd[128] = {0};
6048 char buf[128] = {0};
6049 char ack_filepath[128] = {0};
6050 uint16_t bitmap = 0;
6051 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6052 FILE *f = NULL;
6053
6054 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6055
6056 // Get current setting
6057 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6058 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6059 _syscmd(cmd, buf, sizeof(buf));
6060 if (strlen(buf) > 0)
6061 bitmap = strtoul(buf, NULL, 10);
6062
6063 bitmap = strtoul(buf, NULL, 10);
6064
6065 if (ackPolicy == TRUE) { // True, unset this class
6066 bitmap &= ~class_map[class];
6067 } else { // False, set this class
6068 bitmap |= class_map[class];
6069 }
6070
6071 f = fopen(ack_filepath, "w");
6072 if (f == NULL) {
6073 fprintf(stderr, "%s: fopen failed\n", __func__);
6074 return RETURN_ERR;
6075 }
6076 fprintf(f, "%hu", bitmap);
6077 fclose(f);
6078
6079 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
6080 _syscmd(cmd, buf, sizeof(buf));
6081
6082 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6083 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006084}
6085
6086//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.
6087INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6088{
6089 //get the running status from driver
6090 if(!output_uint)
6091 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006092
6093 char output[16]={'\0'};
6094 char config_file[MAX_BUF_SIZE] = {0};
6095
6096 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6097 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6098 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6099 else {
6100 int device_num = atoi(output);
6101 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6102 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6103 return RETURN_ERR;
6104 }
6105 else {
6106 *output_uint = device_num;
6107 }
6108 }
6109
developer06a01d92022-09-07 16:32:39 +08006110 return RETURN_OK;
6111}
6112
6113INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6114{
6115 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006116 char str[MAX_BUF_SIZE]={'\0'};
6117 char cmd[MAX_CMD_SIZE]={'\0'};
6118 struct params params;
6119 char config_file[MAX_BUF_SIZE] = {0};
6120
6121 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006122 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006123 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6124 return RETURN_ERR;
6125 }
6126 sprintf(str, "%d", number);
6127 params.name = "max_num_sta";
6128 params.value = str;
6129
6130 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6131 int ret = wifi_hostapdWrite(config_file, &params, 1);
6132 if (ret) {
6133 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6134 ,__func__, ret);
6135 }
6136
6137 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6138 if (ret) {
6139 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6140 ,__func__, ret);
6141 }
6142 wifi_reloadAp(apIndex);
6143 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6144
6145 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006146}
6147
6148//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.
6149INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6150{
6151 //get the current threshold
6152 if(!output_uint)
6153 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006154 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6155 if (*output_uint == 0)
6156 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006157 return RETURN_OK;
6158}
6159
6160INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6161{
6162 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006163 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6164 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006165 return RETURN_ERR;
6166}
6167
6168//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.
6169INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6170{
6171 if(!output_uint)
6172 return RETURN_ERR;
6173 *output_uint = 3;
6174 return RETURN_OK;
6175}
6176
6177//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6178INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6179{
6180 if(!output_uint)
6181 return RETURN_ERR;
6182 *output_uint = 3;
6183 return RETURN_OK;
6184}
6185
6186//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.
6187INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6188{
6189 if(!output_in_seconds)
6190 return RETURN_ERR;
6191 *output_in_seconds = 0;
6192 return RETURN_OK;
6193}
6194
6195//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
6196INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6197{
6198 if(!output || apIndex>=MAX_APS)
6199 return RETURN_ERR;
6200 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006201 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006202 return RETURN_OK;
6203}
6204
6205//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6206INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6207{
developer587c1b62022-09-27 15:58:59 +08006208 char config_file[128] = {0};
6209 char wpa[16] = {0};
6210 char key_mgmt[64] = {0};
6211 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006212 if (!output)
6213 return RETURN_ERR;
6214
6215 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006216 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006217
developer587c1b62022-09-27 15:58:59 +08006218 strcpy(output, "None");//Copying "None" to output string for default case
6219 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006220 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006221 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006222 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006223 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006224 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006225 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006226 snprintf(output, 32, "WPA-WPA2-Personal");
6227
6228 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006229 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006230 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006231 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006232 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006233 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006234 snprintf(output, 32, "WPA-WPA2-Enterprise");
6235 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006236 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006237 snprintf(output, 32, "WPA3-Personal");
6238 else
developer4a359672022-10-13 15:30:46 +08006239 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006240 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6241 snprintf(output, 32, "WPA3-Enterprise");
6242 }
developer06a01d92022-09-07 16:32:39 +08006243
6244 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6245 return RETURN_OK;
6246#if 0
6247 //TODO: need to revisit below implementation
6248 char securityType[32], authMode[32];
6249 int enterpriseMode=0;
6250
6251 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6252 if(!output)
6253 return RETURN_ERR;
6254
6255 wifi_getApBeaconType(apIndex, securityType);
6256 strcpy(output,"None");//By default, copying "None" to output string
6257 if (strncmp(securityType,"None", strlen("None")) == 0)
6258 return RETURN_OK;
6259
6260 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6261 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6262
6263 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6264 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6265 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6266 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6267 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6268 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6269 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6270
6271 return RETURN_OK;
6272#endif
6273}
6274
6275INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6276{
6277 char securityType[32];
6278 char authMode[32];
6279
6280 //store settings and wait for wifi up to apply
6281 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6282 if(!encMode)
6283 return RETURN_ERR;
6284
developer06a01d92022-09-07 16:32:39 +08006285 if (strcmp(encMode, "None")==0)
6286 {
6287 strcpy(securityType,"None");
6288 strcpy(authMode,"None");
6289 }
6290 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6291 {
6292 strcpy(securityType,"WPAand11i");
6293 strcpy(authMode,"PSKAuthentication");
6294 }
6295 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6296 {
6297 strcpy(securityType,"WPAand11i");
6298 strcpy(authMode,"EAPAuthentication");
6299 }
6300 else if (strcmp(encMode, "WPA-Personal")==0)
6301 {
6302 strcpy(securityType,"WPA");
6303 strcpy(authMode,"PSKAuthentication");
6304 }
6305 else if (strcmp(encMode, "WPA-Enterprise")==0)
6306 {
6307 strcpy(securityType,"WPA");
6308 strcpy(authMode,"EAPAuthentication");
6309 }
6310 else if (strcmp(encMode, "WPA2-Personal")==0)
6311 {
6312 strcpy(securityType,"11i");
6313 strcpy(authMode,"PSKAuthentication");
6314 }
6315 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6316 {
6317 strcpy(securityType,"11i");
6318 strcpy(authMode,"EAPAuthentication");
6319 }
developer587c1b62022-09-27 15:58:59 +08006320 else if (strcmp(encMode, "WPA3-Personal") == 0)
6321 {
6322 strcpy(securityType,"11i");
6323 strcpy(authMode,"SAEAuthentication");
6324 }
developer4a359672022-10-13 15:30:46 +08006325 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006326 {
6327 strcpy(securityType, "11i");
6328 strcpy(authMode, "PSK-SAEAuthentication");
6329 }
developer587c1b62022-09-27 15:58:59 +08006330 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6331 {
6332 strcpy(securityType,"11i");
6333 strcpy(authMode,"EAP_192-bit_Authentication");
6334 }
developer06a01d92022-09-07 16:32:39 +08006335 else
6336 {
6337 strcpy(securityType,"None");
6338 strcpy(authMode,"None");
6339 }
6340 wifi_setApBeaconType(apIndex, securityType);
6341 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6342 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6343
6344 return RETURN_OK;
6345}
6346
6347
6348//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6349// output_string must be pre-allocated as 64 character string by caller
6350// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6351INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6352{
developer30423732022-12-01 16:17:49 +08006353 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006354 char config_file[MAX_BUF_SIZE] = {0};
6355
6356 if(output_string==NULL)
6357 return RETURN_ERR;
6358
6359 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6360 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6361
6362 if(strcmp(buf,"0")==0)
6363 {
6364 printf("wpa_mode is %s ......... \n",buf);
6365 return RETURN_ERR;
6366 }
6367
6368 wifi_dbg_printf("\nFunc=%s\n",__func__);
6369 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6370 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6371 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6372
6373 return RETURN_OK;
6374}
6375
6376// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6377// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6378INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6379{
6380 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6381 struct params params={'\0'};
6382 int ret;
6383 char config_file[MAX_BUF_SIZE] = {0};
6384
6385 if(NULL == preSharedKey)
6386 return RETURN_ERR;
6387
6388 params.name = "wpa_passphrase";
6389
6390 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6391 {
6392 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6393 return RETURN_ERR;
6394 }
6395 params.value = preSharedKey;
6396 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6397 ret = wifi_hostapdWrite(config_file, &params, 1);
6398 if(!ret)
6399 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6400 return ret;
6401 //TODO: call hostapd_cli for dynamic_config_control
6402}
6403
6404//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6405// outputs the passphrase, maximum 63 characters
6406INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6407{
6408 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6409
6410 wifi_dbg_printf("\nFunc=%s\n",__func__);
6411 if (NULL == output_string)
6412 return RETURN_ERR;
6413
6414 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6415 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6416 if(strcmp(buf,"0")==0)
6417 {
6418 printf("wpa_mode is %s ......... \n",buf);
6419 return RETURN_ERR;
6420 }
6421
6422 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6423 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6424
6425 return RETURN_OK;
6426}
6427
6428// sets the passphrase enviornment variable, max 63 characters
6429INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6430{
6431 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6432 struct params params={'\0'};
6433 char config_file[MAX_BUF_SIZE] = {0};
6434 int ret;
6435
6436 if(NULL == passPhrase)
6437 return RETURN_ERR;
6438
6439 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6440 {
6441 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6442 return RETURN_ERR;
6443 }
6444 params.name = "wpa_passphrase";
6445 params.value = passPhrase;
6446 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6447 ret=wifi_hostapdWrite(config_file,&params,1);
6448 if(!ret)
6449 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6450
6451 return ret;
6452}
6453
6454//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.
6455INT wifi_setApSecurityReset(INT apIndex)
6456{
developer8d583982022-09-20 11:28:22 +08006457 char original_config_file[64] = {0};
6458 char current_config_file[64] = {0};
6459 char buf[64] = {0};
6460 char cmd[64] = {0};
6461 char wpa[4] = {0};
6462 char wpa_psk[64] = {0};
6463 char wpa_passphrase[64] = {0};
6464 char wpa_psk_file[128] = {0};
6465 char wpa_key_mgmt[64] = {0};
6466 char wpa_pairwise[32] = {0};
6467 wifi_band band;
6468 struct params list[6];
6469
6470 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6471
6472 band = wifi_index_to_band(apIndex);
6473 if (band == band_2_4)
6474 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006475 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006476 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006477 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006478 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6479 else
6480 return RETURN_ERR;
6481
6482 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6483 list[0].name = "wpa";
6484 list[0].value = wpa;
6485
6486 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6487 list[1].name = "wpa_psk";
6488 list[1].value = wpa_psk;
6489
6490 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6491 list[2].name = "wpa_passphrase";
6492 list[2].value = wpa_passphrase;
6493
6494 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6495
6496 if (strlen(wpa_psk_file) == 0)
6497 strcpy(wpa_psk_file, PSK_FILE);
6498
6499 if (access(wpa_psk_file, F_OK) != 0) {
6500 sprintf(cmd, "touch %s", wpa_psk_file);
6501 _syscmd(cmd, buf, sizeof(buf));
6502 }
6503 list[3].name = "wpa_psk_file";
6504 list[3].value = wpa_psk_file;
6505
6506 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6507 list[4].name = "wpa_key_mgmt";
6508 list[4].value = wpa_key_mgmt;
6509
6510 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6511 list[5].name = "wpa_pairwise";
6512 list[5].value = wpa_pairwise;
6513
6514 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6515 wifi_hostapdWrite(current_config_file, list, 6);
6516
6517 wifi_setApEnable(apIndex, FALSE);
6518 wifi_setApEnable(apIndex, TRUE);
6519
6520 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6521 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006522}
6523
6524//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).
6525INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6526{
developer8f2ddd52022-09-13 15:39:24 +08006527 char config_file[64] = {0};
6528 char buf[64] = {0};
6529 char cmd[256] = {0};
6530
6531 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6532
developer06a01d92022-09-07 16:32:39 +08006533 if(!IP_output || !Port_output || !RadiusSecret_output)
6534 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006535
developer8f2ddd52022-09-13 15:39:24 +08006536 // Read the first matched config
6537 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6538 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6539 _syscmd(cmd, buf, sizeof(buf));
6540 strncpy(IP_output, buf, 64);
6541
6542 memset(buf, 0, sizeof(buf));
6543 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6544 _syscmd(cmd, buf, sizeof(buf));
6545 *Port_output = atoi(buf);
6546
6547 memset(buf, 0, sizeof(buf));
6548 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6549 _syscmd(cmd, buf, sizeof(buf));
6550 strncpy(RadiusSecret_output, buf, 64);
6551
6552 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006553 return RETURN_OK;
6554}
6555
6556INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6557{
developer8f2ddd52022-09-13 15:39:24 +08006558 char config_file[64] = {0};
6559 char port_str[8] = {0};
6560 char cmd[256] = {0};
6561 char buf[128] = {0};
6562
6563 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6564
6565 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6566
6567 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6568 _syscmd(cmd, buf, sizeof(buf));
6569 memset(cmd, 0, sizeof(cmd));
6570
6571 snprintf(port_str, sizeof(port_str), "%d", port);
6572 if (strlen(buf) == 0)
6573 // Append
6574 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6575 "auth_server_addr=%s\\n"
6576 "auth_server_port=%s\\n"
6577 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6578 else {
6579 // Delete the three lines setting after the "# radius 1" comment
6580 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6581 _syscmd(cmd, buf, sizeof(buf));
6582 memset(cmd, 0, sizeof(cmd));
6583 // Use "# radius 1" comment to find the location to insert the radius setting
6584 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6585 "# radius 1\\n"
6586 "auth_server_addr=%s\\n"
6587 "auth_server_port=%s\\n"
6588 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6589 }
6590 if(_syscmd(cmd, buf, sizeof(buf))) {
6591 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6592 return RETURN_ERR;
6593 }
6594
6595 wifi_reloadAp(apIndex);
6596 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6597 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006598}
6599
6600INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6601{
developer8f2ddd52022-09-13 15:39:24 +08006602 char config_file[64] = {0};
6603 char buf[64] = {0};
6604 char cmd[256] = {0};
6605
6606 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6607
developer06a01d92022-09-07 16:32:39 +08006608 if(!IP_output || !Port_output || !RadiusSecret_output)
6609 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006610
6611 // Read the second matched config
6612 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6613 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6614 _syscmd(cmd, buf, sizeof(buf));
6615 strncpy(IP_output, buf, 64);
6616
6617 memset(buf, 0, sizeof(buf));
6618 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6619 _syscmd(cmd, buf, sizeof(buf));
6620 *Port_output = atoi(buf);
6621
6622 memset(buf, 0, sizeof(buf));
6623 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6624 _syscmd(cmd, buf, sizeof(buf));
6625 strncpy(RadiusSecret_output, buf, 64);
6626
6627 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006628 return RETURN_OK;
6629}
6630
6631INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6632{
developer8f2ddd52022-09-13 15:39:24 +08006633 char config_file[64] = {0};
6634 char port_str[8] = {0};
6635 char cmd[256] = {0};
6636 char buf[128] = {0};
6637
6638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6639
6640 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6641
6642 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6643 _syscmd(cmd, buf, sizeof(buf));
6644 memset(cmd, 0, sizeof(cmd));
6645
6646 snprintf(port_str, sizeof(port_str), "%d", port);
6647 if (strlen(buf) == 0)
6648 // Append
6649 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6650 "auth_server_addr=%s\\n"
6651 "auth_server_port=%s\\n"
6652 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6653 else {
6654 // Delete the three lines setting after the "# radius 2" comment
6655 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6656 _syscmd(cmd, buf, sizeof(buf));
6657 memset(cmd, 0, sizeof(cmd));
6658 // Use "# radius 2" comment to find the location to insert the radius setting
6659 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6660 "# radius 2\\n"
6661 "auth_server_addr=%s\\n"
6662 "auth_server_port=%s\\n"
6663 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6664 }
6665 if(_syscmd(cmd, buf, sizeof(buf))) {
6666 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6667 return RETURN_ERR;
6668 }
6669
6670 wifi_reloadAp(apIndex);
6671 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6672 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006673}
6674
6675//RadiusSettings
6676INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6677{
6678 if(!output)
6679 return RETURN_ERR;
6680
6681 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6682 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6683 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6684 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6685 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6686 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.
6687 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6688 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6689 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6690 //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.
6691
6692 return RETURN_OK;
6693}
6694
6695INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6696{
6697 //store the paramters, and apply instantly
6698 return RETURN_ERR;
6699}
6700
6701//Device.WiFi.AccessPoint.{i}.WPS.Enable
6702//Enables or disables WPS functionality for this access point.
6703// outputs the WPS enable state of this ap in output_bool
6704INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6705{
6706 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer5b398df2022-11-17 20:39:48 +08006707 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08006708 return RETURN_ERR;
6709 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6710 _syscmd(cmd, buf, sizeof(buf));
6711 if(strstr(buf, "configured"))
6712 *output_bool=TRUE;
6713 else
6714 *output_bool=FALSE;
6715
6716 return RETURN_OK;
6717}
6718
6719//Device.WiFi.AccessPoint.{i}.WPS.Enable
6720// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6721INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6722{
6723 char config_file[MAX_BUF_SIZE] = {0};
6724 struct params params;
6725
developer06a01d92022-09-07 16:32:39 +08006726 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6727 //store the paramters, and wait for wifi up to apply
6728 params.name = "wps_state";
6729 params.value = enable ? "2":"0";
6730
6731 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6732 wifi_hostapdWrite(config_file, &params, 1);
6733 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6734 wifi_reloadAp(apIndex);
6735
6736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6737 return RETURN_OK;
6738}
6739
6740//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
6741INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6742{
6743 if(!output)
6744 return RETURN_ERR;
6745 snprintf(output, 128, "PushButton,PIN");
6746 return RETURN_OK;
6747}
6748
6749//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6750//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.
6751// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6752INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6753{
6754 if(!output)
6755 return RETURN_ERR;
6756 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6757
6758 return RETURN_OK;
6759}
6760
6761//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6762// 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
6763INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6764{
6765 //apply instantly. No setting need to be stored.
6766 char methods[MAX_BUF_SIZE], *token, *next_token;
6767 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6768 struct params params;
6769
developer5b398df2022-11-17 20:39:48 +08006770 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08006771 return RETURN_ERR;
6772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6773 //store the paramters, and wait for wifi up to apply
6774
6775 snprintf(methods, sizeof(methods), "%s", methodString);
6776 for(token=methods; *token; token=next_token)
6777 {
6778 strtok_r(token, ",", &next_token);
6779 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6780 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6781 else if(*token=='E')
6782 {
6783 if(!strcmp(methods, "Ethernet"))
6784 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6785 else if(!strcmp(methods, "ExternalNFCToken"))
6786 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6787 else
6788 printf("%s: Unknown WpsConfigMethod\n", __func__);
6789 }
6790 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6791 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6792 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6793 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6794 else if(*token=='P' )
6795 {
6796 if(!strcmp(token, "PushButton"))
6797 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6798 else if(!strcmp(token, "PIN"))
6799 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6800 else
6801 printf("%s: Unknown WpsConfigMethod\n", __func__);
6802 }
6803 else
6804 printf("%s: Unknown WpsConfigMethod\n", __func__);
6805 }
6806 params.name = "config_methods";
6807 params.value = config_methods;
6808 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6809 wifi_hostapdWrite(config_file, &params, 1);
6810 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6811 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6812
6813 return RETURN_OK;
6814}
6815
6816// outputs the pin value, ulong_pin must be allocated by the caller
6817INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6818{
6819 char buf[MAX_BUF_SIZE] = {0};
6820 char cmd[MAX_CMD_SIZE] = {0};
6821
developer5b398df2022-11-17 20:39:48 +08006822 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08006823 return RETURN_ERR;
6824 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6825 _syscmd(cmd, buf, sizeof(buf));
6826 if(strlen(buf) > 0)
6827 *output_ulong=strtoul(buf, NULL, 10);
6828
6829 return RETURN_OK;
6830}
6831
6832// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6833INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6834{
6835 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6836 char ap_pin[16] = {0};
6837 char buf[MAX_BUF_SIZE] = {0};
6838 char config_file[MAX_BUF_SIZE] = {0};
6839 ULONG prev_pin = 0;
6840 struct params params;
6841
developer06a01d92022-09-07 16:32:39 +08006842 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6843 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6844 params.name = "ap_pin";
6845 params.value = ap_pin;
6846 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6847 wifi_hostapdWrite(config_file, &params, 1);
6848 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6850
6851 return RETURN_OK;
6852}
6853
6854// Output string is either Not configured or Configured, max 32 characters
6855INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6856{
6857 char cmd[MAX_CMD_SIZE];
6858 char buf[MAX_BUF_SIZE]={0};
6859
developer5b398df2022-11-17 20:39:48 +08006860 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08006861 return RETURN_ERR;
6862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6863 snprintf(output_string, 32, "Not configured");
6864 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6865 _syscmd(cmd, buf, sizeof(buf));
6866
developer348e3d92022-09-13 14:48:41 +08006867 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006868 snprintf(output_string, 32, "Configured");
6869 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6870
6871 return RETURN_OK;
6872}
6873
6874// sets the WPS pin for this AP
6875INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6876{
6877 char cmd[MAX_CMD_SIZE];
6878 char buf[MAX_BUF_SIZE]={0};
6879 BOOL enable;
6880
developer06a01d92022-09-07 16:32:39 +08006881 wifi_getApEnable(apIndex, &enable);
6882 if (!enable)
6883 return RETURN_ERR;
6884 wifi_getApWpsEnable(apIndex, &enable);
6885 if (!enable)
6886 return RETURN_ERR;
6887
6888 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6889 _syscmd(cmd, buf, sizeof(buf));
6890 if((strstr(buf, "OK"))!=NULL)
6891 return RETURN_OK;
6892
6893 return RETURN_ERR;
6894}
6895
6896// This function is called when the WPS push button has been pressed for this AP
6897INT wifi_setApWpsButtonPush(INT apIndex)
6898{
6899 char cmd[MAX_CMD_SIZE];
6900 char buf[MAX_BUF_SIZE]={0};
6901 BOOL enable=FALSE;
6902
developer06a01d92022-09-07 16:32:39 +08006903 wifi_getApEnable(apIndex, &enable);
6904 if (!enable)
6905 return RETURN_ERR;
6906
6907 wifi_getApWpsEnable(apIndex, &enable);
6908 if (!enable)
6909 return RETURN_ERR;
6910
6911 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6912 _syscmd(cmd, buf, sizeof(buf));
6913
6914 if((strstr(buf, "OK"))!=NULL)
6915 return RETURN_OK;
6916 return RETURN_ERR;
6917}
6918
6919// cancels WPS mode for this AP
6920INT wifi_cancelApWPS(INT apIndex)
6921{
6922 char cmd[MAX_CMD_SIZE];
6923 char buf[MAX_BUF_SIZE]={0};
6924
developer06a01d92022-09-07 16:32:39 +08006925 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6926 _syscmd(cmd,buf, sizeof(buf));
6927
6928 if((strstr(buf, "OK"))!=NULL)
6929 return RETURN_OK;
6930 return RETURN_ERR;
6931}
6932
6933//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6934//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6935INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6936{
developer30423732022-12-01 16:17:49 +08006937 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08006938 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08006939 char cmd[256] = {0}, buf[2048] = {0};
6940 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08006941 size_t len = 0;
developer30423732022-12-01 16:17:49 +08006942 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08006943 wifi_associated_dev_t *dev=NULL;
6944
6945 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6946 *associated_dev_array = NULL;
6947 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6948 _syscmd(cmd,buf,sizeof(buf));
6949 *output_array_size = atoi(buf);
6950
6951 if (*output_array_size <= 0)
6952 return RETURN_OK;
6953
6954 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6955 *associated_dev_array = dev;
6956 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6957 _syscmd(cmd,buf,sizeof(buf));
6958 f = fopen("/tmp/connected_devices.txt", "r");
6959 if (f==NULL)
6960 {
6961 *output_array_size=0;
6962 return RETURN_ERR;
6963 }
developer30423732022-12-01 16:17:49 +08006964 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08006965 {
6966 param = strtok(line,"=");
6967 value = strtok(NULL,"=");
6968
6969 if( strcmp("flags",param) == 0 )
6970 {
6971 value[strlen(value)-1]='\0';
6972 if(strstr (value,"AUTHORIZED") != NULL )
6973 {
6974 dev[auth_temp].cli_AuthenticationState = 1;
6975 dev[auth_temp].cli_Active = 1;
6976 auth_temp++;
6977 read_flag=1;
6978 }
6979 }
6980 if(read_flag==1)
6981 {
6982 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6983 {
6984 value[strlen(value)-1]='\0';
6985 sscanf(value, "%x:%x:%x:%x:%x:%x",
6986 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6987 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6988 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6989 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6990 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6991 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6992 mac_temp++;
6993 read_flag=0;
6994 }
6995 }
6996 }
6997 *output_array_size = auth_temp;
6998 auth_temp=0;
6999 mac_temp=0;
7000 free(line);
7001 fclose(f);
7002 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7003 return RETURN_OK;
7004}
7005
7006#define MACADDRESS_SIZE 6
7007
7008INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7009{
7010 FILE *fp = NULL;
7011 char str[MAX_BUF_SIZE] = {0};
7012 int wificlientindex = 0 ;
7013 int count = 0;
7014 int signalstrength = 0;
7015 int arr[MACADDRESS_SIZE] = {0};
7016 unsigned char mac[MACADDRESS_SIZE] = {0};
7017 UINT wifi_count = 0;
7018 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7019 char pipeCmd[MAX_CMD_SIZE] = {0};
7020
7021 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7022 *output_array_size = 0;
7023 *associated_dev_array = NULL;
7024
7025 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7026 fp = popen(pipeCmd, "r");
7027 if (fp == NULL)
7028 {
7029 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7030 return RETURN_ERR;
7031 }
7032
7033 /* Read the output a line at a time - output it. */
7034 fgets(str, sizeof(str)-1, fp);
7035 wifi_count = (unsigned int) atoi ( str );
7036 *output_array_size = wifi_count;
7037 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7038 pclose(fp);
7039
7040 if(wifi_count == 0)
7041 {
7042 return RETURN_OK;
7043 }
7044 else
7045 {
7046 wifi_associated_dev3_t* temp = NULL;
7047 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7048 if(temp == NULL)
7049 {
7050 printf("Error Statement. Insufficient memory \n");
7051 return RETURN_ERR;
7052 }
7053
7054 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7055 system(pipeCmd);
7056 memset(pipeCmd,0,sizeof(pipeCmd));
7057 if(apIndex == 0)
7058 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7059 else if(apIndex == 1)
7060 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7061 system(pipeCmd);
7062
7063 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7064 if(fp == NULL)
7065 {
7066 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7067 return RETURN_ERR;
7068 }
7069 fclose(fp);
7070
developer30423732022-12-01 16:17:49 +08007071 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007072 fp = popen(pipeCmd, "r");
7073 if(fp)
7074 {
7075 for(count =0 ; count < wifi_count; count++)
7076 {
7077 fgets(str, MAX_BUF_SIZE, fp);
7078 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7079 {
7080 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7081 {
7082 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7083
7084 }
7085 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7086 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]);
7087 }
7088 temp[count].cli_AuthenticationState = 1; //TODO
7089 temp[count].cli_Active = 1; //TODO
7090 }
7091 pclose(fp);
7092 }
7093
developer30423732022-12-01 16:17:49 +08007094 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
developer06a01d92022-09-07 16:32:39 +08007095 fp = popen(pipeCmd, "r");
7096 if(fp)
7097 {
7098 pclose(fp);
7099 }
7100 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7101 if(fp)
7102 {
7103 for(count =0 ; count < wifi_count ;count++)
7104 {
7105 fgets(str, MAX_BUF_SIZE, fp);
7106 signalstrength = atoi(str);
7107 temp[count].cli_SignalStrength = signalstrength;
7108 temp[count].cli_RSSI = signalstrength;
7109 temp[count].cli_SNR = signalstrength + 95;
7110 }
7111 pclose(fp);
7112 }
7113
7114
7115 if((apIndex == 0) || (apIndex == 4))
7116 {
7117 for(count =0 ; count < wifi_count ;count++)
7118 {
7119 strcpy(temp[count].cli_OperatingStandard,"g");
7120 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7121 }
7122
7123 //BytesSent
developer30423732022-12-01 16:17:49 +08007124 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
developer06a01d92022-09-07 16:32:39 +08007125 fp = popen(pipeCmd, "r");
7126 if(fp)
7127 {
7128 pclose(fp);
7129 }
7130 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7131 if(fp)
7132 {
7133 for (count = 0; count < wifi_count; count++)
7134 {
7135 fgets(str, MAX_BUF_SIZE, fp);
7136 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7137 }
7138 pclose(fp);
7139 }
7140
7141 //BytesReceived
developer30423732022-12-01 16:17:49 +08007142 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
developer06a01d92022-09-07 16:32:39 +08007143 fp = popen(pipeCmd, "r");
7144 if (fp)
7145 {
7146 pclose(fp);
7147 }
7148 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7149 if (fp)
7150 {
7151 for (count = 0; count < wifi_count; count++)
7152 {
7153 fgets(str, MAX_BUF_SIZE, fp);
7154 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7155 }
7156 pclose(fp);
7157 }
7158
7159 //PacketsSent
developer30423732022-12-01 16:17:49 +08007160 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
developer06a01d92022-09-07 16:32:39 +08007161 fp = popen(pipeCmd, "r");
7162 if (fp)
7163 {
7164 pclose(fp);
7165 }
7166
7167 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7168 if (fp)
7169 {
7170 for (count = 0; count < wifi_count; count++)
7171 {
7172 fgets(str, MAX_BUF_SIZE, fp);
7173 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7174 }
7175 pclose(fp);
7176 }
7177
7178 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007179 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
developer06a01d92022-09-07 16:32:39 +08007180 fp = popen(pipeCmd, "r");
7181 if (fp)
7182 {
7183 pclose(fp);
7184 }
7185 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7186 if (fp)
7187 {
7188 for (count = 0; count < wifi_count; count++)
7189 {
7190 fgets(str, MAX_BUF_SIZE, fp);
7191 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7192 }
7193 pclose(fp);
7194 }
7195
7196 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007197 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
developer06a01d92022-09-07 16:32:39 +08007198 fp = popen(pipeCmd, "r");
7199 if (fp)
7200 {
7201 pclose(fp);
7202 }
7203 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7204 if (fp)
7205 {
7206 for (count = 0; count < wifi_count; count++)
7207 {
7208 fgets(str, MAX_BUF_SIZE, fp);
7209 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7210 }
7211 pclose(fp);
7212 }
7213
7214 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007215 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
developer06a01d92022-09-07 16:32:39 +08007216 fp = popen(pipeCmd, "r");
7217 if (fp)
7218 {
7219 pclose(fp);
7220 }
7221 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7222 if (fp)
7223 {
7224 for (count = 0; count < wifi_count; count++)
7225 {
7226 fgets(str, MAX_BUF_SIZE, fp);
7227 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7228 }
7229 pclose(fp);
7230 }
7231
7232 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007233 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
developer06a01d92022-09-07 16:32:39 +08007234 fp = popen(pipeCmd, "r");
7235 if (fp)
7236 {
7237 pclose(fp);
7238 }
7239 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7240 if (fp)
7241 {
7242 for (count = 0; count < wifi_count; count++)
7243 {
7244 fgets(str, MAX_BUF_SIZE, fp);
7245 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7246 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7247 }
7248 pclose(fp);
7249 }
7250
7251 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007252 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
developer06a01d92022-09-07 16:32:39 +08007253 fp = popen(pipeCmd, "r");
7254 if (fp)
7255 {
7256 pclose(fp);
7257 }
7258 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7259 if (fp)
7260 {
7261 for (count = 0; count < wifi_count; count++)
7262 {
7263 fgets(str, MAX_BUF_SIZE, fp);
7264 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7265 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7266 }
7267 pclose(fp);
7268 }
7269
7270 }
7271 else if ((apIndex == 1) || (apIndex == 5))
7272 {
7273 for (count = 0; count < wifi_count; count++)
7274 {
7275 strcpy(temp[count].cli_OperatingStandard, "a");
7276 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7277 temp[count].cli_BytesSent = 0;
7278 temp[count].cli_BytesReceived = 0;
7279 temp[count].cli_LastDataUplinkRate = 0;
7280 temp[count].cli_LastDataDownlinkRate = 0;
7281 temp[count].cli_PacketsSent = 0;
7282 temp[count].cli_PacketsReceived = 0;
7283 temp[count].cli_ErrorsSent = 0;
7284 }
7285 }
7286
7287 for (count = 0; count < wifi_count; count++)
7288 {
7289 temp[count].cli_Retransmissions = 0;
7290 temp[count].cli_DataFramesSentAck = 0;
7291 temp[count].cli_DataFramesSentNoAck = 0;
7292 temp[count].cli_MinRSSI = 0;
7293 temp[count].cli_MaxRSSI = 0;
7294 strncpy(temp[count].cli_InterferenceSources, "", 64);
7295 memset(temp[count].cli_IPAddress, 0, 64);
7296 temp[count].cli_RetransCount = 0;
7297 temp[count].cli_FailedRetransCount = 0;
7298 temp[count].cli_RetryCount = 0;
7299 temp[count].cli_MultipleRetryCount = 0;
7300 }
7301 *associated_dev_array = temp;
7302 }
7303 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7304 return RETURN_OK;
7305}
7306
7307int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7308{
7309 FILE *fp = NULL;
7310 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7311 char cmd[MAX_CMD_SIZE];
7312 int count = 0;
7313
7314 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7315 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7316 fp = popen(cmd,"r");
7317 if(fp == NULL)
7318 {
7319 printf("Failed to run command in Function %s\n",__FUNCTION__);
7320 return 0;
7321 }
7322 if(fgets(path, sizeof(path)-1, fp) != NULL)
7323 {
7324 for(count=0;path[count]!='\n';count++)
7325 status[count]=path[count];
7326 status[count]='\0';
7327 }
7328 strcpy(wifi_status,status);
7329 pclose(fp);
7330 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7331 return RETURN_OK;
7332}
7333
7334/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7335struct hostapd_sta_param {
7336 char key[50];
7337 char value[100];
7338}
7339
7340static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7341 int i = 0;
7342
7343 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7344 if (strncmp(params[i].key,key,50) == 0){
7345 return &params[i].value;
7346 }
7347 i++;
7348 }
7349 return NULL;
7350
7351} */
7352
7353static unsigned int count_occurences(const char *buf, const char *word)
7354{
7355 unsigned int n = 0;
7356 char *ptr = strstr(buf, word);
7357
7358 while (ptr++) {
7359 n++;
7360 ptr = strstr(ptr, word);
7361 }
7362
7363 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7364 return n;
7365}
7366
7367static const char *get_line_from_str_buf(const char *buf, char *line)
7368{
7369 int i;
7370 int n = strlen(buf);
7371
7372 for (i = 0; i < n; i++) {
7373 line[i] = buf[i];
7374 if (buf[i] == '\n') {
7375 line[i] = '\0';
7376 return &buf[i + 1];
7377 }
7378 }
7379
7380 return NULL;
7381}
7382
7383INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7384{
7385 unsigned int assoc_cnt = 0;
7386 char interface_name[50] = {0};
7387 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7388 char cmd[MAX_CMD_SIZE] = {'\0'};
7389 char line[256] = {'\0'};
7390 int i = 0;
7391 int ret = 0;
7392 const char *ptr = NULL;
7393 char *key = NULL;
7394 char *val = NULL;
7395 wifi_associated_dev3_t *temp = NULL;
7396 int rssi;
7397
7398 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7399
7400 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7401 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7402 return RETURN_ERR;
7403 }
7404
7405 // Example filtered output of 'iw dev' command:
7406 // Station 0a:69:72:10:d2:fa (on wifi0)
7407 // signal avg:-67 [-71, -71] dBm
7408 // Station 28:c2:1f:25:5f:99 (on wifi0)
7409 // signal avg:-67 [-71, -70] dBm
7410 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7411 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7412 return RETURN_ERR;
7413 }
7414
7415 ret = _syscmd(cmd, buf, sizeof(buf));
7416 if (ret == RETURN_ERR) {
7417 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7418 return RETURN_ERR;
7419 }
7420
7421 *output_array_size = count_occurences(buf, "Station");
7422 if (*output_array_size == 0) return RETURN_OK;
7423
7424 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7425 if (temp == NULL) {
7426 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7427 return RETURN_ERR;
7428 }
7429 *associated_dev_array = temp;
7430
7431 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7432 ptr = get_line_from_str_buf(buf, line);
7433 i = -1;
7434 while (ptr) {
7435 if (strstr(line, "Station")) {
7436 i++;
7437 key = strtok(line, " ");
7438 val = strtok(NULL, " ");
7439 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7440 &temp[i].cli_MACAddress[0],
7441 &temp[i].cli_MACAddress[1],
7442 &temp[i].cli_MACAddress[2],
7443 &temp[i].cli_MACAddress[3],
7444 &temp[i].cli_MACAddress[4],
7445 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7446 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7447 free(*associated_dev_array);
7448 return RETURN_ERR;
7449 }
7450 }
7451 else if (i < 0) {
7452 ptr = get_line_from_str_buf(ptr, line);
7453 continue; // We didn't detect 'station' entry yet
7454 }
7455 else if (strstr(line, "signal avg")) {
7456 key = strtok(line, ":");
7457 val = strtok(NULL, " ");
7458 if (sscanf(val, "%d", &rssi) <= 0 ) {
7459 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7460 free(*associated_dev_array);
7461 return RETURN_ERR;
7462 }
7463 temp[i].cli_RSSI = rssi;
7464 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7465 }
7466 // Here other fields can be parsed if added to filter of 'iw dev' command
7467
7468 ptr = get_line_from_str_buf(ptr, line);
7469 };
7470
7471 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7472
7473 return RETURN_OK;
7474}
7475
7476#if 0
7477//To-do
7478INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7479{
7480 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7481
7482 //Using different approach to get required WiFi Parameters from system available commands
7483#if 0
7484 FILE *f;
7485 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7486 char cmd[256], buf[2048];
7487 char *param , *value, *line=NULL;
7488 size_t len = 0;
7489 ssize_t nread;
7490 wifi_associated_dev3_t *dev=NULL;
7491 *associated_dev_array = NULL;
7492 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7493 _syscmd(cmd,buf,sizeof(buf));
7494 *output_array_size = atoi(buf);
7495
7496 if (*output_array_size <= 0)
7497 return RETURN_OK;
7498
7499 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7500 *associated_dev_array = dev;
7501 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7502 _syscmd(cmd,buf,sizeof(buf));
7503 f = fopen("/tmp/connected_devices.txt", "r");
7504 if (f==NULL)
7505 {
7506 *output_array_size=0;
7507 return RETURN_ERR;
7508 }
7509 while ((nread = getline(&line, &len, f)) != -1)
7510 {
7511 param = strtok(line,"=");
7512 value = strtok(NULL,"=");
7513
7514 if( strcmp("flags",param) == 0 )
7515 {
7516 value[strlen(value)-1]='\0';
7517 if(strstr (value,"AUTHORIZED") != NULL )
7518 {
7519 dev[auth_temp].cli_AuthenticationState = 1;
7520 dev[auth_temp].cli_Active = 1;
7521 auth_temp++;
7522 read_flag=1;
7523 }
7524 }
7525 if(read_flag==1)
7526 {
7527 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7528 {
7529 value[strlen(value)-1]='\0';
7530 sscanf(value, "%x:%x:%x:%x:%x:%x",
7531 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7532 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7533 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7534 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7535 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7536 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7537
7538 }
7539 else if( strcmp("rx_packets",param) == 0 )
7540 {
7541 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7542 }
7543
7544 else if( strcmp("tx_packets",param) == 0 )
7545 {
7546 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7547 }
7548
7549 else if( strcmp("rx_bytes",param) == 0 )
7550 {
7551 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7552 }
7553
7554 else if( strcmp("tx_bytes",param) == 0 )
7555 {
7556 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7557 mac_temp++;
7558 read_flag=0;
7559 }
7560 }
7561 }
7562
7563 *output_array_size = auth_temp;
7564 auth_temp=0;
7565 mac_temp=0;
7566 free(line);
7567 fclose(f);
7568#endif
7569 char interface_name[MAX_BUF_SIZE] = {0};
7570 char wifi_status[MAX_BUF_SIZE] = {0};
7571 char hostapdconf[MAX_BUF_SIZE] = {0};
7572
7573 wifi_associated_dev3_t *dev_array = NULL;
7574 ULONG wifi_count = 0;
7575
7576 *associated_dev_array = NULL;
7577 *output_array_size = 0;
7578
7579 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7580 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7581 {
7582 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7583
7584 GetInterfaceName(interface_name, hostapdconf);
7585
7586 if(strlen(interface_name) > 1)
7587 {
7588 wifihal_interfacestatus(wifi_status,interface_name);
7589 if(strcmp(wifi_status,"RUNNING") == 0)
7590 {
7591 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7592
7593 *associated_dev_array = dev_array;
7594 *output_array_size = wifi_count;
7595 }
7596 else
7597 {
7598 *associated_dev_array = NULL;
7599 }
7600 }
7601 }
7602
7603 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7604 return RETURN_OK;
7605}
7606#endif
7607
7608/* getIPAddress function */
7609/**
7610* @description Returning IpAddress of the Matched String
7611*
7612* @param
7613* @str Having MacAddress
7614* @ipaddr Having ipaddr
7615* @return The status of the operation
7616* @retval RETURN_OK if successful
7617* @retval RETURN_ERR if any error is detected
7618*
7619*/
7620
7621INT getIPAddress(char *str,char *ipaddr)
7622{
7623 FILE *fp = NULL;
7624 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7625 int LeaseTime = 0,ret = 0;
7626 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7627 {
7628 return RETURN_ERR;
7629 }
7630
7631 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7632 {
7633 /*
7634 Sample:sss
7635 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7636 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7637 */
7638 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7639 &(LeaseTime),
7640 phyAddr,
7641 ipAddr,
7642 hostName
7643 );
7644 if(ret != 4)
7645 continue;
7646 if(strcmp(str,phyAddr) == 0)
7647 strcpy(ipaddr,ipAddr);
7648 }
7649 return RETURN_OK;
7650}
7651
7652/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7653/**
7654* @description Returning Inactive wireless connected clients informations
7655*
7656* @param
7657* @filename Holding private_wifi 2g/5g content files
7658* @associated_dev_array Having inactiv wireless clients informations
7659* @output_array_size Returning Inactive wireless counts
7660* @return The status of the operation
7661* @retval RETURN_OK if successful
7662* @retval RETURN_ERR if any error is detected
7663*
7664*/
7665
7666INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7667{
7668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7669 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7670 FILE *fp = NULL;
7671 int arr[MACADDRESS_SIZE] = {0};
7672 unsigned char mac[MACADDRESS_SIZE] = {0};
7673 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7674 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7675 fp = popen(buf,"r");
7676 if(fp == NULL)
7677 return RETURN_ERR;
7678 else
7679 {
7680 fgets(path,sizeof(path),fp);
7681 maccount = atoi(path);
7682 }
7683 pclose(fp);
7684 *output_array_size = maccount;
7685 wifi_associated_dev3_t* temp = NULL;
7686 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7687 *associated_dev_array = temp;
7688 if(temp == NULL)
7689 {
7690 printf("Error Statement. Insufficient memory \n");
7691 return RETURN_ERR;
7692 }
7693 memset(buf,0,sizeof(buf));
7694 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7695 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08007696 if (fp == NULL) {
7697 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
7698 return RETURN_ERR;
7699 }
developer06a01d92022-09-07 16:32:39 +08007700 for(count = 0; count < maccount ; count++)
7701 {
7702 fgets(path,sizeof(path),fp);
7703 for(i = 0; path[i]!='\n';i++)
7704 str[i]=path[i];
7705 str[i]='\0';
7706 getIPAddress(str,ipaddr);
7707 memset(buf,0,sizeof(buf));
7708 if(strlen(ipaddr) > 0)
7709 {
7710 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7711 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7712 {
7713 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7714 {
7715 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7716 {
7717 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7718
7719 }
7720 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7721 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]);
7722 }
7723 temp[count].cli_AuthenticationState = 0; //TODO
7724 temp[count].cli_Active = 0; //TODO
7725 temp[count].cli_SignalStrength = 0;
7726 }
7727 else //Active wireless clients info
7728 {
7729 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7730 {
7731 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7732 {
7733 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7734
7735 }
7736 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7737 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]);
7738 }
7739 temp[count].cli_Active = 1;
7740 }
7741 }
7742 memset(ipaddr,0,sizeof(ipaddr));
7743 }
7744 pclose(fp);
7745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7746 return RETURN_OK;
7747}
7748//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7749//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7750//To get Band Steering Capability
7751INT wifi_getBandSteeringCapability(BOOL *support)
7752{
7753 *support = FALSE;
7754 return RETURN_OK;
7755}
7756
7757
7758//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7759//To get Band Steering enable status
7760INT wifi_getBandSteeringEnable(BOOL *enable)
7761{
7762 *enable = FALSE;
7763 return RETURN_OK;
7764}
7765
7766//To turn on/off Band steering
7767INT wifi_setBandSteeringEnable(BOOL enable)
7768{
7769 return RETURN_OK;
7770}
7771
7772//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7773//To get Band Steering AP group
7774INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7775{
7776 if (NULL == output_ApGroup)
7777 return RETURN_ERR;
7778
7779 strcpy(output_ApGroup, "1,2");
7780 return RETURN_OK;
7781}
7782
7783//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7784//to set and read the band steering BandUtilizationThreshold parameters
7785INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7786{
7787 return RETURN_ERR;
7788}
7789
7790INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7791{
7792 return RETURN_ERR;
7793}
7794
7795//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7796//to set and read the band steering RSSIThreshold parameters
7797INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7798{
7799 return RETURN_ERR;
7800}
7801
7802INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7803{
7804 return RETURN_ERR;
7805}
7806
7807
7808//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7809//to set and read the band steering physical modulation rate threshold parameters
7810INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7811{
7812 //If chip is not support, return -1
7813 return RETURN_ERR;
7814}
7815
7816INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7817{
7818 //If chip is not support, return -1
7819 return RETURN_ERR;
7820}
7821
7822//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7823//to set and read the inactivity time (in seconds) for steering under overload condition
7824INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7825{
7826 return RETURN_ERR;
7827}
7828
7829INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7830{
7831 return RETURN_ERR;
7832}
7833
7834//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7835//to set and read the inactivity time (in seconds) for steering under Idle condition
7836INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7837{
7838 return RETURN_ERR;
7839}
7840
7841INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7842{
7843 return RETURN_ERR;
7844}
7845
7846//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7847//pClientMAC[64]
7848//pSourceSSIDIndex[64]
7849//pDestSSIDIndex[64]
7850//pSteeringReason[256]
7851INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7852{
7853 //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
7854 *pSteeringTime=time(NULL);
7855 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7856 return RETURN_OK;
7857}
7858
7859INT wifi_ifConfigDown(INT apIndex)
7860{
7861 INT status = RETURN_OK;
7862 char cmd[64];
7863
7864 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7865 printf("%s: %s\n", __func__, cmd);
7866 system(cmd);
7867
7868 return status;
7869}
7870
7871INT wifi_ifConfigUp(INT apIndex)
7872{
7873 char cmd[128];
7874 char buf[1024];
7875
7876 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7877 _syscmd(cmd, buf, sizeof(buf));
7878 return 0;
7879}
7880
7881//>> Deprecated. Replace with wifi_applyRadioSettings
7882INT wifi_pushBridgeInfo(INT apIndex)
7883{
developer30423732022-12-01 16:17:49 +08007884 char ip[32] = {0};
7885 char subnet[32] = {0};
7886 char bridge[32] = {0};
7887 int vlanId = 0;
7888 char cmd[128] = {0};
7889 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08007890
7891 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7892 wifi_getApVlanID(apIndex,&vlanId);
7893
7894 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7895 _syscmd(cmd,buf, sizeof(buf));
7896
7897 return 0;
7898}
7899
7900INT wifi_pushChannel(INT radioIndex, UINT channel)
7901{
7902 char cmd[128];
7903 char buf[1024];
7904 int apIndex;
7905
7906 apIndex=(radioIndex==0)?0:1;
7907 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7908 _syscmd(cmd,buf, sizeof(buf));
7909
7910 return 0;
7911}
7912
7913INT wifi_pushChannelMode(INT radioIndex)
7914{
7915 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7916 return RETURN_ERR;
7917}
7918
7919INT wifi_pushDefaultValues(INT radioIndex)
7920{
7921 //Apply Comcast specified default radio settings instantly
7922 //AMPDU=1
7923 //AMPDUFrames=32
7924 //AMPDULim=50000
7925 //txqueuelen=1000
7926
7927 return RETURN_ERR;
7928}
7929
7930INT wifi_pushTxChainMask(INT radioIndex)
7931{
7932 //Apply default TxChainMask instantly
7933 return RETURN_ERR;
7934}
7935
7936INT wifi_pushRxChainMask(INT radioIndex)
7937{
7938 //Apply default RxChainMask instantly
7939 return RETURN_ERR;
7940}
7941
7942INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7943{
7944 INT status;
7945
7946 status = wifi_setSSIDName(apIndex,ssid);
7947 wifi_setApEnable(apIndex,FALSE);
7948 wifi_setApEnable(apIndex,TRUE);
7949
7950 return status;
7951}
7952
7953INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7954{
7955 //Apply default Ssid Advertisement instantly
7956 return RETURN_ERR;
7957}
7958
7959INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7960{
7961 INT status = RETURN_ERR;
7962 *output = 0;
7963 return RETURN_ERR;
7964}
7965
7966INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7967{
7968 return RETURN_OK;
7969}
7970
7971INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7972{
7973 return RETURN_OK;
7974}
7975
7976//To-do
7977INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7978{
developereb199ae2022-09-13 14:04:27 +08007979 char output[16]={'\0'};
7980 char config_file[MAX_BUF_SIZE] = {0};
7981
7982 if (!output_string)
7983 return RETURN_ERR;
7984
7985 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7986 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7987
7988 if (strlen(output) == 0)
7989 snprintf(output_string, 64, "Disabled");
7990 else if (strncmp(output, "0", 1) == 0)
7991 snprintf(output_string, 64, "Disabled");
7992 else if (strncmp(output, "1", 1) == 0)
7993 snprintf(output_string, 64, "Optional");
7994 else if (strncmp(output, "2", 1) == 0)
7995 snprintf(output_string, 64, "Required");
7996 else {
7997 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7998 return RETURN_ERR;
7999 }
8000
8001 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008002 return RETURN_OK;
8003}
8004INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8005{
developereb199ae2022-09-13 14:04:27 +08008006 char str[MAX_BUF_SIZE]={'\0'};
8007 char cmd[MAX_CMD_SIZE]={'\0'};
8008 struct params params;
8009 char config_file[MAX_BUF_SIZE] = {0};
8010
8011 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8012 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8013 return RETURN_ERR;
8014
8015 params.name = "ieee80211w";
8016 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8017 params.value = "0";
8018 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8019 params.value = "1";
8020 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8021 params.value = "2";
8022 else{
8023 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8024 return RETURN_ERR;
8025 }
8026 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8027 wifi_hostapdWrite(config_file, &params, 1);
8028 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008029 return RETURN_OK;
8030}
8031INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8032{
8033 char output[16]={'\0'};
8034 char config_file[MAX_BUF_SIZE] = {0};
8035
8036 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8037 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8038 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8039
8040 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8041 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8042
8043 return RETURN_OK;
8044}
8045
8046INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8047{
8048 return RETURN_OK;
8049}
8050
8051INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8052{
8053 return RETURN_OK;
8054}
8055
8056INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8057{
8058 return RETURN_OK;
8059}
8060
8061INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8062{
8063 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8064 char config_file[MAX_BUF_SIZE] = {0};
8065
8066 if (NULL == output)
8067 return RETURN_ERR;
8068 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8069 wifi_hostapdRead(config_file,"hw_mode",output,64);
8070
8071 if(strcmp(output,"b")==0)
8072 sprintf(output, "%s", "1,2,5.5,11");
8073 else if (strcmp(output,"a")==0)
8074 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8075 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8076 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8077
8078 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8079 return RETURN_OK;
8080}
8081
8082INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8083{
8084 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8085 char *temp;
8086 char temp_output[128];
8087 char temp_TransmitRates[128];
8088 char config_file[MAX_BUF_SIZE] = {0};
8089
8090 if (NULL == output)
8091 return RETURN_ERR;
8092
8093 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8094 wifi_hostapdRead(config_file,"supported_rates",output,64);
8095
developer5b398df2022-11-17 20:39:48 +08008096 if (strlen(output) == 0) {
8097 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8098 return RETURN_OK;
8099 }
developer06a01d92022-09-07 16:32:39 +08008100 strcpy(temp_TransmitRates,output);
8101 strcpy(temp_output,"");
8102 temp = strtok(temp_TransmitRates," ");
8103 while(temp!=NULL)
8104 {
8105 temp[strlen(temp)-1]=0;
8106 if((temp[0]=='5') && (temp[1]=='\0'))
8107 {
8108 temp="5.5";
8109 }
8110 strcat(temp_output,temp);
8111 temp = strtok(NULL," ");
8112 if(temp!=NULL)
8113 {
8114 strcat(temp_output,",");
8115 }
8116 }
8117 strcpy(output,temp_output);
8118 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8119
8120 return RETURN_OK;
8121}
8122
8123INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8124{
8125 return RETURN_OK;
8126}
8127
8128
8129INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8130{
8131 int i=0;
8132 char *temp;
developeref938762022-10-19 17:21:01 +08008133 char temp1[128] = {0};
8134 char temp_output[128] = {0};
8135 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008136 struct params params={'\0'};
8137 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008138 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008139
8140 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8141 if(NULL == output)
8142 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008143 strcpy(temp_TransmitRates,output);
8144
8145 for(i=0;i<strlen(temp_TransmitRates);i++)
8146 {
developeref938762022-10-19 17:21:01 +08008147 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008148 {
8149 continue;
8150 }
8151 else
8152 {
8153 return RETURN_ERR;
8154 }
8155 }
8156 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008157 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008158 while(temp!=NULL)
8159 {
8160 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008161 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008162 {
developeref938762022-10-19 17:21:01 +08008163 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008164 {
8165 return RETURN_ERR;
8166 }
8167 }
8168
8169 if(strcmp(temp,"5.5")==0)
8170 {
8171 strcpy(temp1,"55");
8172 }
8173 else
8174 {
8175 strcat(temp1,"0");
8176 }
8177 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008178 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008179 if(temp!=NULL)
8180 {
8181 strcat(temp_output," ");
8182 }
8183 }
8184 strcpy(output,temp_output);
8185
developer06a01d92022-09-07 16:32:39 +08008186 params.name = "supported_rates";
8187 params.value = output;
8188
8189 wifi_dbg_printf("\n%s:",__func__);
8190 wifi_dbg_printf("params.value=%s\n",params.value);
8191 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8192 wifi_hostapdWrite(config_file,&params,1);
8193 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8194
8195 return RETURN_OK;
8196}
8197
8198
8199static char *sncopy(char *dst, int dst_sz, const char *src)
8200{
8201 if (src && dst && dst_sz > 0) {
8202 strncpy(dst, src, dst_sz);
8203 dst[dst_sz - 1] = '\0';
8204 }
8205 return dst;
8206}
8207
8208static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8209{
8210 if (0 == strcmp(ht_mode, "HT40") ||
8211 0 == strcmp(ht_mode, "HT80") ||
8212 0 == strcmp(ht_mode, "HT160")) {
8213 switch (channel) {
8214 case 1 ... 7:
8215 case 36:
8216 case 44:
8217 case 52:
8218 case 60:
8219 case 100:
8220 case 108:
8221 case 116:
8222 case 124:
8223 case 132:
8224 case 140:
8225 case 149:
8226 case 157:
8227 return 1;
8228 case 8 ... 13:
8229 case 40:
8230 case 48:
8231 case 56:
8232 case 64:
8233 case 104:
8234 case 112:
8235 case 120:
8236 case 128:
8237 case 136:
8238 case 144:
8239 case 153:
8240 case 161:
8241 return -1;
8242 default:
8243 return -EINVAL;
8244 }
8245 }
8246
8247 return -EINVAL;
8248}
8249
developerb7593de2022-10-18 09:51:57 +08008250static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8251{
8252 int idx = channel%8;
8253 if (0 == strcmp(ht_mode, "HT40") ||
8254 0 == strcmp(ht_mode, "HT80") ||
8255 0 == strcmp(ht_mode, "HT160")) {
8256 switch (idx) {
8257 case 1:
8258 return 1;
8259 case 5:
8260 return -1;
8261 default:
8262 return -EINVAL;
8263 }
8264 }
8265
8266 return -EINVAL;
8267}
developer06a01d92022-09-07 16:32:39 +08008268static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8269{
8270 if (NULL == hw_mode) return;
8271
8272 if (0 == strcmp(hw_mode, "ac"))
8273 sncopy(bw_mode, bw_mode_len, "ht vht");
8274
8275 if (0 == strcmp(hw_mode, "n"))
8276 sncopy(bw_mode, bw_mode_len, "ht");
8277
8278 return;
8279}
8280
8281static int util_chan_to_freq(int chan)
8282{
8283 if (chan == 14)
8284 return 2484;
8285 else if (chan < 14)
8286 return 2407 + chan * 5;
8287 else if (chan >= 182 && chan <= 196)
8288 return 4000 + chan * 5;
8289 else
8290 return 5000 + chan * 5;
8291 return 0;
8292}
8293
developerb7593de2022-10-18 09:51:57 +08008294static int util_6G_chan_to_freq(int chan)
8295{
8296 if (chan)
8297 return 5950 + chan * 5;
8298 else
8299 return 0;
8300
8301}
developer06a01d92022-09-07 16:32:39 +08008302const int *util_unii_5g_chan2list(int chan, int width)
8303{
8304 static const int lists[] = {
8305 // <width>, <chan1>, <chan2>..., 0,
8306 20, 36, 0,
8307 20, 40, 0,
8308 20, 44, 0,
8309 20, 48, 0,
8310 20, 52, 0,
8311 20, 56, 0,
8312 20, 60, 0,
8313 20, 64, 0,
8314 20, 100, 0,
8315 20, 104, 0,
8316 20, 108, 0,
8317 20, 112, 0,
8318 20, 116, 0,
8319 20, 120, 0,
8320 20, 124, 0,
8321 20, 128, 0,
8322 20, 132, 0,
8323 20, 136, 0,
8324 20, 140, 0,
8325 20, 144, 0,
8326 20, 149, 0,
8327 20, 153, 0,
8328 20, 157, 0,
8329 20, 161, 0,
8330 20, 165, 0,
8331 40, 36, 40, 0,
8332 40, 44, 48, 0,
8333 40, 52, 56, 0,
8334 40, 60, 64, 0,
8335 40, 100, 104, 0,
8336 40, 108, 112, 0,
8337 40, 116, 120, 0,
8338 40, 124, 128, 0,
8339 40, 132, 136, 0,
8340 40, 140, 144, 0,
8341 40, 149, 153, 0,
8342 40, 157, 161, 0,
8343 80, 36, 40, 44, 48, 0,
8344 80, 52, 56, 60, 64, 0,
8345 80, 100, 104, 108, 112, 0,
8346 80, 116, 120, 124, 128, 0,
8347 80, 132, 136, 140, 144, 0,
8348 80, 149, 153, 157, 161, 0,
8349 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8350 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8351 -1 // final delimiter
8352 };
8353 const int *start;
8354 const int *p;
8355
8356 for (p = lists; *p != -1; p++) {
8357 if (*p == width) {
8358 for (start = ++p; *p != 0; p++) {
8359 if (*p == chan)
8360 return start;
8361 }
8362 }
8363 // move to the end of channel list of given width
8364 while (*p != 0) {
8365 p++;
8366 }
8367 }
8368
8369 return NULL;
8370}
8371
8372static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8373{
8374 if (NULL == ht_mode)
8375 return 0;
8376
8377 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8378 const int *chans = util_unii_5g_chan2list(channel, width);
8379 int sum = 0;
8380 int cnt = 0;
8381
8382 if (NULL == chans)
8383 return 0;
8384
8385 while (*chans) {
8386 sum += *chans;
8387 cnt++;
8388 chans++;
8389 }
developer30423732022-12-01 16:17:49 +08008390 if (cnt == 0)
8391 return 0;
developer06a01d92022-09-07 16:32:39 +08008392 return sum / cnt;
8393}
8394
developerb7593de2022-10-18 09:51:57 +08008395static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8396{
8397 if (NULL == ht_mode)
8398 return 0;
8399
8400 int width = strtol((ht_mode + 2), NULL, 10);
8401
8402 int idx = 0 ;
8403 int centerchan = 0;
8404 int chan_ofs = 1;
8405
8406 if (width == 40){
8407 idx = ((channel/4) + chan_ofs)%2;
8408 switch (idx) {
8409 case 0:
8410 centerchan = (channel - 2);
8411 break;
8412 case 1:
8413 centerchan = (channel + 2);
8414 break;
8415 default:
8416 return -EINVAL;
8417 }
8418 }else if (width == 80){
8419 idx = ((channel/4) + chan_ofs)%4;
8420 switch (idx) {
8421 case 0:
8422 centerchan = (channel - 6);
8423 break;
8424 case 1:
8425 centerchan = (channel + 6);
8426 break;
8427 case 2:
8428 centerchan = (channel + 2);
8429 break;
8430 case 3:
8431 centerchan = (channel - 2);
8432 break;
8433 default:
8434 return -EINVAL;
8435 }
8436 }else if (width == 160){
8437 switch (channel) {
8438 case 1 ... 29:
8439 centerchan = 15;
8440 break;
8441 case 33 ... 61:
8442 centerchan = 47;
8443 break;
8444 case 65 ... 93:
8445 centerchan = 79;
8446 break;
8447 case 97 ... 125:
8448 centerchan = 111;
8449 break;
8450 case 129 ... 157:
8451 centerchan = 143;
8452 break;
8453 case 161 ... 189:
8454 centerchan = 175;
8455 break;
8456 case 193 ... 221:
8457 centerchan = 207;
8458 break;
8459 default:
8460 return -EINVAL;
8461 }
8462 }
8463 return centerchan;
8464}
developer06a01d92022-09-07 16:32:39 +08008465static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8466{
8467 BOOL onlyG, onlyN, onlyA;
8468 CHAR tmp[64];
8469 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8470 if (ret == RETURN_OK) {
8471 sncopy(hw_mode, hw_mode_size, tmp);
8472 }
8473 return ret;
8474}
8475
8476INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8477{
8478 // Sample commands:
8479 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8480 // hostapd_cli -i wifi0 chan_switch 30 2437
8481 char cmd[MAX_CMD_SIZE] = {0};
8482 char buf[MAX_BUF_SIZE] = {0};
8483 int freq = 0, ret = 0;
8484 char center_freq1_str[32] = ""; // center_freq1=%d
8485 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8486 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8487 char hw_mode[16] = ""; // n|ac
8488 char bw_mode[16] = ""; // ht|ht vht
8489 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8490 int sec_chan_offset;
8491 int width;
developer4fb0b922022-09-30 14:29:09 +08008492 char config_file[64] = {0};
8493 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008494 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008495 wifi_band band = band_invalid;
8496 int center_chan = 0;
8497 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008498
developer4fb0b922022-09-30 14:29:09 +08008499 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008500
8501 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8502
developerb7593de2022-10-18 09:51:57 +08008503 band = wifi_index_to_band(radioIndex);
8504
developer5884e982022-10-06 10:52:50 +08008505 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008506
8507 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008508 if (channel){
developerb7593de2022-10-18 09:51:57 +08008509 if (band == band_6){
8510 freq = util_6G_chan_to_freq(channel);
8511 }else{
8512 freq = util_chan_to_freq(channel);
8513 }
developer5884e982022-10-06 10:52:50 +08008514 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008515
developer5884e982022-10-06 10:52:50 +08008516 // Provide bandwith if specified
8517 if (channel_width_MHz > 20) {
8518 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8519 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8520 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008521
developer5884e982022-10-06 10:52:50 +08008522 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8523 }else if (channel_width_MHz == 20){
8524 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8525 }
developer06a01d92022-09-07 16:32:39 +08008526
developerb7593de2022-10-18 09:51:57 +08008527
developer5884e982022-10-06 10:52:50 +08008528 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008529 if (band == band_6){
8530 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8531 if(center_chan){
8532 center_freq1 = util_6G_chan_to_freq(center_chan);
8533 }
8534 }else{
8535 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8536 if(center_chan){
8537 center_freq1 = util_chan_to_freq(center_chan);
8538 }
developer5884e982022-10-06 10:52:50 +08008539 }
developerb7593de2022-10-18 09:51:57 +08008540
8541 if (center_freq1)
8542 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8543
8544 }
8545
8546 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8547 if (band == band_6){
8548 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8549 }else{
8550 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008551 }
developerb7593de2022-10-18 09:51:57 +08008552 if (sec_chan_offset != -EINVAL)
8553 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008554
developer5884e982022-10-06 10:52:50 +08008555 // Only the first AP, other are hanging on the same radio
8556 int apIndex = radioIndex;
8557 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8558 AP_PREFIX, apIndex, csa_beacon_count, freq,
8559 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8560 wifi_dbg_printf("execute: '%s'\n", cmd);
8561 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008562
developer5884e982022-10-06 10:52:50 +08008563 ret = wifi_setRadioChannel(radioIndex, channel);
8564 if (ret != RETURN_OK) {
8565 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8566 return RETURN_ERR;
8567 }
8568
8569 if (sec_chan_offset == 1) ext_str = "Above";
8570 else if (sec_chan_offset == -1) ext_str = "Below";
8571
8572 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008573
developer5884e982022-10-06 10:52:50 +08008574 } else {
8575 if (channel_width_MHz > 20)
8576 ext_str = "Above";
8577 }
developer4fb0b922022-09-30 14:29:09 +08008578 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8579 _syscmd(cmd, buf, sizeof(buf));
8580 if (strlen(buf) != 0)
8581 stbcEnable = TRUE;
8582
developer06a01d92022-09-07 16:32:39 +08008583 wifi_setRadioExtChannel(radioIndex, ext_str);
8584
developer4fb0b922022-09-30 14:29:09 +08008585 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8586
developer06a01d92022-09-07 16:32:39 +08008587 char mhz_str[16];
8588 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8589 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8590
8591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8592
8593 return RETURN_OK;
8594}
8595
8596INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8597{
developer615510b2022-09-27 10:14:35 +08008598 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008599 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008600 char cmd[256]={0};
8601 char buf[128]={0};
8602 char file_name[32] = {0};
8603 char filter_SSID[32] = {0};
8604 char line[256] = {0};
8605 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008606 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008607 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008608 size_t len=0;
8609 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008610 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008611 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008612 bool filter_enable = false;
8613 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008614 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008615
developer615510b2022-09-27 10:14:35 +08008616 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008617
developer615510b2022-09-27 10:14:35 +08008618 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8619 f = fopen(file_name, "r");
8620 if (f != NULL) {
8621 fgets(filter_SSID, sizeof(file_name), f);
8622 if (strlen(filter_SSID) != 0)
8623 filter_enable = true;
8624 fclose(f);
8625 }
8626
developer033b37b2022-10-18 11:27:46 +08008627 phyId = radio_index_to_phy(radio_index);
8628
8629 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008630 _syscmd(cmd, buf, sizeof(buf));
8631 channels_num = strtol(buf, NULL, 10);
8632
developer615510b2022-09-27 10:14:35 +08008633 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8634 // 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);
8635 fprintf(stderr, "cmd: %s\n", cmd);
8636 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008637 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8638 return RETURN_ERR;
8639 }
developer5550e242022-09-30 09:59:32 +08008640
8641 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8642 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8643
developer615510b2022-09-27 10:14:35 +08008644 ret = fgets(line, sizeof(line), f);
8645 while (ret != NULL) {
8646 if(strstr(line, "BSS") != NULL) { // new neighbor info
8647 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8648 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8649 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8650
8651 if (!filter_BSS) {
8652 index++;
8653 wifi_neighbor_ap2_t *tmp;
8654 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8655 if (tmp == NULL) { // no more memory to use
8656 index--;
8657 wifi_dbg_printf("%s: realloc failed\n", __func__);
8658 break;
8659 }
8660 scan_array = tmp;
8661 }
8662 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008663
developer615510b2022-09-27 10:14:35 +08008664 filter_BSS = false;
8665 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8666 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8667 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8668 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8669 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008670 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008671 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008672
developer615510b2022-09-27 10:14:35 +08008673 if (freq >= 2412 && freq <= 2484) {
8674 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8675 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8676 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8677 }
8678 else if (freq >= 5160 && freq <= 5805) {
8679 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8680 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8681 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8682 }
developer06a01d92022-09-07 16:32:39 +08008683
developer615510b2022-09-27 10:14:35 +08008684 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008685 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008686 for (int i = 0; i < channels_num; i++) {
8687 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8688 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8689 break;
8690 }
8691 }
developer06a01d92022-09-07 16:32:39 +08008692 }
developer615510b2022-09-27 10:14:35 +08008693 } else if (strstr(line, "beacon interval") != NULL) {
8694 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8695 } else if (strstr(line, "signal") != NULL) {
8696 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8697 } else if (strstr(line,"SSID") != NULL) {
8698 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8699 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8700 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008701 }
developer615510b2022-09-27 10:14:35 +08008702 } else if (strstr(line, "Supported rates") != NULL) {
8703 char SRate[80] = {0}, *tmp = NULL;
8704 memset(buf, 0, sizeof(buf));
8705 strcpy(SRate, line);
8706 tmp = strtok(SRate, ":");
8707 tmp = strtok(NULL, ":");
8708 strcpy(buf, tmp);
8709 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008710
developer615510b2022-09-27 10:14:35 +08008711 tmp = strtok(buf, " \n");
8712 while (tmp != NULL) {
8713 strcat(SRate, tmp);
8714 if (SRate[strlen(SRate) - 1] == '*') {
8715 SRate[strlen(SRate) - 1] = '\0';
8716 }
8717 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008718
developer615510b2022-09-27 10:14:35 +08008719 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008720 }
developer615510b2022-09-27 10:14:35 +08008721 SRate[strlen(SRate) - 1] = '\0';
8722 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8723 } else if (strstr(line, "DTIM") != NULL) {
8724 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8725 } else if (strstr(line, "VHT capabilities") != NULL) {
8726 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8727 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8728 } else if (strstr(line, "HT capabilities") != NULL) {
8729 strcat(scan_array[index].ap_SupportedStandards, ",n");
8730 strcpy(scan_array[index].ap_OperatingStandards, "n");
8731 } else if (strstr(line, "VHT operation") != NULL) {
8732 ret = fgets(line, sizeof(line), f);
8733 sscanf(line," * channel width: %d", &vht_channel_width);
8734 if(vht_channel_width == 1) {
8735 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8736 } else {
8737 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8738 }
8739 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8740 continue;
8741 } else if (strstr(line, "HT operation") != NULL) {
8742 ret = fgets(line, sizeof(line), f);
8743 sscanf(line," * secondary channel offset: %s", &buf);
8744 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008745 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008746 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 +08008747 }
developer615510b2022-09-27 10:14:35 +08008748 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008749 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008750 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8751 } else {
8752 //20Mhz
8753 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 +08008754 }
developer615510b2022-09-27 10:14:35 +08008755 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008756 continue;
developer615510b2022-09-27 10:14:35 +08008757 } else if (strstr(line, "HE capabilities") != NULL) {
8758 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8759 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8760 ret = fgets(line, sizeof(line), f);
8761 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8762 if (strstr(line, "HE40/2.4GHz") != NULL)
8763 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8764 else
8765 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8766 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8767 if (strstr(line, "HE80/5GHz") != NULL) {
8768 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8769 ret = fgets(line, sizeof(line), f);
8770 } else
8771 continue;
8772 if (strstr(line, "HE160/5GHz") != NULL)
8773 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008774 }
developer615510b2022-09-27 10:14:35 +08008775 continue;
8776 } else if (strstr(line, "WPA") != NULL) {
8777 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8778 } else if (strstr(line, "RSN") != NULL) {
8779 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8780 } else if (strstr(line, "Group cipher") != NULL) {
8781 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8782 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8783 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008784 }
developer06a01d92022-09-07 16:32:39 +08008785 }
developer615510b2022-09-27 10:14:35 +08008786 ret = fgets(line, sizeof(line), f);
8787 }
8788
8789 if (!filter_BSS) {
8790 *output_array_size = index + 1;
8791 } else {
8792 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8793 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008794 }
developer06a01d92022-09-07 16:32:39 +08008795 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008796 pclose(f);
developer5550e242022-09-30 09:59:32 +08008797 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008798 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008799 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008800}
developer615510b2022-09-27 10:14:35 +08008801
developer06a01d92022-09-07 16:32:39 +08008802INT wifi_getApAssociatedDeviceStats(
8803 INT apIndex,
8804 mac_address_t *clientMacAddress,
8805 wifi_associated_dev_stats_t *associated_dev_stats,
8806 u64 *handle)
8807{
8808 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8809 char interface_name[50] = {0};
8810 char cmd[1024] = {0};
8811 char mac_str[18] = {0};
8812 char *key = NULL;
8813 char *val = NULL;
8814 FILE *f = NULL;
8815 char *line = NULL;
8816 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08008817
8818 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8819 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8820 return RETURN_ERR;
8821 }
8822
8823 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8824 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8825 if((f = popen(cmd, "r")) == NULL) {
8826 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8827 return RETURN_ERR;
8828 }
8829
developer30423732022-12-01 16:17:49 +08008830 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08008831 key = strtok(line,":");
8832 val = strtok(NULL,":");
8833
8834 if(!strncmp(key,"rx bytes",8))
8835 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8836 if(!strncmp(key,"tx bytes",8))
8837 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8838 if(!strncmp(key,"rx packets",10))
8839 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8840 if(!strncmp(key,"tx packets",10))
8841 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8842 if(!strncmp(key,"tx retries",10))
8843 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8844 if(!strncmp(key,"tx failed",9))
8845 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8846 if(!strncmp(key,"rx drop misc",13))
8847 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8848 if(!strncmp(key,"rx bitrate",10)) {
8849 val = strtok(val, " ");
8850 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8851 }
8852 if(!strncmp(key,"tx bitrate",10)) {
8853 val = strtok(val, " ");
8854 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8855 }
8856 }
8857 free(line);
8858 pclose(f);
8859 return RETURN_OK;
8860}
8861
8862INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8863{
8864 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8865
8866 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8867 if (NULL == output_string)
8868 return RETURN_ERR;
8869
8870 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8871 _syscmd(cmd, buf, sizeof(buf));
8872
8873 //size of SSID name restricted to value less than 32 bytes
8874 snprintf(output_string, 32, "%s", buf);
8875 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8876
8877 return RETURN_OK;
8878}
8879
8880INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8881{
8882 //char cmd[MAX_CMD_SIZE] = {0};
8883 char config_file[MAX_BUF_SIZE] = {0};
8884 char buf[32] = {0};
8885
8886 if (!output_filterMode)
8887 return RETURN_ERR;
8888
8889 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8890 //_syscmd(cmd, buf, sizeof(buf));
8891 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8892 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008893 if(strlen(buf) == 0) {
8894 *output_filterMode = 0;
8895 }
8896 else {
8897 int macaddr_acl_mode = strtol(buf, NULL, 10);
8898 if (macaddr_acl_mode == 1) {
8899 *output_filterMode = 1;
8900 } else if (macaddr_acl_mode == 0) {
8901 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8902 if (strlen(buf) == 0) {
8903 *output_filterMode = 0;
8904 } else {
8905 *output_filterMode = 2;
8906 }
8907 } else {
8908 return RETURN_ERR;
8909 }
8910 }
developer06a01d92022-09-07 16:32:39 +08008911
8912 return RETURN_OK;
8913}
8914
8915INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8916{
8917 FILE *fp = NULL;
8918 char str[MAX_BUF_SIZE] = {0};
8919 int wificlientindex = 0 ;
8920 int count = 0;
8921 int signalstrength = 0;
8922 int arr[MACADDRESS_SIZE] = {0};
8923 unsigned char mac[MACADDRESS_SIZE] = {0};
8924 UINT wifi_count = 0;
8925 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8926 char pipeCmd[MAX_CMD_SIZE] = {0};
8927
8928 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8929 *output_array_size = 0;
8930 *associated_dev_array = NULL;
8931 char interface_name[50] = {0};
8932
8933 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8934 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8935 return RETURN_ERR;
8936 }
8937
8938 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8939 fp = popen(pipeCmd, "r");
8940 if (fp == NULL)
8941 {
8942 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8943 return RETURN_ERR;
8944 }
8945
8946 /* Read the output a line at a time - output it. */
8947 fgets(str, sizeof(str)-1, fp);
8948 wifi_count = (unsigned int) atoi ( str );
8949 *output_array_size = wifi_count;
8950 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8951 pclose(fp);
8952
8953 if(wifi_count == 0)
8954 {
8955 return RETURN_OK;
8956 }
8957 else
8958 {
8959 wifi_associated_dev2_t* temp = NULL;
8960 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8961 *associated_dev_array = temp;
8962 if(temp == NULL)
8963 {
8964 printf("Error Statement. Insufficient memory \n");
8965 return RETURN_ERR;
8966 }
8967
8968 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8969 system(pipeCmd);
8970
8971 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8972 if(fp == NULL)
8973 {
8974 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8975 return RETURN_ERR;
8976 }
8977 fclose(fp);
8978
developer30423732022-12-01 16:17:49 +08008979 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08008980 fp = popen(pipeCmd, "r");
8981 if(fp)
8982 {
8983 for(count =0 ; count < wifi_count; count++)
8984 {
8985 fgets(str, MAX_BUF_SIZE, fp);
8986 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8987 {
8988 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8989 {
8990 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8991
8992 }
8993 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8994 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]);
8995 }
8996 temp[count].cli_AuthenticationState = 1; //TODO
8997 temp[count].cli_Active = 1; //TODO
8998 }
8999 pclose(fp);
9000 }
9001
9002 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009003 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
developer06a01d92022-09-07 16:32:39 +08009004 fp = popen(pipeCmd, "r");
9005 if(fp)
9006 {
9007 pclose(fp);
9008 }
9009 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9010 if(fp)
9011 {
9012 for(count =0 ; count < wifi_count ;count++)
9013 {
9014 fgets(str, MAX_BUF_SIZE, fp);
9015 signalstrength = atoi(str);
9016 temp[count].cli_RSSI = signalstrength;
9017 }
9018 pclose(fp);
9019 }
9020
9021
9022 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009023 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
developer06a01d92022-09-07 16:32:39 +08009024 fp = popen(pipeCmd, "r");
9025 if (fp)
9026 {
9027 pclose(fp);
9028 }
9029 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9030 if (fp)
9031 {
9032 for (count = 0; count < wifi_count; count++)
9033 {
9034 fgets(str, MAX_BUF_SIZE, fp);
9035 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9036 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9037 }
9038 pclose(fp);
9039 }
9040
9041 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009042 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
developer06a01d92022-09-07 16:32:39 +08009043 fp = popen(pipeCmd, "r");
9044 if (fp)
9045 {
9046 pclose(fp);
9047 }
9048 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9049 if (fp)
9050 {
9051 for (count = 0; count < wifi_count; count++)
9052 {
9053 fgets(str, MAX_BUF_SIZE, fp);
9054 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9055 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9056 }
9057 pclose(fp);
9058 }
9059 }
9060 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9061 return RETURN_OK;
9062
9063}
9064
9065INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9066{
9067#if 0
9068 /*char buf[1024] = {0};
9069 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
9070 _syscmd(cmd, buf, sizeof(buf));*/
9071
9072 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9073 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9074 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9075 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9076
9077 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.
9078 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].
9079 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].
9080 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].
9081 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9082 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9083
9084 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9085 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9086 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9087 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.
9088 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.
9089 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.
9090 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.
9091 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.
9092 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.
9093 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.
9094 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9095#endif
9096
9097 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08009098 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08009099 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009100 char pipeCmd[128] = {0};
9101 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009102 wifi_ssidTrafficStats2_t *out = output_struct;
9103
developerce736392022-09-13 15:24:34 +08009104 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009105 if (!output_struct)
9106 return RETURN_ERR;
9107
developerce736392022-09-13 15:24:34 +08009108 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9109 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
9110 GetInterfaceName(interface_name, HConf_file);
9111 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009112
developer06a01d92022-09-07 16:32:39 +08009113 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009114 if (fp == NULL) {
9115 fprintf(stderr, "%s: popen failed\n", __func__);
9116 return RETURN_ERR;
9117 }
9118 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08009119
developerce736392022-09-13 15:24:34 +08009120 if (strlen(str) == 0) // interface not exist
9121 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009122
developerce736392022-09-13 15:24:34 +08009123 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9124 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009125 pclose(fp);
9126
developerce736392022-09-13 15:24:34 +08009127 memset(str, 0, sizeof(str));
9128 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009129 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009130 if (fp == NULL) {
9131 fprintf(stderr, "%s: popen failed\n", __func__);
9132 return RETURN_ERR;
9133 }
9134 fgets(str, sizeof(str), fp);
9135
9136 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9137 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009138 pclose(fp);
developerce736392022-09-13 15:24:34 +08009139
9140 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9141 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9142
9143 // Not supported
9144 output_struct->ssid_RetransCount = 0;
9145 output_struct->ssid_FailedRetransCount = 0;
9146 output_struct->ssid_RetryCount = 0;
9147 output_struct->ssid_MultipleRetryCount = 0;
9148 output_struct->ssid_ACKFailureCount = 0;
9149 output_struct->ssid_AggregatedPacketCount = 0;
9150
developer06a01d92022-09-07 16:32:39 +08009151 return RETURN_OK;
9152}
9153
9154//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).
9155INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9156{
9157 char output_val[16]={'\0'};
9158 char config_file[MAX_BUF_SIZE] = {0};
9159
9160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9161 if (!output)
9162 return RETURN_ERR;
9163 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9164 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9165
9166 if( strcmp(output_val,"1") == 0 )
9167 *output = TRUE;
9168 else
9169 *output = FALSE;
9170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9171
9172 return RETURN_OK;
9173}
9174
9175INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9176{
9177 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9178 char str[MAX_BUF_SIZE]={'\0'};
9179 char string[MAX_BUF_SIZE]={'\0'};
9180 char cmd[MAX_CMD_SIZE]={'\0'};
9181 char *ch;
9182 char config_file[MAX_BUF_SIZE] = {0};
9183 struct params params;
9184
9185 if(enable == TRUE)
9186 strcpy(string,"1");
9187 else
9188 strcpy(string,"0");
9189
9190 params.name = "ap_isolate";
9191 params.value = string;
9192
9193 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9194 wifi_hostapdWrite(config_file,&params,1);
9195 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9196
9197 return RETURN_OK;
9198}
9199
9200INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9201{
9202 if (NULL == output_dBm)
9203 return RETURN_ERR;
9204
9205 *output_dBm = 0;
9206 return RETURN_OK;
9207}
9208
9209INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9210{
9211 return RETURN_OK;
9212}
9213INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9214{
9215 return RETURN_OK;
9216}
9217INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9218{
9219 return RETURN_OK;
9220}
9221INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9222{
9223 return RETURN_OK;
9224}
9225INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9226{
9227 return RETURN_OK;
9228}
9229INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9230{
9231 char config_file[MAX_BUF_SIZE] = {0};
9232 struct params list;
9233
9234 list.name = "bss_transition";
9235 list.value = activate?"1":"0";
9236 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9237 wifi_hostapdWrite(config_file, &list, 1);
9238
9239 return RETURN_OK;
9240}
9241wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9242
9243void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9244{
9245 return;
9246}
9247
9248INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9249{
9250 // TODO Implement me!
9251 return RETURN_OK;
9252}
9253
9254INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9255{
developera3c68b92022-09-13 15:27:29 +08009256 char file_name[128] = {0};
9257 char buf[128] = {0};
9258 FILE *f = NULL;
developer804c64f2022-10-19 13:54:40 +08009259 int max_num_radios = 0;
developera3c68b92022-09-13 15:27:29 +08009260
9261 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9262
developer804c64f2022-10-19 13:54:40 +08009263 wifi_getMaxRadioNumber(&max_num_radios);
developera3c68b92022-09-13 15:27:29 +08009264 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
developer804c64f2022-10-19 13:54:40 +08009265 for (int index = 0; index < max_num_radios; index++) {
developera3c68b92022-09-13 15:27:29 +08009266 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9267 f = fopen(file_name, "w");
9268 if (f == NULL)
9269 return RETURN_ERR;
9270 // For mode == 0 is to disable filter, just don't write to the file.
9271 if (mode)
9272 fprintf(f, "%s", essid);
9273
9274 fclose(f);
9275 }
9276 } else { // special case, need to set AP's SSID as filter for each radio.
9277 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9278 f = fopen(file_name, "w");
9279 if (f == NULL)
9280 return RETURN_ERR;
9281
9282 // For mode == 0 is to disable filter, just don't write to the file.
9283 if (mode)
9284 fprintf(f, "%s", essid);
9285
9286 fclose(f);
9287 }
9288
9289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009290 return RETURN_OK;
9291}
9292
9293INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9294{
9295 // TODO Implement me!
9296 //Apply wifi_pushRadioChannel() instantly
9297 return RETURN_ERR;
9298}
9299
9300INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9301{
9302 // TODO Implement me!
9303 return RETURN_OK;
9304}
9305
9306#ifdef HAL_NETLINK_IMPL
9307static int tidStats_callback(struct nl_msg *msg, void *arg) {
9308 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9309 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9310 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9311 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9312 int rem , tid_index = 0;
9313
9314 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9315 wifi_associated_dev_tid_entry_t *stats_entry;
9316
9317 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9318 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9319 };
9320 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9321 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9322 };
9323
9324 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9325 genlmsg_attrlen(gnlh, 0), NULL);
9326
9327
9328 if (!tb[NL80211_ATTR_STA_INFO]) {
9329 fprintf(stderr, "station stats missing!\n");
9330 return NL_SKIP;
9331 }
9332
9333 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9334 tb[NL80211_ATTR_STA_INFO],
9335 stats_policy)) {
9336 fprintf(stderr, "failed to parse nested attributes!\n");
9337 return NL_SKIP;
9338 }
9339
9340 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9341 {
9342 stats_entry = &out->tid_array[tid_index];
9343
9344 stats_entry->tid = tid_index;
9345 stats_entry->ac = _tid_ac_index_get[tid_index];
9346
9347 if(sinfo[NL80211_STA_INFO_TID_STATS])
9348 {
9349 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9350 printf("failed to parse nested stats attributes!");
9351 return NL_SKIP;
9352 }
9353 }
9354 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9355 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9356
9357 if(tid_index < (PS_MAX_TID - 1))
9358 tid_index++;
9359 }
9360 //ToDo: sum_time_ms, ewma_time_ms
9361 return NL_SKIP;
9362}
9363#endif
9364
9365INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9366{
9367#ifdef HAL_NETLINK_IMPL
9368 Netlink nl;
9369 char if_name[10];
9370
9371 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9372
9373 nl.id = initSock80211(&nl);
9374
9375 if (nl.id < 0) {
9376 fprintf(stderr, "Error initializing netlink \n");
9377 return -1;
9378 }
9379
9380 struct nl_msg* msg = nlmsg_alloc();
9381
9382 if (!msg) {
9383 fprintf(stderr, "Failed to allocate netlink message.\n");
9384 nlfree(&nl);
9385 return -2;
9386 }
9387
9388 genlmsg_put(msg,
9389 NL_AUTO_PORT,
9390 NL_AUTO_SEQ,
9391 nl.id,
9392 0,
9393 0,
9394 NL80211_CMD_GET_STATION,
9395 0);
9396
9397 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9398 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9399 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9400 nl_send_auto(nl.socket, msg);
9401 nl_recvmsgs(nl.socket, nl.cb);
9402 nlmsg_free(msg);
9403 nlfree(&nl);
9404 return RETURN_OK;
9405#else
9406//iw implementation
9407#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9408#define TOTAL_MAX_LINES 50
9409
9410 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9411 char if_name[10];
9412 FILE *fp=NULL;
9413 char pipeCmd[1024]= {'\0'};
9414 int lines,tid_index=0;
9415 char mac_addr[20] = {'\0'};
9416
9417 wifi_associated_dev_tid_entry_t *stats_entry;
9418
9419 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9420 strcpy(mac_addr,clientMacAddress);
9421
9422 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9423 fp= popen(pipeCmd,"r");
9424 if(fp == NULL)
9425 {
9426 perror("popen for station dump failed\n");
9427 return RETURN_ERR;
9428 }
9429 pclose(fp);
9430
9431 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9432 fp=popen(pipeCmd,"r");
9433 if(fp == NULL)
9434 {
9435 perror("popen for grep station failed\n");
9436 return RETURN_ERR;
9437 }
9438 else if(fgets(buf,sizeof(buf),fp) != NULL)
9439 lines=atoi(buf);
9440 else
9441 {
9442 pclose(fp);
9443 fprintf(stderr,"No devices are connected \n");
9444 return RETURN_ERR;
9445 }
9446 pclose(fp);
9447
9448 if(lines == 1)
9449 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9450
9451 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9452 {
9453 stats_entry = &tid_stats->tid_array[tid_index];
9454 stats_entry->tid = tid_index;
9455
9456 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);
9457
9458 fp=popen(pipeCmd,"r");
9459 if(fp ==NULL)
9460 {
9461 perror("Failed to read from tid file \n");
9462 return RETURN_ERR;
9463 }
9464 else if(fgets(buf,sizeof(buf),fp) != NULL)
9465 stats_entry->num_msdus = atol(buf);
9466
9467 pclose(fp);
9468 stats_entry->ac = _tid_ac_index_get[tid_index];
9469// TODO:
9470// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9471// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9472 }
9473 return RETURN_OK;
9474#endif
9475}
9476
9477
9478INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9479{
developer615510b2022-09-27 10:14:35 +08009480 char cmd[128]={0};
9481 char buf[128]={0};
9482 int freq = 0;
9483
9484 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9485
9486 // full mode is used to scan all channels.
9487 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9488 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9489 ieee80211_channel_to_frequency(chan_list[0], &freq);
9490
9491 if (freq)
9492 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9493 else
9494 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9495
9496 _syscmd(cmd, buf, sizeof(buf));
9497 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9498
developer06a01d92022-09-07 16:32:39 +08009499 return RETURN_OK;
9500}
9501
9502
9503INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9504{
9505 // TODO Implement me!
9506 return RETURN_ERR;
9507}
9508
9509INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9510{
9511 // TODO Implement me!
9512 return RETURN_ERR;
9513}
9514
9515INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9516{
9517 // TODO Implement me!
9518 return RETURN_ERR;
9519}
9520
9521INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9522{
9523 // TODO Implement me!
9524 return RETURN_ERR;
9525}
9526
9527INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9528{
9529 // TODO Implement me!
9530 return RETURN_ERR;
9531}
9532
9533INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9534{
9535 // TODO Implement me!
9536 return RETURN_ERR;
9537}
9538
9539INT wifi_steering_eventUnregister(void)
9540{
9541 // TODO Implement me!
9542 return RETURN_ERR;
9543}
9544
9545INT wifi_delApAclDevices(INT apIndex)
9546{
9547#if 0
9548 char cmd[MAX_BUF_SIZE] = {0};
9549 char buf[MAX_BUF_SIZE] = {0};
9550
9551 /* Not reset proof solution */
9552 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9553 if(_syscmd(cmd,buf,sizeof(buf)))
9554 return RETURN_ERR;
9555#endif
developere6aafda2022-09-13 14:59:28 +08009556 char cmd[MAX_CMD_SIZE]={0};
9557 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009558
developere6aafda2022-09-13 14:59:28 +08009559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9560 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9561 if(_syscmd(cmd, buf, sizeof(buf)))
9562 return RETURN_ERR;
9563 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009564
9565 return RETURN_OK;
9566}
9567
9568#ifdef HAL_NETLINK_IMPL
9569static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9570 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9571 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9572 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9573 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9574 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9575 char mac_addr[20],dev[20];
9576
9577 nla_parse(tb,
9578 NL80211_ATTR_MAX,
9579 genlmsg_attrdata(gnlh, 0),
9580 genlmsg_attrlen(gnlh, 0),
9581 NULL);
9582
9583 if(!tb[NL80211_ATTR_STA_INFO]) {
9584 fprintf(stderr, "sta stats missing!\n");
9585 return NL_SKIP;
9586 }
9587
9588 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9589 fprintf(stderr, "failed to parse nested attributes!\n");
9590 return NL_SKIP;
9591 }
9592 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9593
9594 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9595
9596 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9597 fprintf(stderr, "failed to parse nested rate attributes!");
9598 return NL_SKIP;
9599 }
9600
9601 if(sinfo[NL80211_STA_INFO_TID_STATS])
9602 {
9603 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9604 printf("failed to parse nested stats attributes!");
9605 return NL_SKIP;
9606 }
9607 }
9608
9609 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9610 {
9611 printf("Type is VHT\n");
9612 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9613 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9614
9615 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9616 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9617 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9618 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9619 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9620 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9621 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9622 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9623 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9624 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9625 }
9626 else
9627 {
9628 printf(" OFDM or CCK \n");
9629 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9630 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9631 }
9632
9633 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9634 if(rinfo[NL80211_RATE_INFO_MCS])
9635 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9636 }
9637 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9638 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9639 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9640 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9641
9642 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9643 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9644
9645 if (sinfo[NL80211_STA_INFO_SIGNAL])
9646 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9647 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9648 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9649 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9650 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9651 //rssi_array need to be filled
9652 return NL_SKIP;
9653}
9654#endif
9655
9656INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9657{
9658#ifdef HAL_NETLINK_IMPL
9659 Netlink nl;
9660 char if_name[10];
9661
9662 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9663
9664 if (*output_array_size <= 0)
9665 return RETURN_OK;
9666
9667 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9668 nl.id = initSock80211(&nl);
9669
9670 if (nl.id < 0) {
9671 fprintf(stderr, "Error initializing netlink \n");
9672 return 0;
9673 }
9674
9675 struct nl_msg* msg = nlmsg_alloc();
9676
9677 if (!msg) {
9678 fprintf(stderr, "Failed to allocate netlink message.\n");
9679 nlfree(&nl);
9680 return 0;
9681 }
9682
9683 genlmsg_put(msg,
9684 NL_AUTO_PORT,
9685 NL_AUTO_SEQ,
9686 nl.id,
9687 0,
9688 0,
9689 NL80211_CMD_GET_STATION,
9690 0);
9691
9692 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9693 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9694 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9695 nl_send_auto(nl.socket, msg);
9696 nl_recvmsgs(nl.socket, nl.cb);
9697 nlmsg_free(msg);
9698 nlfree(&nl);
9699 return RETURN_OK;
9700#else
9701 //TODO Implement me
9702 return RETURN_OK;
9703#endif
9704}
9705
9706#ifdef HAL_NETLINK_IMPL
9707static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9708 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9709 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9710 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9711 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9712 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9713 char mac_addr[20],dev[20];
9714
9715 nla_parse(tb,
9716 NL80211_ATTR_MAX,
9717 genlmsg_attrdata(gnlh, 0),
9718 genlmsg_attrlen(gnlh, 0),
9719 NULL);
9720
9721 if(!tb[NL80211_ATTR_STA_INFO]) {
9722 fprintf(stderr, "sta stats missing!\n");
9723 return NL_SKIP;
9724 }
9725
9726 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9727 fprintf(stderr, "failed to parse nested attributes!\n");
9728 return NL_SKIP;
9729 }
9730
9731 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9732
9733 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9734
9735 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9736 fprintf(stderr, "failed to parse nested rate attributes!");
9737 return NL_SKIP;
9738 }
9739
9740 if(sinfo[NL80211_STA_INFO_TID_STATS])
9741 {
9742 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9743 printf("failed to parse nested stats attributes!");
9744 return NL_SKIP;
9745 }
9746 }
9747 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9748 {
9749 printf("Type is VHT\n");
9750 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9751 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9752
9753 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9754 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9755 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9756 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9757 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9758 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9759 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9760 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9761 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9762 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9763 }
9764 else
9765 {
9766 printf(" OFDM or CCK \n");
9767 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9768 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9769 }
9770
9771 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9772 if(rinfo[NL80211_RATE_INFO_MCS])
9773 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9774 }
9775
9776 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9777 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9778 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9779 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9780
9781 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9782 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9783 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9784
9785 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9786 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9787
9788 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9789 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9790
9791 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9792 ((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]);
9793
9794 return NL_SKIP;
9795}
9796#endif
9797
9798INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9799{
9800#ifdef HAL_NETLINK_IMPL
9801 Netlink nl;
9802 char if_name[10];
9803
9804 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9805
9806 if (*output_array_size <= 0)
9807 return RETURN_OK;
9808
9809 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9810
9811 nl.id = initSock80211(&nl);
9812
9813 if(nl.id < 0) {
9814 fprintf(stderr, "Error initializing netlink \n");
9815 return 0;
9816 }
9817
9818 struct nl_msg* msg = nlmsg_alloc();
9819
9820 if(!msg) {
9821 fprintf(stderr, "Failed to allocate netlink message.\n");
9822 nlfree(&nl);
9823 return 0;
9824 }
9825
9826 genlmsg_put(msg,
9827 NL_AUTO_PORT,
9828 NL_AUTO_SEQ,
9829 nl.id,
9830 0,
9831 0,
9832 NL80211_CMD_GET_STATION,
9833 0);
9834
9835 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9836 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9837 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9838 nl_send_auto(nl.socket, msg);
9839 nl_recvmsgs(nl.socket, nl.cb);
9840 nlmsg_free(msg);
9841 nlfree(&nl);
9842 return RETURN_OK;
9843#else
9844 //TODO Implement me
9845 return RETURN_OK;
9846#endif
9847}
9848
9849INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9850{
9851 // TODO Implement me!
9852 char buf[MAX_BUF_SIZE] = {0};
9853 char config_file[MAX_BUF_SIZE] = {0};
9854
9855 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9856 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9857 *activate = (strncmp("1",buf,1) == 0);
9858
9859 return RETURN_OK;
9860}
9861
9862INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9863{
9864 char config_file[MAX_BUF_SIZE] = {0};
9865 struct params list;
9866
9867 list.name = "rrm_neighbor_report";
9868 list.value = activate?"1":"0";
9869 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9870 wifi_hostapdWrite(config_file, &list, 1);
9871
9872 return RETURN_OK;
9873}
9874
9875INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9876{
9877 char buf[32] = {0};
9878 char config_file[MAX_BUF_SIZE] = {0};
9879
9880 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9881 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9882 *activate = (strncmp("1",buf,1) == 0);
9883
9884 return RETURN_OK;
9885}
9886#undef HAL_NETLINK_IMPL
9887#ifdef HAL_NETLINK_IMPL
9888static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9889 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9890 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9891 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9892 char dev[20];
9893 int freq =0 ;
9894 static int i=0;
9895
9896 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9897
9898 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9899 };
9900
9901 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9902
9903 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9904
9905 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9906 fprintf(stderr, "survey data missing!\n");
9907 return NL_SKIP;
9908 }
9909
9910 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9911 {
9912 fprintf(stderr, "failed to parse nested attributes!\n");
9913 return NL_SKIP;
9914 }
9915
9916
9917 if(out[0].array_size == 1 )
9918 {
9919 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9920 {
9921 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9922 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9923 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9924
9925 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9926 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9927 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9928 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9929 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9930 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9931 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9932 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9933 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9934 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9935 if (sinfo[NL80211_SURVEY_INFO_TIME])
9936 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9937 return NL_STOP;
9938 }
9939 }
9940 else
9941 {
9942 if ( i <= out[0].array_size )
9943 {
9944 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9945 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9946 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9947
9948 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9949 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9950 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9951 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9952 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9953 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9954 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9955 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9956 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9957 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9958 if (sinfo[NL80211_SURVEY_INFO_TIME])
9959 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9960 }
9961 }
9962
9963 i++;
9964 return NL_SKIP;
9965}
9966#endif
9967
9968static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9969{
9970 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9971 FILE *fp;
9972
9973 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9974 {
9975 printf("Creating Frequency-Channel Map\n");
9976 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9977 }
9978 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9979 if((fp = popen(command, "r")))
9980 {
9981 fgets(output, sizeof(output), fp);
9982 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +08009983 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009984 }
9985
9986 return 0;
9987}
9988
9989static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9990{
9991 int freqMHz = -1;
9992 char cmd[MAX_CMD_SIZE] = {'\0'};
developer033b37b2022-10-18 11:27:46 +08009993 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08009994
9995 ieee80211_channel_to_frequency(channel, &freqMHz);
9996 if (freqMHz == -1) {
9997 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9998 return -1;
9999 }
10000
developer033b37b2022-10-18 11:27:46 +080010001 phyId = radio_index_to_phy(radioIndex);
10002 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, phyId, freqMHz) < 0) {
developer06a01d92022-09-07 16:32:39 +080010003 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10004 radioIndex, freqMHz);
10005 return -1;
10006 }
10007
10008 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10009 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10010 return -1;
10011 }
10012
10013 return 0;
10014}
10015
10016static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10017{
10018 const char *ptr = buf;
10019 char *key = NULL;
10020 char *val = NULL;
10021 char line[256] = { '\0' };
10022
10023 while (ptr = get_line_from_str_buf(ptr, line)) {
10024 if (strstr(line, "Frequency")) continue;
10025
10026 key = strtok(line, ":");
10027 val = strtok(NULL, " ");
10028 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10029
10030 if (!strcmp(key, "noise")) {
10031 sscanf(val, "%d", &stats->ch_noise);
10032 if (stats->ch_noise == 0) {
10033 // Workaround for missing noise information.
10034 // Assume -95 for 2.4G and -103 for 5G
10035 if (radioIndex == 0) stats->ch_noise = -95;
10036 if (radioIndex == 1) stats->ch_noise = -103;
10037 }
10038 }
10039 else if (!strcmp(key, "channel active time")) {
10040 sscanf(val, "%llu", &stats->ch_utilization_total);
10041 }
10042 else if (!strcmp(key, "channel busy time")) {
10043 sscanf(val, "%llu", &stats->ch_utilization_busy);
10044 }
10045 else if (!strcmp(key, "channel receive time")) {
10046 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10047 }
10048 else if (!strcmp(key, "channel transmit time")) {
10049 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10050 }
10051 };
10052
10053 return 0;
10054}
10055
10056INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10057{
10058 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10059#ifdef HAL_NETLINK_IMPL
10060 Netlink nl;
10061 wifi_channelStats_t_loc local[array_size];
10062 char if_name[10];
10063
10064 local[0].array_size = array_size;
10065
10066 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
10067
10068 nl.id = initSock80211(&nl);
10069
10070 if (nl.id < 0) {
10071 fprintf(stderr, "Error initializing netlink \n");
10072 return -1;
10073 }
10074
10075 struct nl_msg* msg = nlmsg_alloc();
10076
10077 if (!msg) {
10078 fprintf(stderr, "Failed to allocate netlink message.\n");
10079 nlfree(&nl);
10080 return -2;
10081 }
10082
10083 genlmsg_put(msg,
10084 NL_AUTO_PORT,
10085 NL_AUTO_SEQ,
10086 nl.id,
10087 0,
10088 NLM_F_DUMP,
10089 NL80211_CMD_GET_SURVEY,
10090 0);
10091
10092 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10093 nl_send_auto(nl.socket, msg);
10094 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10095 nl_recvmsgs(nl.socket, nl.cb);
10096 nlmsg_free(msg);
10097 nlfree(&nl);
10098 //Copying the Values
10099 for(int i=0;i<array_size;i++)
10100 {
10101 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10102 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10103 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10104 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10105 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10106 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10107 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10108 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10109 }
10110#else
10111 ULONG channel = 0;
10112 int i;
10113 int number_of_channels = array_size;
10114 char buf[512];
10115 INT ret;
10116 wifi_channelStats_t tmp_stats;
10117
10118 if (number_of_channels == 0) {
10119 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10120 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10121 return RETURN_ERR;
10122 }
10123 number_of_channels = 1;
10124 input_output_channelStats_array[0].ch_number = channel;
10125 }
10126
10127 for (i = 0; i < number_of_channels; i++) {
10128
10129 input_output_channelStats_array[i].ch_noise = 0;
10130 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10131 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10132 input_output_channelStats_array[i].ch_utilization_busy = 0;
10133 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10134 input_output_channelStats_array[i].ch_utilization_total = 0;
10135
10136 memset(buf, 0, sizeof(buf));
10137 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10138 return RETURN_ERR;
10139 }
10140 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10141 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10142 return RETURN_ERR;
10143 }
10144
10145 // XXX: fake missing 'self' counter which is not available in iw survey output
10146 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10147 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10148
10149 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10150 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10151 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10152 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10153 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10154
10155 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",
10156 __func__,
10157 input_output_channelStats_array[i].ch_number,
10158 input_output_channelStats_array[i].ch_noise,
10159 input_output_channelStats_array[i].ch_utilization_total,
10160 input_output_channelStats_array[i].ch_utilization_busy,
10161 input_output_channelStats_array[i].ch_utilization_busy_rx,
10162 input_output_channelStats_array[i].ch_utilization_busy_tx,
10163 input_output_channelStats_array[i].ch_utilization_busy_self,
10164 input_output_channelStats_array[i].ch_utilization_busy_ext);
10165 }
10166#endif
10167 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10168 return RETURN_OK;
10169}
10170#define HAL_NETLINK_IMPL
10171
10172/* Hostapd events */
10173
10174#ifndef container_of
10175#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10176#define container_of(ptr, type, member) \
10177 ((type *)((char *)ptr - offset_of(type, member)))
10178#endif /* container_of */
10179
10180struct ctrl {
10181 char sockpath[128];
10182 char sockdir[128];
10183 char bss[IFNAMSIZ];
10184 char reply[4096];
10185 int ssid_index;
10186 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10187 void (*overrun)(struct ctrl *ctrl);
10188 struct wpa_ctrl *wpa;
10189 unsigned int ovfl;
10190 size_t reply_len;
10191 int initialized;
10192 ev_timer retry;
10193 ev_timer watchdog;
10194 ev_stat stat;
10195 ev_io io;
10196};
10197static wifi_newApAssociatedDevice_callback clients_connect_cb;
10198static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10199static struct ctrl wpa_ctrl[MAX_APS];
10200static int initialized;
10201
10202static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10203{
10204 char cbuf[256] = {};
10205 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10206 struct cmsghdr *cmsg;
10207 unsigned int ovfl = ctrl->ovfl;
10208 unsigned int drop;
10209
10210 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10211 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10212 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10213 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10214
10215 drop = ovfl - ctrl->ovfl;
10216 ctrl->ovfl = ovfl;
10217
10218 return drop;
10219}
10220
10221static void ctrl_close(struct ctrl *ctrl)
10222{
10223 if (ctrl->io.cb)
10224 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10225 if (ctrl->retry.cb)
10226 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10227 if (!ctrl->wpa)
10228 return;
10229
10230 wpa_ctrl_detach(ctrl->wpa);
10231 wpa_ctrl_close(ctrl->wpa);
10232 ctrl->wpa = NULL;
10233 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10234}
10235
10236static void ctrl_process(struct ctrl *ctrl)
10237{
10238 const char *str;
10239 int drops;
10240 int level;
10241 int err;
10242
10243 /* Example events:
10244 *
10245 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10246 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10247 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10248 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10249 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10250 */
10251 if (!(str = index(ctrl->reply, '>')))
10252 return;
10253 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10254 return;
10255
10256 str++;
10257
10258 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10259 if (!(str = index(ctrl->reply, ' ')))
10260 return;
10261 wifi_associated_dev_t sta;
10262 memset(&sta, 0, sizeof(sta));
10263
10264 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10265 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10266 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10267
10268 sta.cli_Active=true;
10269
10270 (clients_connect_cb)(ctrl->ssid_index, &sta);
10271 goto handled;
10272 }
10273
10274 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10275 if (!(str = index(ctrl->reply, ' ')))
10276 return;
10277
10278 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10279 goto handled;
10280 }
10281
10282 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10283 printf("CTRL_WPA: handle TERMINATING event\n");
10284 goto retry;
10285 }
10286
10287 if (strncmp("AP-DISABLED", str, 11) == 0) {
10288 printf("CTRL_WPA: handle AP-DISABLED\n");
10289 goto retry;
10290 }
10291
10292 printf("Event not supported!!\n");
10293
10294handled:
10295
10296 if ((drops = ctrl_get_drops(ctrl))) {
10297 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10298 if (ctrl->overrun)
10299 ctrl->overrun(ctrl);
10300 }
10301
10302 return;
10303
10304retry:
10305 printf("WPA_CTRL: closing\n");
10306 ctrl_close(ctrl);
10307 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10308 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10309}
10310
10311static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10312{
10313 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10314 int err;
10315
10316 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10317 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10318 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10319 ctrl->reply[ctrl->reply_len] = 0;
10320 if (err < 0) {
10321 if (errno == EAGAIN || errno == EWOULDBLOCK)
10322 return;
10323 ctrl_close(ctrl);
10324 ev_timer_again(EV_A_ &ctrl->retry);
10325 return;
10326 }
10327
10328 ctrl_process(ctrl);
10329}
10330
10331static int ctrl_open(struct ctrl *ctrl)
10332{
10333 int fd;
10334
10335 if (ctrl->wpa)
10336 return 0;
10337
10338 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10339 if (!ctrl->wpa)
10340 goto err;
10341
10342 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10343 goto err_close;
10344
10345 fd = wpa_ctrl_get_fd(ctrl->wpa);
10346 if (fd < 0)
10347 goto err_detach;
10348
10349 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10350 goto err_detach;
10351
10352 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10353 ev_io_start(EV_DEFAULT_ &ctrl->io);
10354
10355 return 0;
10356
10357err_detach:
10358 wpa_ctrl_detach(ctrl->wpa);
10359err_close:
10360 wpa_ctrl_close(ctrl->wpa);
10361err:
10362 ctrl->wpa = NULL;
10363 return -1;
10364}
10365
10366static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10367{
10368 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10369
10370 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10371 ctrl_open(ctrl);
10372}
10373
10374static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10375{
10376 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10377
10378 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10379 if (ctrl_open(ctrl) == 0) {
10380 printf("WPA_CTRL: retry successful\n");
10381 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10382 }
10383}
10384
10385int ctrl_enable(struct ctrl *ctrl)
10386{
10387 if (ctrl->wpa)
10388 return 0;
10389
10390 if (!ctrl->stat.cb) {
10391 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10392 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10393 }
10394
10395 if (!ctrl->retry.cb) {
10396 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10397 }
10398
10399 return ctrl_open(ctrl);
10400}
10401
10402static void
10403ctrl_msg_cb(char *buf, size_t len)
10404{
10405 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10406
10407 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10408 ctrl_process(ctrl);
10409}
10410
10411static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10412{
10413 int err;
10414
10415 if (!ctrl->wpa)
10416 return -1;
10417 if (*reply_len < 2)
10418 return -1;
10419
10420 (*reply_len)--;
10421 ctrl->reply_len = sizeof(ctrl->reply);
10422 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10423 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10424 if (err < 0)
10425 return err;
10426
10427 if (ctrl->reply_len > *reply_len)
10428 ctrl->reply_len = *reply_len;
10429
10430 *reply_len = ctrl->reply_len;
10431 memcpy(reply, ctrl->reply, *reply_len);
10432 reply[*reply_len - 1] = 0;
10433 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10434 return 0;
10435}
10436
10437static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10438{
10439 const char *pong = "PONG";
10440 const char *ping = "PING";
10441 char reply[1024];
10442 size_t len = sizeof(reply);
10443 int err;
10444 ULONG s, snum;
10445 INT ret;
10446 BOOL status;
10447
10448 printf("WPA_CTRL: watchdog cb\n");
10449
10450 ret = wifi_getSSIDNumberOfEntries(&snum);
10451 if (ret != RETURN_OK) {
10452 printf("%s: failed to get SSID count", __func__);
10453 return;
10454 }
10455
10456 if (snum > MAX_APS) {
10457 printf("more ssid than supported! %lu\n", snum);
10458 return;
10459 }
10460
10461 for (s = 0; s < snum; s++) {
10462 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010463 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010464 continue;
10465 }
10466 if (status == false) continue;
10467
10468 memset(reply, 0, sizeof(reply));
10469 len = sizeof(reply);
10470 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10471 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10472 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10473 continue;
10474
10475 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10476 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010477 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010478 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10479 }
10480}
10481
10482static int init_wpa()
10483{
10484 int ret = 0, i = 0;
10485 ULONG s, snum;
10486
10487 ret = wifi_getSSIDNumberOfEntries(&snum);
10488 if (ret != RETURN_OK) {
10489 printf("%s: failed to get SSID count", __func__);
10490 return RETURN_ERR;
10491 }
10492
10493 if (snum > MAX_APS) {
10494 printf("more ssid than supported! %lu\n", snum);
10495 return RETURN_ERR;
10496 }
10497
10498 for (s = 0; s < snum; s++) {
10499 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10500 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10501 wpa_ctrl[s].ssid_index = s;
10502 ctrl_enable(&wpa_ctrl[s]);
10503 }
10504
10505 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10506 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10507
10508 initialized = 1;
10509 printf("WPA_CTRL: initialized\n");
10510
10511 return RETURN_OK;
10512}
10513
10514void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10515{
10516 clients_connect_cb = callback_proc;
10517 if (!initialized)
10518 init_wpa();
10519}
10520
10521void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10522{
10523 clients_disconnect_cb = callback_proc;
10524 if (!initialized)
10525 init_wpa();
10526}
10527
10528INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10529{
10530 // TODO Implement me!
10531 return RETURN_ERR;
10532}
10533
10534INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10535{
10536 // TODO Implement me!
10537 return RETURN_ERR;
10538}
10539
10540INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10541{
10542 int i;
10543 char cmd[256];
10544 char channel_numbers_buf[256];
10545 char dfs_state_buf[256];
10546 char line[256];
10547 const char *ptr;
10548
10549 memset(cmd, 0, sizeof(cmd));
10550 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10551 memset(line, 0, sizeof(line));
10552 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10553 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10554
10555 if (radioIndex == 0) { // 2.4G - all allowed
10556 if (outputMapSize < 11) {
10557 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10558 return RETURN_ERR;
10559 }
10560
10561 for (i = 0; i < 11; i++) {
10562 outputMap[i].ch_number = i + 1;
10563 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10564 }
10565
10566 return RETURN_OK;
10567 }
10568
10569 if (radioIndex == 1) { // 5G
10570// Example output of iw list:
10571//
10572// Frequencies:
10573// * 5180 MHz [36] (17.0 dBm)
10574// * 5200 MHz [40] (17.0 dBm)
10575// * 5220 MHz [44] (17.0 dBm)
10576// * 5240 MHz [48] (17.0 dBm)
10577// * 5260 MHz [52] (23.0 dBm) (radar detection)
10578// DFS state: usable (for 78930 sec)
10579// DFS CAC time: 60000 ms
10580// * 5280 MHz [56] (23.0 dBm) (radar detection)
10581// DFS state: usable (for 78930 sec)
10582// DFS CAC time: 60000 ms
10583// * 5300 MHz [60] (23.0 dBm) (radar detection)
10584// DFS state: usable (for 78930 sec)
10585// DFS CAC time: 60000 ms
10586// * 5320 MHz [64] (23.0 dBm) (radar detection)
10587// DFS state: usable (for 78930 sec)
10588// DFS CAC time: 60000 ms
10589// * 5500 MHz [100] (disabled)
10590// * 5520 MHz [104] (disabled)
10591// * 5540 MHz [108] (disabled)
10592// * 5560 MHz [112] (disabled)
10593//
10594// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10595 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10596 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10597 return RETURN_ERR;
10598 }
10599
10600 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10601 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10602 return RETURN_ERR;
10603 }
10604
10605 ptr = channel_numbers_buf;
10606 i = 0;
10607 while (ptr = get_line_from_str_buf(ptr, line)) {
10608 if (i >= outputMapSize) {
10609 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10610 return RETURN_ERR;
10611 }
10612 sscanf(line, "%d", &outputMap[i].ch_number);
10613
10614 memset(cmd, 0, sizeof(cmd));
10615 // Below command should fetch string for DFS state (usable, available or unavailable)
10616 // Example line: "DFS state: usable (for 78930 sec)"
10617 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) {
10618 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10619 return RETURN_ERR;
10620 }
10621
10622 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10623 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10624 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10625 return RETURN_ERR;
10626 }
10627
10628 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10629
10630 if (!strcmp(dfs_state_buf, "usable")) {
10631 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10632 } else if (!strcmp(dfs_state_buf, "available")) {
10633 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10634 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10635 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10636 } else {
10637 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10638 }
10639 i++;
10640 }
10641
10642 return RETURN_OK;
10643 }
10644
10645 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10646 return RETURN_ERR;
10647}
10648
10649INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10650{
10651 // TODO Implement me!
10652 return RETURN_ERR;
10653}
10654
10655INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10656{
10657 return RETURN_OK;
10658}
10659
10660INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10661{
10662 // TODO Implement me!
10663 return RETURN_ERR;
10664}
10665
10666INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10667{
10668 // TODO API refrence Implementaion is present on RPI hal
10669 return RETURN_ERR;
10670}
10671
10672INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10673{
developera5005b62022-09-13 15:43:35 +080010674 char cmd[128]={'\0'};
10675 char buf[128]={'\0'};
10676 char *support;
10677 int maximum_tx = 0, current_tx = 0;
10678
10679 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10680 if(txpwr_pcntg == NULL)
10681 return RETURN_ERR;
10682
10683 // Get the maximum tx power of the device
10684 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10685 _syscmd(cmd, buf, sizeof(buf));
10686 maximum_tx = strtol(buf, NULL, 10);
10687
10688 // Get the current tx power
10689 memset(cmd, 0, sizeof(cmd));
10690 memset(buf, 0, sizeof(buf));
10691 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10692 _syscmd(cmd, buf, sizeof(buf));
10693 current_tx = strtol(buf, NULL, 10);
10694
10695 // Get the power supported list and find the current power percentage in supported list
10696 memset(buf, 0, sizeof(buf));
10697 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10698 support = strtok(buf, ",");
10699 while(true)
10700 {
10701 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
developer033b37b2022-10-18 11:27:46 +080010702 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010703 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010704 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010705 }
10706 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10707 if (tmp == current_tx) {
10708 *txpwr_pcntg = strtol(support, NULL, 10);
10709 break;
10710 }
10711 support = strtok(NULL, ",");
10712 }
10713 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010714 return RETURN_OK;
10715}
10716
10717INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10718{
developer58599c22022-09-13 16:40:34 +080010719 // TODO precac feature.
10720 struct params params = {0};
10721 char config_file[128] = {0};
10722
10723 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10724
10725 params.name = "enable_background_radar";
10726 params.value = enable?"1":"0";
10727 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10728 wifi_hostapdWrite(config_file, &params, 1);
10729 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10730
10731 /* TODO precac feature */
10732
10733 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10734 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010735}
10736
10737INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10738{
developer58599c22022-09-13 16:40:34 +080010739 char config_file[128] = {0};
10740 char buf[64] = {0};
10741
10742 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10743 if (NULL == enable || NULL == precac)
10744 return RETURN_ERR;
10745
10746 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10747 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10748 if (strncmp(enable, "1", 1) == 0)
10749 *enable = true;
10750 else
10751 *enable = false;
10752
10753 /* TODO precac feature */
10754
10755 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10756 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010757}
10758
10759INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10760{
developer58599c22022-09-13 16:40:34 +080010761 *supported = TRUE;
10762 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010763}
10764
developer3e6b1692022-09-30 18:04:05 +080010765INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10766{
10767 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10768 struct params params = {0};
10769 char config_file[64] = {0};
10770 char buf[64] = {0};
10771 unsigned int set_mu_type = 0;
10772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10773
10774 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10775 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10776
10777 if (strlen(buf) > 0)
10778 set_mu_type = strtol(buf, NULL, 10);
10779
10780 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10781 set_mu_type &= ~0x05; // unset bit 0, 2
10782 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10783 set_mu_type |= 0x01;
10784 set_mu_type &= ~0x04;
10785 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10786 set_mu_type &= ~0x01;
10787 set_mu_type |= 0x04;
10788 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10789 set_mu_type |= 0x05; // set bit 0, 2
10790 }
10791
10792 params.name = "hemu_onoff";
10793 sprintf(buf, "%u", set_mu_type);
10794 params.value = buf;
10795 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10796 wifi_hostapdWrite(config_file, &params, 1);
10797 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10798
10799 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10800 return RETURN_OK;
10801}
10802
10803INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10804{
10805 struct params params={0};
10806 char config_file[64] = {0};
10807 char buf[64] = {0};
10808 unsigned int get_mu_type = 0;
10809
10810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10811
10812 if (mu_type == NULL)
10813 return RETURN_ERR;
10814
10815 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10816 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10817 get_mu_type = strtol(buf, NULL, 10);
10818
10819 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10820 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10821 else if (get_mu_type & 0x04)
10822 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10823 else if (get_mu_type & 0x01)
10824 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10825 else
10826 *mu_type = WIFI_DL_MU_TYPE_NONE;
10827
10828 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10829 return RETURN_OK;
10830}
10831
10832INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10833{
10834 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10835 struct params params={0};
10836 char config_file[64] = {0};
10837 char buf[64] = {0};
10838 unsigned int set_mu_type = 0;
10839 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10840
10841 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10842 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10843
10844 if (strlen(buf) > 0)
10845 set_mu_type = strtol(buf, NULL, 10);
10846
10847 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10848 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10849 set_mu_type &= ~0x0a;
10850 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10851 set_mu_type |= 0x02;
10852 set_mu_type &= ~0x08;
10853 }
10854
10855 params.name = "hemu_onoff";
10856 sprintf(buf, "%u", set_mu_type);
10857 params.value = buf;
10858 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10859 wifi_hostapdWrite(config_file, &params, 1);
10860 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10861
10862 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10863 return RETURN_OK;
10864}
10865
10866INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10867{
10868 struct params params={0};
10869 char config_file[64] = {0};
10870 char buf[64] = {0};
10871 unsigned int get_mu_type = 0;
10872
10873 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10874
10875 if (mu_type == NULL)
10876 return RETURN_ERR;
10877
10878 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10879 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10880
10881 get_mu_type = strtol(buf, NULL, 10);
10882 if (get_mu_type & 0x02)
10883 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10884 else
10885 *mu_type = WIFI_DL_MU_TYPE_NONE;
10886
10887 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10888 return RETURN_OK;
10889}
10890
10891
developer454b9462022-09-13 15:29:16 +080010892INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10893{
10894 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080010895 char buf[256] = {0};
10896 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080010897 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080010898 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080010899 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080010900 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080010901
10902 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10903
developer254882b2022-09-30 17:12:31 +080010904 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080010905 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10906 return RETURN_ERR;
10907 }
developer454b9462022-09-13 15:29:16 +080010908
developer254882b2022-09-30 17:12:31 +080010909 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080010910 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080010911
developer254882b2022-09-30 17:12:31 +080010912 // Hostapd are not supported HE mode GI 1600, 3200 ns.
10913 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080010914 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080010915 _syscmd(cmd, buf, sizeof(buf));
10916 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
10917 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
10918 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080010919 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
developer254882b2022-09-30 17:12:31 +080010920 _syscmd(cmd, buf, sizeof(buf));
10921 }
10922 if (band == band_5) {
10923 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
10924 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080010925 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
developer254882b2022-09-30 17:12:31 +080010926 _syscmd(cmd, buf, sizeof(buf));
10927 }
10928 }
10929 }
10930 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080010931
developer254882b2022-09-30 17:12:31 +080010932 if (guard_interval == wifi_guard_interval_400)
10933 strcpy(GI, "0.4");
10934 else if (guard_interval == wifi_guard_interval_800)
10935 strcpy(GI, "0.8");
10936 else if (guard_interval == wifi_guard_interval_1600)
10937 strcpy(GI, "1.6");
10938 else if (guard_interval == wifi_guard_interval_3200)
10939 strcpy(GI, "3.2");
10940 else if (guard_interval == wifi_guard_interval_auto)
10941 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080010942 // Record GI for get GI function
10943 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10944 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080010945 if (f == NULL)
10946 return RETURN_ERR;
10947 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080010948 fclose(f);
10949 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10950 return RETURN_OK;
10951}
10952
10953INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10954{
10955 char buf[32] = {0};
10956 char cmd[64] = {0};
10957
10958 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10959
10960 if (guard_interval == NULL)
10961 return RETURN_ERR;
10962
10963 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10964 _syscmd(cmd, buf, sizeof(buf));
10965
10966 if (strncmp(buf, "0.4", 3) == 0)
10967 *guard_interval = wifi_guard_interval_400;
10968 else if (strncmp(buf, "0.8", 3) == 0)
10969 *guard_interval = wifi_guard_interval_800;
10970 else if (strncmp(buf, "1.6", 3) == 0)
10971 *guard_interval = wifi_guard_interval_1600;
10972 else if (strncmp(buf, "3.2", 3) == 0)
10973 *guard_interval = wifi_guard_interval_3200;
10974 else
10975 *guard_interval = wifi_guard_interval_auto;
10976
10977 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10978 return RETURN_OK;
10979}
10980
developer3cc61d12022-09-13 16:36:05 +080010981INT wifi_setBSSColor(INT radio_index, UCHAR color)
10982{
10983 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10984 struct params params = {0};
10985 char config_file[128] = {0};
10986 char bss_color[4] ={0};
10987
10988 params.name = "he_bss_color";
10989 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10990 params.value = bss_color;
10991 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10992 wifi_hostapdWrite(config_file, &params, 1);
10993 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10994
10995 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10996 return RETURN_OK;
10997}
10998
10999INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11000{
11001 char config_file[128] = {0};
11002 char buf[64] = {0};
11003 char temp_output[128] = {'\0'};
11004
11005 wifi_dbg_printf("\nFunc=%s\n", __func__);
11006 if (NULL == color)
11007 return RETURN_ERR;
11008
11009 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11010 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11011
11012 if(strlen(buf) > 0) {
11013 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11014 } else {
11015 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11016 }
11017
11018 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11019 wifi_dbg_printf("\noutput_string=%s\n", color);
11020
11021 return RETURN_OK;
11022}
11023
developer06a01d92022-09-07 16:32:39 +080011024/* multi-psk support */
11025INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11026{
11027 char cmd[256];
11028
11029 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11030 AP_PREFIX,
11031 apIndex,
11032 mac[0],
11033 mac[1],
11034 mac[2],
11035 mac[3],
11036 mac[4],
11037 mac[5]
11038 );
11039 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11040 _syscmd(cmd, key->wifi_keyId, 64);
11041
11042
11043 return RETURN_OK;
11044}
11045
11046INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11047{
11048 FILE *fd = NULL;
11049 char fname[100];
11050 char cmd[128] = {0};
11051 char out[64] = {0};
11052 wifi_key_multi_psk_t * key = NULL;
11053 if(keysNumber < 0)
11054 return RETURN_ERR;
11055
11056 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11057 fd = fopen(fname, "w");
11058 if (!fd) {
11059 return RETURN_ERR;
11060 }
11061 key= (wifi_key_multi_psk_t *) keys;
11062 for(int i=0; i<keysNumber; ++i, key++) {
11063 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11064 }
11065 fclose(fd);
11066
11067 //reload file
11068 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
11069 _syscmd(cmd, out, 64);
11070 return RETURN_OK;
11071}
11072
11073INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11074{
11075 FILE *fd = NULL;
11076 char fname[100];
11077 char * line = NULL;
11078 char * pos = NULL;
11079 size_t len = 0;
11080 ssize_t read = 0;
11081 INT ret = RETURN_OK;
11082 wifi_key_multi_psk_t *keys_it = NULL;
11083
11084 if (keysNumber < 1) {
11085 return RETURN_ERR;
11086 }
11087
11088 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
11089 fd = fopen(fname, "r");
11090 if (!fd) {
11091 return RETURN_ERR;
11092 }
11093
11094 if (keys == NULL) {
11095 ret = RETURN_ERR;
11096 goto close;
11097 }
11098
11099 keys_it = keys;
11100 while ((read = getline(&line, &len, fd)) != -1) {
11101 //Strip trailing new line if present
11102 if (read > 0 && line[read-1] == '\n') {
11103 line[read-1] = '\0';
11104 }
11105
11106 if(strcmp(line,"keyid=")) {
11107 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11108 if (!(pos = index(line, ' '))) {
11109 ret = RETURN_ERR;
11110 goto close;
11111 }
11112 pos++;
11113 //Here should be 00:00:00:00:00:00
11114 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11115 printf("Not supported MAC: %s\n", pos);
11116 }
11117 if (!(pos = index(pos, ' '))) {
11118 ret = RETURN_ERR;
11119 goto close;
11120 }
11121 pos++;
11122
11123 //The rest is PSK
11124 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11125 keys_it++;
11126
11127 if(--keysNumber <= 0)
11128 break;
11129 }
11130 }
11131
11132close:
11133 free(line);
11134 fclose(fd);
11135 return ret;
11136}
11137/* end of multi-psk support */
11138
11139INT wifi_setNeighborReports(UINT apIndex,
11140 UINT numNeighborReports,
11141 wifi_NeighborReport_t *neighborReports)
11142{
11143 char cmd[256] = { 0 };
11144 char hex_bssid[13] = { 0 };
11145 char bssid[18] = { 0 };
11146 char nr[256] = { 0 };
11147 char ssid[256];
11148 char hex_ssid[256];
11149 INT ret;
11150
11151 /*rmeove all neighbors*/
11152 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
11153 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);
11154 system(cmd);
11155
11156 for(unsigned int i = 0; i < numNeighborReports; i++)
11157 {
11158 memset(ssid, 0, sizeof(ssid));
11159 ret = wifi_getSSIDName(apIndex, ssid);
11160 if (ret != RETURN_OK)
11161 return RETURN_ERR;
11162
11163 memset(hex_ssid, 0, sizeof(hex_ssid));
11164 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11165 sprintf(hex_ssid + k,"%02x", ssid[j]);
11166
11167 snprintf(hex_bssid, sizeof(hex_bssid),
11168 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11169 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11170 snprintf(bssid, sizeof(bssid),
11171 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11172 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11173
11174 snprintf(nr, sizeof(nr),
11175 "%s" // bssid
11176 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11177 "%02hhx" // operclass
11178 "%02hhx" // channel
11179 "%02hhx", // phy_mode
11180 hex_bssid,
11181 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11182 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11183 neighborReports[i].opClass,
11184 neighborReports[i].channel,
11185 neighborReports[i].phyTable);
11186
11187 snprintf(cmd, sizeof(cmd),
11188 "hostapd_cli set_neighbor "
11189 "%s " // bssid
11190 "ssid=%s " // ssid
11191 "nr=%s " // nr
11192 "-i %s%d",
11193 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
11194
11195 if (WEXITSTATUS(system(cmd)) != 0)
11196 {
11197 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11198 }
11199 }
11200
11201 return RETURN_OK;
11202}
11203
11204INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11205{
11206 return RETURN_OK;
11207}
11208
11209#ifdef _WIFI_HAL_TEST_
11210int main(int argc,char **argv)
11211{
11212 int index;
11213 INT ret=0;
11214 char buf[1024]="";
11215
11216 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11217 if(argc<3)
11218 {
11219 if(argc==2)
11220 {
11221 if(!strcmp(argv[1], "init"))
11222 return wifi_init();
11223 if(!strcmp(argv[1], "reset"))
11224 return wifi_reset();
11225 if(!strcmp(argv[1], "wifi_getHalVersion"))
11226 {
11227 char buffer[64];
11228 if(wifi_getHalVersion(buffer)==RETURN_OK)
11229 printf("Version: %s\n", buffer);
11230 else
11231 printf("Error in wifi_getHalVersion\n");
11232 return RETURN_OK;
11233 }
11234 }
11235 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11236 exit(-1);
11237 }
11238
11239 index = atoi(argv[2]);
11240 if(strstr(argv[1], "wifi_getApName")!=NULL)
11241 {
11242 wifi_getApName(index,buf);
11243 printf("Ap name is %s \n",buf);
11244 return 0;
11245 }
11246 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11247 {
11248 BOOL b = FALSE;
11249 BOOL *output_bool = &b;
11250 wifi_getRadioAutoChannelEnable(index,output_bool);
11251 printf("Channel enabled = %d \n",b);
11252 return 0;
11253 }
11254 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11255 {
11256 wifi_getApWpaEncryptionMode(index,buf);
11257 printf("encryption enabled = %s\n",buf);
11258 return 0;
11259 }
11260 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11261 {
11262 BOOL b = FALSE;
11263 BOOL *output_bool = &b;
11264 wifi_getApSsidAdvertisementEnable(index,output_bool);
11265 printf("advertisment enabled = %d\n",b);
11266 return 0;
11267 }
11268 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11269 {
11270 if(argc <= 3 )
11271 {
11272 printf("Insufficient arguments \n");
11273 exit(-1);
11274 }
11275
11276 char sta[20] = {'\0'};
11277 ULLONG handle= 0;
11278 strcpy(sta,argv[3]);
11279 mac_address_t st;
11280 mac_addr_aton(st,sta);
11281
11282 wifi_associated_dev_tid_stats_t tid_stats;
11283 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11284 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11285 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);
11286 }
11287
11288 if(strstr(argv[1], "getApEnable")!=NULL) {
11289 BOOL enable;
11290 ret=wifi_getApEnable(index, &enable);
11291 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11292 }
11293 else if(strstr(argv[1], "setApEnable")!=NULL) {
11294 BOOL enable = atoi(argv[3]);
11295 ret=wifi_setApEnable(index, enable);
11296 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11297 }
11298 else if(strstr(argv[1], "getApStatus")!=NULL) {
11299 char status[64];
11300 ret=wifi_getApStatus(index, status);
11301 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11302 }
11303 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11304 {
11305 wifi_getSSIDNameStatus(index,buf);
11306 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11307 return 0;
11308 }
11309 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11310 wifi_ssidTrafficStats2_t stats={0};
11311 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11312 printf("%s %d: returns %d\n", argv[1], index, ret);
11313 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11314 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11315 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11316 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11317 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11318 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11319 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11320 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11321 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11322 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11323 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11324 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11325 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11326 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11327 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11328 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11329 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11330 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11331 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11332 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11333 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11334 }
11335 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11336 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11337 UINT array_size=0;
11338 UINT i=0;
11339 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11340 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11341 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11342 printf(" neighbor %d:\n", i);
11343 printf(" ap_SSID =%s\n", pt->ap_SSID);
11344 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11345 printf(" ap_Mode =%s\n", pt->ap_Mode);
11346 printf(" ap_Channel =%d\n", pt->ap_Channel);
11347 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11348 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11349 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11350 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11351 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11352 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11353 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11354 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11355 printf(" ap_Noise =%d\n", pt->ap_Noise);
11356 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11357 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11358 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11359 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11360 }
11361 if(neighbor_ap_array)
11362 free(neighbor_ap_array); //make sure to free the list
11363 }
11364 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11365 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11366 UINT array_size=0;
11367 UINT i=0;
11368 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11369 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11370 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11371 printf(" associated_dev %d:\n", i);
11372 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11373 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11374 printf(" cli_SNR =%d\n", pt->cli_SNR);
11375 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11376 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11377 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11378 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11379 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11380 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11381 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11382 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11383 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11384 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11385 }
11386 if(associated_dev_array)
11387 free(associated_dev_array); //make sure to free the list
11388 }
11389
11390 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11391 {
11392#define MAX_ARRAY_SIZE 64
11393 int i, array_size;
11394 char *p, *ch_str;
11395 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11396
11397 if(argc != 5)
11398 {
11399 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11400 exit(-1);
11401 }
11402 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11403
11404 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11405 {
11406 strtok_r(ch_str, ",", &p);
11407 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11408 }
11409 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11410 if(!array_size)
11411 array_size=1;//Need to print current channel statistics
11412 for(i=0; i<array_size; i++)
11413 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11414 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11415 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11416 input_output_channelStats_array[i].ch_number,\
11417 input_output_channelStats_array[i].ch_noise,\
11418 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11419 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11420 input_output_channelStats_array[i].ch_utilization_busy,\
11421 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11422 input_output_channelStats_array[i].ch_utilization_total);
11423 }
11424
11425 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11426 {
11427 if(argc <= 3 )
11428 {
11429 printf("Insufficient arguments \n");
11430 exit(-1);
11431 }
11432 char mac_addr[20] = {'\0'};
11433 wifi_device_t output_struct;
11434 int dev_index = atoi(argv[3]);
11435
11436 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11437 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11438 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);
11439 }
11440
11441 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11442 {
11443 if (argc <= 3)
11444 {
11445 printf("Insufficient arguments\n");
11446 exit(-1);
11447 }
11448 char args[256];
11449 wifi_NeighborReport_t *neighborReports;
11450
11451 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11452 if (!neighborReports)
11453 {
11454 printf("Failed to allocate memory");
11455 exit(-1);
11456 }
11457
11458 for (int i = 3; i < argc; ++i)
11459 {
11460 char *val;
11461 int j = 0;
11462 memset(args, 0, sizeof(args));
11463 strncpy(args, argv[i], sizeof(args));
11464 val = strtok(args, ";");
11465 while (val != NULL)
11466 {
11467 if (j == 0)
11468 {
11469 mac_addr_aton(neighborReports[i - 3].bssid, val);
11470 } else if (j == 1)
11471 {
11472 neighborReports[i - 3].info = strtol(val, NULL, 16);
11473 } else if (j == 2)
11474 {
11475 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11476 } else if (j == 3)
11477 {
11478 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11479 } else if (j == 4)
11480 {
11481 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11482 } else {
11483 printf("Insufficient arguments]n\n");
11484 exit(-1);
11485 }
11486 val = strtok(NULL, ";");
11487 j++;
11488 }
11489 }
11490
11491 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11492 if (ret != RETURN_OK)
11493 {
11494 printf("wifi_setNeighborReports ret = %d", ret);
11495 exit(-1);
11496 }
11497 }
11498 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11499 {
11500 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11501 printf("%s.\n", buf);
11502 else
11503 printf("Error returned\n");
11504 }
11505 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11506 {
11507 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11508 printf("%s.\n", buf);
11509 else
11510 printf("Error returned\n");
11511 }
11512 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11513 {
11514 if (argc <= 2)
11515 {
11516 printf("Insufficient arguments\n");
11517 exit(-1);
11518 }
11519 char buf[64]= {'\0'};
11520 wifi_getRadioOperatingChannelBandwidth(index,buf);
11521 printf("Current bandwidth is %s \n",buf);
11522 return 0;
11523 }
11524 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11525 {
11526 if (argc <= 5)
11527 {
11528 printf("Insufficient arguments\n");
11529 exit(-1);
11530 }
11531 UINT channel = atoi(argv[3]);
11532 UINT width = atoi(argv[4]);
11533 UINT beacon = atoi(argv[5]);
11534 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11535 printf("Result = %d", ret);
11536 }
11537
11538 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11539 return 0;
11540}
11541
11542#endif
11543
11544#ifdef WIFI_HAL_VERSION_3
11545
developer1e5aa162022-09-13 16:06:24 +080011546INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11547{
11548 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11549 if (bitMap & WIFI_BITRATE_1MBPS)
11550 strcat(BasicRate, "1,");
11551 if (bitMap & WIFI_BITRATE_2MBPS)
11552 strcat(BasicRate, "2,");
11553 if (bitMap & WIFI_BITRATE_5_5MBPS)
11554 strcat(BasicRate, "5.5,");
11555 if (bitMap & WIFI_BITRATE_6MBPS)
11556 strcat(BasicRate, "6,");
11557 if (bitMap & WIFI_BITRATE_9MBPS)
11558 strcat(BasicRate, "9,");
11559 if (bitMap & WIFI_BITRATE_11MBPS)
11560 strcat(BasicRate, "11,");
11561 if (bitMap & WIFI_BITRATE_12MBPS)
11562 strcat(BasicRate, "12,");
11563 if (bitMap & WIFI_BITRATE_18MBPS)
11564 strcat(BasicRate, "18,");
11565 if (bitMap & WIFI_BITRATE_24MBPS)
11566 strcat(BasicRate, "24,");
11567 if (bitMap & WIFI_BITRATE_36MBPS)
11568 strcat(BasicRate, "36,");
11569 if (bitMap & WIFI_BITRATE_48MBPS)
11570 strcat(BasicRate, "48,");
11571 if (bitMap & WIFI_BITRATE_54MBPS)
11572 strcat(BasicRate, "54,");
11573 if (strlen(BasicRate) != 0) // remove last comma
11574 BasicRate[strlen(BasicRate) - 1] = '\0';
11575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11576 return RETURN_OK;
11577}
11578
11579INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11580{
11581 UINT BitMap = 0;
11582 char *rate;
11583
11584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11585 rate = strtok(BasicRatesList, ",");
11586 while(rate != NULL)
11587 {
11588 if (strcmp(rate, "1") == 0)
11589 BitMap |= WIFI_BITRATE_1MBPS;
11590 else if (strcmp(rate, "2") == 0)
11591 BitMap |= WIFI_BITRATE_2MBPS;
11592 else if (strcmp(rate, "5.5") == 0)
11593 BitMap |= WIFI_BITRATE_5_5MBPS;
11594 else if (strcmp(rate, "6") == 0)
11595 BitMap |= WIFI_BITRATE_6MBPS;
11596 else if (strcmp(rate, "9") == 0)
11597 BitMap |= WIFI_BITRATE_9MBPS;
11598 else if (strcmp(rate, "11") == 0)
11599 BitMap |= WIFI_BITRATE_11MBPS;
11600 else if (strcmp(rate, "12") == 0)
11601 BitMap |= WIFI_BITRATE_12MBPS;
11602 else if (strcmp(rate, "18") == 0)
11603 BitMap |= WIFI_BITRATE_18MBPS;
11604 else if (strcmp(rate, "24") == 0)
11605 BitMap |= WIFI_BITRATE_24MBPS;
11606 else if (strcmp(rate, "36") == 0)
11607 BitMap |= WIFI_BITRATE_36MBPS;
11608 else if (strcmp(rate, "48") == 0)
11609 BitMap |= WIFI_BITRATE_48MBPS;
11610 else if (strcmp(rate, "54") == 0)
11611 BitMap |= WIFI_BITRATE_54MBPS;
11612 rate = strtok(NULL, ",");
11613 }
11614 *basicRateBitMap = BitMap;
11615 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11616 return RETURN_OK;
11617}
11618
11619// 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 +080011620INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11621{
developer1e5aa162022-09-13 16:06:24 +080011622 char buf[128] = {0};
11623 char cmd[128] = {0};
11624 char config_file[64] = {0};
11625 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011626 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011627 wifi_radio_operationParam_t current_param;
11628
11629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11630
11631 multiple_set = TRUE;
11632 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11633 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11634 return RETURN_ERR;
11635 }
11636 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11637 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11638 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11639 return RETURN_ERR;
11640 }
11641 }
developer5884e982022-10-06 10:52:50 +080011642
11643 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11644 bandwidth = 20;
11645 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11646 bandwidth = 40;
11647 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11648 bandwidth = 80;
11649 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11650 bandwidth = 160;
11651 if (operationParam->autoChannelEnabled){
11652 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11653 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11654 return RETURN_ERR;
11655 }
11656 }else{
developer1e5aa162022-09-13 16:06:24 +080011657 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11658 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11659 return RETURN_ERR;
11660 }
11661 }
developer5884e982022-10-06 10:52:50 +080011662
developer1e5aa162022-09-13 16:06:24 +080011663 if (current_param.variant != operationParam->variant) {
11664 // Two different definition bit map, so need to check every bit.
11665 if (operationParam->variant & WIFI_80211_VARIANT_A)
11666 set_mode |= WIFI_MODE_A;
11667 if (operationParam->variant & WIFI_80211_VARIANT_B)
11668 set_mode |= WIFI_MODE_B;
11669 if (operationParam->variant & WIFI_80211_VARIANT_G)
11670 set_mode |= WIFI_MODE_G;
11671 if (operationParam->variant & WIFI_80211_VARIANT_N)
11672 set_mode |= WIFI_MODE_N;
11673 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11674 set_mode |= WIFI_MODE_AC;
11675 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11676 set_mode |= WIFI_MODE_AX;
11677 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11678 memset(buf, 0, sizeof(buf));
11679 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11680 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11681 return RETURN_ERR;
11682 }
11683 }
11684 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11685 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11686 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11687 return RETURN_ERR;
11688 }
11689 }
11690 if (current_param.beaconInterval != operationParam->beaconInterval) {
11691 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11692 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11693 return RETURN_ERR;
11694 }
11695 }
11696 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11697 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11698 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11699 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11700 return RETURN_ERR;
11701 }
11702 }
11703 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11704 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11705 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11706 return RETURN_ERR;
11707 }
11708 }
11709 if (current_param.guardInterval != operationParam->guardInterval) {
11710 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11711 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11712 return RETURN_ERR;
11713 }
11714 }
11715 if (current_param.transmitPower != operationParam->transmitPower) {
11716 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11717 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11718 return RETURN_ERR;
11719 }
11720 }
11721 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11722 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11723 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11724 return RETURN_ERR;
11725 }
11726 }
11727 if (current_param.obssCoex != operationParam->obssCoex) {
11728 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11729 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11730 return RETURN_ERR;
11731 }
11732 }
11733 if (current_param.stbcEnable != operationParam->stbcEnable) {
11734 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11735 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11736 return RETURN_ERR;
11737 }
11738 }
11739 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11740 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11741 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11742 return RETURN_ERR;
11743 }
11744 }
11745
11746 // if enable is true, then restart the radio
11747 wifi_setRadioEnable(index, FALSE);
11748 if (operationParam->enable == TRUE)
11749 wifi_setRadioEnable(index, TRUE);
11750 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11751
developer06a01d92022-09-07 16:32:39 +080011752 return RETURN_OK;
11753}
11754
11755INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11756{
developer1e5aa162022-09-13 16:06:24 +080011757 char band[64] = {0};
11758 char buf[256] = {0};
11759 char config_file[64] = {0};
11760 char cmd[128] = {0};
11761 int ret = RETURN_ERR;
11762 int mode = 0;
11763 ULONG channel = 0;
11764 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011765
11766 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11767 printf("Entering %s index = %d\n", __func__, (int)index);
11768
developer1e5aa162022-09-13 16:06:24 +080011769 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11770 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11771 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011772 {
developer1e5aa162022-09-13 16:06:24 +080011773 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011774 return RETURN_ERR;
11775 }
11776 operationParam->enable = enabled;
11777
11778 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011779 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011780 {
developer1e5aa162022-09-13 16:06:24 +080011781 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011782 return RETURN_ERR;
11783 }
11784
11785 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011786 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011787 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011788 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011789 else if (!strcmp(band, "6GHz"))
11790 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011791 else
11792 {
developer1e5aa162022-09-13 16:06:24 +080011793 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011794 band);
11795 }
11796
developer1e5aa162022-09-13 16:06:24 +080011797 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11798 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11799 operationParam->channel = 0;
11800 operationParam->autoChannelEnabled = TRUE;
11801 } else {
11802 operationParam->channel = strtol(buf, NULL, 10);
11803 operationParam->autoChannelEnabled = FALSE;
11804 }
11805
developer06a01d92022-09-07 16:32:39 +080011806 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011807 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11808 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11809 return RETURN_ERR;
11810 }
developer06a01d92022-09-07 16:32:39 +080011811 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11812 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11813 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011814 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11815 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011816 else
11817 {
developer1e5aa162022-09-13 16:06:24 +080011818 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11819 return false;
developer06a01d92022-09-07 16:32:39 +080011820 }
11821
developer1e5aa162022-09-13 16:06:24 +080011822 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11823 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11824 return RETURN_ERR;
11825 }
11826 // Two different definition bit map, so need to check every bit.
11827 if (mode & WIFI_MODE_A)
11828 operationParam->variant |= WIFI_80211_VARIANT_A;
11829 if (mode & WIFI_MODE_B)
11830 operationParam->variant |= WIFI_80211_VARIANT_B;
11831 if (mode & WIFI_MODE_G)
11832 operationParam->variant |= WIFI_80211_VARIANT_G;
11833 if (mode & WIFI_MODE_N)
11834 operationParam->variant |= WIFI_80211_VARIANT_N;
11835 if (mode & WIFI_MODE_AC)
11836 operationParam->variant |= WIFI_80211_VARIANT_AC;
11837 if (mode & WIFI_MODE_AX)
11838 operationParam->variant |= WIFI_80211_VARIANT_AX;
11839 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11840 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11841 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011842 }
developer1e5aa162022-09-13 16:06:24 +080011843 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11844 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11845 return RETURN_ERR;
11846 }
11847 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11848 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11849 return RETURN_ERR;
11850 }
developer06a01d92022-09-07 16:32:39 +080011851
developer1e5aa162022-09-13 16:06:24 +080011852 memset(buf, 0, sizeof(buf));
11853 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11854 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11855 return RETURN_ERR;
11856 }
11857 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11858
11859 memset(buf, 0, sizeof(buf));
11860 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11861 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11862 return RETURN_ERR;
11863 }
11864 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11865
11866 memset(buf, 0, sizeof(buf));
11867 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11868 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11869
11870 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11871 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11872 return RETURN_ERR;
11873 }
11874 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11875 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11876 return RETURN_ERR;
11877 }
11878
11879 memset(buf, 0, sizeof(buf));
11880 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11881 if (strcmp(buf, "-1") == 0) {
11882 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11883 operationParam->ctsProtection = FALSE;
11884 } else {
11885 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11886 operationParam->ctsProtection = TRUE;
11887 }
11888
11889 memset(buf, 0, sizeof(buf));
11890 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11891 if (strcmp(buf, "0") == 0)
11892 operationParam->obssCoex = FALSE;
11893 else
11894 operationParam->obssCoex = TRUE;
11895
11896 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11897 _syscmd(cmd, buf, sizeof(buf));
11898 if (strlen(buf) != 0)
11899 operationParam->stbcEnable = TRUE;
11900 else
11901 operationParam->stbcEnable = FALSE;
11902
11903 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11904 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11905 return RETURN_ERR;
11906 }
11907
11908 // Below value is hardcoded
11909
11910 operationParam->numSecondaryChannels = 0;
11911 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11912 operationParam->channelSecondary[i] = 0;
11913 }
11914 operationParam->csa_beacon_count = 15;
11915 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011916
11917 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11918 return RETURN_OK;
11919}
11920
11921static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11922{
developerc086fb72022-10-04 10:18:22 +080011923 int max_radio_num = 0;
11924
11925 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080011926 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080011927 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
11928 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011929 }
11930
developerc086fb72022-10-04 10:18:22 +080011931 return (arrayIndex * max_radio_num) + radioIndex;
11932}
developer06a01d92022-09-07 16:32:39 +080011933
developerc086fb72022-10-04 10:18:22 +080011934wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
11935 if (strncmp(beaconRate, "1Mbps", 5) == 0)
11936 return WIFI_BITRATE_1MBPS;
11937 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
11938 return WIFI_BITRATE_2MBPS;
11939 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
11940 return WIFI_BITRATE_5_5MBPS;
11941 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
11942 return WIFI_BITRATE_6MBPS;
11943 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
11944 return WIFI_BITRATE_9MBPS;
11945 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
11946 return WIFI_BITRATE_11MBPS;
11947 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
11948 return WIFI_BITRATE_12MBPS;
11949 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
11950 return WIFI_BITRATE_18MBPS;
11951 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
11952 return WIFI_BITRATE_24MBPS;
11953 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
11954 return WIFI_BITRATE_36MBPS;
11955 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
11956 return WIFI_BITRATE_48MBPS;
11957 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
11958 return WIFI_BITRATE_54MBPS;
11959 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080011960}
11961
developer1d57d002022-10-12 18:03:15 +080011962INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
11963{
11964 if (beacon == WIFI_BITRATE_1MBPS)
11965 strcpy(beacon_str, "1Mbps");
11966 else if (beacon == WIFI_BITRATE_2MBPS)
11967 strcpy(beacon_str, "2Mbps");
11968 else if (beacon == WIFI_BITRATE_5_5MBPS)
11969 strcpy(beacon_str, "5.5Mbps");
11970 else if (beacon == WIFI_BITRATE_6MBPS)
11971 strcpy(beacon_str, "6Mbps");
11972 else if (beacon == WIFI_BITRATE_9MBPS)
11973 strcpy(beacon_str, "9Mbps");
11974 else if (beacon == WIFI_BITRATE_11MBPS)
11975 strcpy(beacon_str, "11Mbps");
11976 else if (beacon == WIFI_BITRATE_12MBPS)
11977 strcpy(beacon_str, "12Mbps");
11978 else if (beacon == WIFI_BITRATE_18MBPS)
11979 strcpy(beacon_str, "18Mbps");
11980 else if (beacon == WIFI_BITRATE_24MBPS)
11981 strcpy(beacon_str, "24Mbps");
11982 else if (beacon == WIFI_BITRATE_36MBPS)
11983 strcpy(beacon_str, "36Mbps");
11984 else if (beacon == WIFI_BITRATE_48MBPS)
11985 strcpy(beacon_str, "48Mbps");
11986 else if (beacon == WIFI_BITRATE_54MBPS)
11987 strcpy(beacon_str, "54Mbps");
11988 return RETURN_OK;
11989}
11990
developer06a01d92022-09-07 16:32:39 +080011991INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11992{
developerc086fb72022-10-04 10:18:22 +080011993 INT mode = 0;
11994 INT ret = -1;
11995 INT output = 0;
11996 int i = 0;
11997 int vap_index = 0;
11998 BOOL enabled = FALSE;
11999 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012000 wifi_vap_security_t security = {0};
developerc086fb72022-10-04 10:18:22 +080012001 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080012002
12003 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12004 printf("Entering %s index = %d\n", __func__, (int)index);
12005
developer06a01d92022-09-07 16:32:39 +080012006 for (i = 0; i < 5; i++)
12007 {
developerc086fb72022-10-04 10:18:22 +080012008 map->vap_array[i].radio_index = index;
12009
developer06a01d92022-09-07 16:32:39 +080012010 vap_index = array_index_to_vap_index(index, i);
12011 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012012 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012013
developerc086fb72022-10-04 10:18:22 +080012014 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012015
12016 map->vap_array[i].vap_index = vap_index;
12017
12018 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012019 ret = wifi_getApName(vap_index, buf);
12020 if (ret != RETURN_OK) {
12021 printf("%s: wifi_getApName return error\n", __func__);
12022 return RETURN_ERR;
12023 }
12024 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12025
12026 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012027 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012028 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012029 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012030 return RETURN_ERR;
12031 }
12032 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
developer06a01d92022-09-07 16:32:39 +080012033
12034 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012035 if (ret != RETURN_OK) {
12036 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012037 return RETURN_ERR;
12038 }
12039 map->vap_array[i].u.bss_info.enabled = enabled;
12040
developerc086fb72022-10-04 10:18:22 +080012041 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12042 if (ret != RETURN_OK) {
12043 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12044 return RETURN_ERR;
12045 }
developer06a01d92022-09-07 16:32:39 +080012046 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012047
12048 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12049 if (ret != RETURN_OK) {
12050 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12051 return RETURN_ERR;
12052 }
12053 map->vap_array[i].u.bss_info.isolation = enabled;
12054
12055 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12056 if (ret != RETURN_OK) {
12057 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12058 return RETURN_ERR;
12059 }
12060 map->vap_array[i].u.bss_info.bssMaxSta = output;
12061
12062 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12063 if (ret != RETURN_OK) {
12064 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12065 return RETURN_ERR;
12066 }
12067 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012068
developerc086fb72022-10-04 10:18:22 +080012069 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12070 if (ret != RETURN_OK) {
12071 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12072 return RETURN_ERR;
12073 }
12074 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012075
developerc086fb72022-10-04 10:18:22 +080012076 ret = wifi_getApSecurity(vap_index, &security);
12077 if (ret != RETURN_OK) {
12078 printf("%s: wifi_getApSecurity return error\n", __func__);
12079 return RETURN_ERR;
12080 }
12081 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012082
developerc086fb72022-10-04 10:18:22 +080012083 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12084 if (ret != RETURN_OK) {
12085 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12086 return RETURN_ERR;
12087 }
12088 if (mode == 0)
12089 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12090 else
12091 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12092 if (mode == 1)
12093 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12094 else if (mode == 2)
12095 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012096
developerc086fb72022-10-04 10:18:22 +080012097 ret = wifi_getApWmmEnable(vap_index, &enabled);
12098 if (ret != RETURN_OK) {
12099 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12100 return RETURN_ERR;
12101 }
12102 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012103
developerc086fb72022-10-04 10:18:22 +080012104 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12105 if (ret != RETURN_OK) {
12106 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012107 return RETURN_ERR;
12108 }
developerc086fb72022-10-04 10:18:22 +080012109 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012110
12111 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012112 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012113 if (ret != RETURN_OK) {
12114 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12115 return RETURN_ERR;
12116 }
12117 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012118
developerc086fb72022-10-04 10:18:22 +080012119 memset(buf, 0, sizeof(buf));
12120 ret = wifi_getBaseBSSID(vap_index, buf);
12121 if (ret != RETURN_OK) {
12122 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12123 return RETURN_ERR;
12124 }
12125 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12126 &map->vap_array[i].u.bss_info.bssid[0],
12127 &map->vap_array[i].u.bss_info.bssid[1],
12128 &map->vap_array[i].u.bss_info.bssid[2],
12129 &map->vap_array[i].u.bss_info.bssid[3],
12130 &map->vap_array[i].u.bss_info.bssid[4],
12131 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012132 // fprintf(stderr, "%s index %d: mac: %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", __func__, vap_index, map->vap_array[i].u.bss_info.bssid[0], map->vap_array[i].u.bss_info.bssid[1], map->vap_array[i].u.bss_info.bssid[2], map->vap_array[i].u.bss_info.bssid[3], map->vap_array[i].u.bss_info.bssid[4], map->vap_array[i].u.bss_info.bssid[5]);
12133
12134 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12135 if (ret != RETURN_OK) {
12136 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12137 return RETURN_ERR;
12138 }
12139 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012140
developerc086fb72022-10-04 10:18:22 +080012141 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012142 }
12143 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12144 return RETURN_OK;
12145}
12146
12147INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12148{
12149 unsigned int i;
12150 wifi_vap_info_t *vap_info = NULL;
12151 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012152 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012153 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012154 char buf[256] = {0};
12155 char cmd[128] = {0};
12156 char config_file[64] = {0};
12157 char bssid[32] = {0};
12158 char psk_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +080012159
12160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12161 printf("Entering %s index = %d\n", __func__, (int)index);
12162 for (i = 0; i < map->num_vaps; i++)
12163 {
developer1d57d002022-10-12 18:03:15 +080012164 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012165 vap_info = &map->vap_array[i];
developer1d57d002022-10-12 18:03:15 +080012166 if (vap_info->u.bss_info.enabled == FALSE)
12167 continue;
developer06a01d92022-09-07 16:32:39 +080012168
developer1d57d002022-10-12 18:03:15 +080012169 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12170
12171 // multi-ap need to copy current radio config
12172 if (vap_info->radio_index != vap_info->vap_index) {
12173 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12174 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +080012175 }
developer06a01d92022-09-07 16:32:39 +080012176
developer1d57d002022-10-12 18:03:15 +080012177 struct params params[3];
12178 snprintf(vap_info->vap_name, 64, "%s%d", AP_PREFIX, vap_info->vap_index);
12179 params[0].name = "interface";
12180 params[0].value = vap_info->vap_name;
12181 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12182 params[1].name = "bssid";
12183 params[1].value = bssid;
12184 snprintf(psk_file, sizeof(psk_file), "\\/tmp\\/hostapd%d.psk", vap_info->vap_index);
12185 params[2].name = "wpa_psk_file";
12186 params[2].value = psk_file;
12187
12188 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12189 wifi_hostapdWrite(config_file, params, 3);
12190
12191 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12192 _syscmd(cmd, buf, sizeof(buf));
12193
12194 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12195 if (ret != RETURN_OK) {
12196 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12197 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012198 }
developer1d57d002022-10-12 18:03:15 +080012199
12200 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12201 if (ret != RETURN_OK) {
12202 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12203 return RETURN_ERR;
12204 }
12205
12206 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12207 if (ret != RETURN_OK) {
12208 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12209 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012210 }
12211
developer1d57d002022-10-12 18:03:15 +080012212 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12213 if (ret != RETURN_OK) {
12214 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12215 return RETURN_ERR;
12216 }
developer06a01d92022-09-07 16:32:39 +080012217
developer1d57d002022-10-12 18:03:15 +080012218 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12219 if (ret != RETURN_OK) {
12220 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12221 return RETURN_ERR;
12222 }
developer06a01d92022-09-07 16:32:39 +080012223
developer1d57d002022-10-12 18:03:15 +080012224 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12225 if (ret != RETURN_OK) {
12226 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12227 return RETURN_ERR;
12228 }
12229
developer804c64f2022-10-19 13:54:40 +080012230 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012231 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012232 }else {
12233 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012234 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012235 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12236 _syscmd(cmd, buf, sizeof(buf));
12237 }else{
developer1d57d002022-10-12 18:03:15 +080012238 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012239 }
developer1d57d002022-10-12 18:03:15 +080012240 }
12241
12242 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12243 if (ret != RETURN_OK) {
12244 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12245 return RETURN_ERR;
12246 }
12247
12248 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12249 if (ret != RETURN_OK) {
12250 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12251 return RETURN_ERR;
12252 }
12253
12254 memset(buf, 0, sizeof(buf));
12255 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12256 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12257 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12258 if (ret != RETURN_OK) {
12259 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12260 return RETURN_ERR;
12261 }
12262
12263 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12264 if (ret != RETURN_OK) {
12265 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12266 return RETURN_ERR;
12267 }
12268
12269 wifi_setApEnable(vap_info->vap_index, TRUE);
12270 multiple_set = FALSE;
12271
12272 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12273 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12274 if (ret != RETURN_OK) {
12275 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12276 return RETURN_ERR;
12277 }
12278
12279 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12280 if (ret != RETURN_OK) {
12281 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12282 return RETURN_ERR;
12283 }
developer06a01d92022-09-07 16:32:39 +080012284
developer1d57d002022-10-12 18:03:15 +080012285 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012286 }
12287 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12288 return RETURN_OK;
12289}
12290
12291int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12292{
12293 char *token, *next;
12294 const char s[2] = ",";
12295 int count =0;
12296
12297 /* get the first token */
12298 token = strtok_r(pchannels, s, &next);
12299
12300 /* walk through other tokens */
12301 while( token != NULL && count < MAX_CHANNELS) {
12302 chlistptr->channels_list[count++] = atoi(token);
12303 token = strtok_r(NULL, s, &next);
12304 }
12305
12306 return count;
12307}
12308
12309static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12310{
12311 INT status;
12312 wifi_channels_list_t *chlistp;
12313 CHAR output_string[64];
12314 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080012315 wifi_band band;
developer033b37b2022-10-18 11:27:46 +080012316 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080012317
12318 if(rcap == NULL)
12319 {
12320 return RETURN_ERR;
12321 }
12322
12323 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012324 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012325
developer1e5aa162022-09-13 16:06:24 +080012326 if (band == band_2_4)
12327 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12328 else if (band == band_5)
12329 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12330 else if (band == band_6)
12331 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012332
12333 chlistp = &(rcap->channel_list[0]);
12334 memset(pchannels, 0, sizeof(pchannels));
12335
12336 /* possible number of radio channels */
12337 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12338 {
12339 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12340 }
12341 /* Number of channels and list*/
12342 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12343
12344 /* autoChannelSupported */
12345 /* always ON with wifi_getRadioAutoChannelSupported */
12346 rcap->autoChannelSupported = TRUE;
12347
12348 /* DCSSupported */
12349 /* always ON with wifi_getRadioDCSSupported */
12350 rcap->DCSSupported = TRUE;
12351
12352 /* zeroDFSSupported - TBD */
12353 rcap->zeroDFSSupported = FALSE;
12354
12355 /* Supported Country List*/
12356 memset(output_string, 0, sizeof(output_string));
12357 status = wifi_getRadioCountryCode(radioIndex, output_string);
12358 if( status != 0 ) {
12359 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12360 return RETURN_ERR;
12361 } else {
12362 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12363 }
12364 if(!strcmp(output_string,"US")){
12365 rcap->countrySupported[0] = wifi_countrycode_US;
12366 rcap->countrySupported[1] = wifi_countrycode_CA;
12367 } else if (!strcmp(output_string,"CA")) {
12368 rcap->countrySupported[0] = wifi_countrycode_CA;
12369 rcap->countrySupported[1] = wifi_countrycode_US;
12370 } else {
12371 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12372 }
12373
12374 rcap->numcountrySupported = 2;
12375
12376 /* csi */
12377 rcap->csi.maxDevices = 8;
12378 rcap->csi.soudingFrameSupported = TRUE;
12379
developer033b37b2022-10-18 11:27:46 +080012380 phyId = radio_index_to_phy(radioIndex);
12381 snprintf(rcap->ifaceName, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +080012382
12383 /* channelWidth - all supported bandwidths */
12384 int i=0;
12385 rcap->channelWidth[i] = 0;
12386 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12387 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12388 WIFI_CHANNELBANDWIDTH_40MHZ);
12389
12390 }
developer1e5aa162022-09-13 16:06:24 +080012391 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012392 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12393 WIFI_CHANNELBANDWIDTH_40MHZ |
12394 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12395 }
12396
12397
12398 /* mode - all supported variants */
12399 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12400 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012401 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 +080012402 }
12403 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012404 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12405 }
12406 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12407 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012408 }
12409 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12410 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12411
12412 /* supportedBitRate - all supported bitrates */
12413 rcap->supportedBitRate[i] = 0;
12414 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12415 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12416 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12417 }
developer1e5aa162022-09-13 16:06:24 +080012418 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012419 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12420 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12421 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12422 }
12423
12424
12425 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12426 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12427 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12428 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12429 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12430 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12431 rcap->cipherSupported = 0;
12432 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12433 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12434
12435 return RETURN_OK;
12436}
12437
12438INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12439{
developer30423732022-12-01 16:17:49 +080012440 INT status = 0, radioIndex = 0;
12441 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080012442 int iter = 0;
developer30423732022-12-01 16:17:49 +080012443 unsigned int j = 0;
12444 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080012445
12446 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12447
12448 memset(cap, 0, sizeof(wifi_hal_capability_t));
12449
12450 /* version */
12451 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12452 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12453
12454 /* number of radios platform property */
12455 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12456 _syscmd(cmd, output, sizeof(output));
developer804c64f2022-10-19 13:54:40 +080012457 cap->wifi_prop.numRadios = atoi(output) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS: atoi(output) ;
developer06a01d92022-09-07 16:32:39 +080012458
12459 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12460 {
12461 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12462 if (status != 0) {
12463 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12464 return RETURN_ERR;
12465 }
12466
12467 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12468 {
developer804c64f2022-10-19 13:54:40 +080012469 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012470 {
12471 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12472 return RETURN_ERR;
12473 }
12474 iface_info = &cap->wifi_prop.interface_map[iter];
12475 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12476 iface_info->rdk_radio_index = radioIndex;
12477 memset(output, 0, sizeof(output));
12478 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12479 {
12480 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12481 }
12482 // TODO: bridge name
12483 // TODO: vlan id
12484 // TODO: primary
12485 iface_info->index = array_index_to_vap_index(radioIndex, j);
12486 memset(output, 0, sizeof(output));
developer30423732022-12-01 16:17:49 +080012487 if (iface_info->index >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012488 {
12489 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12490 }
12491 iter++;
12492 }
12493 }
12494
12495 cap->BandSteeringSupported = FALSE;
12496 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12497 return RETURN_OK;
12498}
12499
developer9df4e652022-10-11 11:27:38 +080012500INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12501{
12502 struct params h_config={0};
12503 char config_file[64] = {0};
12504
12505 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12506
12507 h_config.name = "okc";
12508 h_config.value = okc_enable?"1":"0";
12509
12510 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12511 wifi_hostapdWrite(config_file, &h_config, 1);
12512 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12513
12514 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12515 return RETURN_OK;
12516}
12517
12518INT wifi_setSAEMFP(int ap_index, BOOL enable)
12519{
12520 struct params h_config={0};
12521 char config_file[64] = {0};
12522 char buf[128] = {0};
12523
12524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12525
12526 h_config.name = "sae_require_mfp";
12527 h_config.value = enable?"1":"0";
12528
12529 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12530 wifi_hostapdWrite(config_file, &h_config, 1);
12531 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12532
12533 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12534 return RETURN_OK;
12535}
12536
12537INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12538{
12539 struct params h_config={0};
12540 char config_file[64] = {0};
12541 char buf[128] = {0};
12542
12543 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12544
12545 h_config.name = "sae_pwe";
12546 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12547 h_config.value = buf;
12548
12549 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12550 wifi_hostapdWrite(config_file, &h_config, 1);
12551 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12552
12553 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12554 return RETURN_OK;
12555}
12556
12557INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12558{
12559 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12560 struct params h_config={0};
12561 char config_file[64] = {0};
12562
12563 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12564
12565 h_config.name = "wpa_disable_eapol_key_retries";
12566 h_config.value = disable_EAPOL_retries?"1":"0";
12567
12568 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12569 wifi_hostapdWrite(config_file, &h_config, 1);
12570 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12571
12572 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12573 return RETURN_OK;
12574}
12575
developer06a01d92022-09-07 16:32:39 +080012576INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12577{
developer587c1b62022-09-27 15:58:59 +080012578 char buf[128] = {0};
12579 char config_file[128] = {0};
12580 char password[64] = {0};
12581 char mfp[32] = {0};
12582 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012583 BOOL okc_enable = FALSE;
12584 BOOL sae_MFP = FALSE;
12585 BOOL disable_EAPOL_retries = TRUE;
12586 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012587 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012588 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012589
12590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12591
12592 multiple_set = TRUE;
12593 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12594 if (security->mode == wifi_security_mode_none) {
12595 strcpy(wpa_mode, "None");
12596 } else if (security->mode == wifi_security_mode_wpa_personal)
12597 strcpy(wpa_mode, "WPA-Personal");
12598 else if (security->mode == wifi_security_mode_wpa2_personal)
12599 strcpy(wpa_mode, "WPA2-Personal");
12600 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12601 strcpy(wpa_mode, "WPA-WPA2-Personal");
12602 else if (security->mode == wifi_security_mode_wpa_enterprise)
12603 strcpy(wpa_mode, "WPA-Enterprise");
12604 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12605 strcpy(wpa_mode, "WPA2-Enterprise");
12606 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12607 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012608 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012609 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012610 okc_enable = TRUE;
12611 sae_MFP = TRUE;
12612 sae_pwe = 2;
12613 disable_EAPOL_retries = FALSE;
12614 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012615 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012616 okc_enable = TRUE;
12617 sae_MFP = TRUE;
12618 sae_pwe = 2;
12619 disable_EAPOL_retries = FALSE;
12620 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012621 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012622 sae_MFP = TRUE;
12623 sae_pwe = 2;
12624 disable_EAPOL_retries = FALSE;
12625 }
12626
12627 band = wifi_index_to_band(ap_index);
12628 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12629 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12630 return RETURN_ERR;
12631 }
developer587c1b62022-09-27 15:58:59 +080012632
12633 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012634 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012635 wifi_setSAEMFP(ap_index, sae_MFP);
12636 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012637 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012638
developer9df4e652022-10-11 11:27:38 +080012639 if (security->mode != wifi_security_mode_none) {
12640 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12641 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12642 password[63] = '\0';
12643 wifi_setApSecurityKeyPassphrase(ap_index, password);
12644 }
12645 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12646 params.name = "sae_password";
12647 params.value = security->u.key.key;
12648 wifi_hostapdWrite(config_file, &params, 1);
12649 }
12650 }
developer587c1b62022-09-27 15:58:59 +080012651
12652 if (security->mode != wifi_security_mode_none) {
12653 memset(&params, 0, sizeof(params));
12654 params.name = "wpa_pairwise";
12655 if (security->encr == wifi_encryption_tkip)
12656 params.value = "TKIP";
12657 else if (security->encr == wifi_encryption_aes)
12658 params.value = "CCMP";
12659 else if (security->encr == wifi_encryption_aes_tkip)
12660 params.value = "TKIP CCMP";
12661 wifi_hostapdWrite(config_file, &params, 1);
12662 }
12663
12664 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012665 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012666 else if (security->mfp == wifi_mfp_cfg_optional)
12667 strcpy(mfp, "Optional");
12668 else if (security->mfp == wifi_mfp_cfg_required)
12669 strcpy(mfp, "Required");
12670 wifi_setApSecurityMFPConfig(ap_index, mfp);
12671
12672 memset(&params, 0, sizeof(params));
12673 params.name = "transition_disable";
12674 if (security->wpa3_transition_disable == TRUE)
12675 params.value = "0x01";
12676 else
12677 params.value = "0x00";
12678 wifi_hostapdWrite(config_file, &params, 1);
12679
12680 memset(&params, 0, sizeof(params));
12681 params.name = "wpa_group_rekey";
12682 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12683 params.value = buf;
12684 wifi_hostapdWrite(config_file, &params, 1);
12685
12686 memset(&params, 0, sizeof(params));
12687 params.name = "wpa_strict_rekey";
12688 params.value = security->strict_rekey?"1":"0";
12689 wifi_hostapdWrite(config_file, &params, 1);
12690
12691 memset(&params, 0, sizeof(params));
12692 params.name = "wpa_pairwise_update_count";
12693 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12694 params.value = buf;
12695 wifi_hostapdWrite(config_file, &params, 1);
12696
12697 memset(&params, 0, sizeof(params));
12698 params.name = "disable_pmksa_caching";
12699 params.value = security->disable_pmksa_caching?"1":"0";
12700 wifi_hostapdWrite(config_file, &params, 1);
12701
12702 wifi_setApEnable(ap_index, FALSE);
12703 wifi_setApEnable(ap_index, TRUE);
12704
12705 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12706
developer06a01d92022-09-07 16:32:39 +080012707 return RETURN_OK;
12708}
12709
12710INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12711{
developer9df4e652022-10-11 11:27:38 +080012712 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012713 char config_file[128] = {0};
12714 int disable = 0;
12715 // struct params params = {0};
12716
12717 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12718 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12719 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12720 security->mode = wifi_security_mode_none;
12721 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012722 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012723 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012724 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012725 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012726 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012727 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012728 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012729 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012730 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012731 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012732 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012733 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012734 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012735 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012736 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080012737 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012738 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012739 security->mode = wifi_security_mode_wpa3_enterprise;
12740 }
12741
12742 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12743 if (security->mode == wifi_security_mode_none)
12744 security->encr = wifi_encryption_none;
12745 else {
12746 if (strcmp(buf, "TKIP") == 0)
12747 security->encr = wifi_encryption_tkip;
12748 else if (strcmp(buf, "CCMP") == 0)
12749 security->encr = wifi_encryption_aes;
12750 else
12751 security->encr = wifi_encryption_aes_tkip;
12752 }
12753
developer9df4e652022-10-11 11:27:38 +080012754 if (security->mode != wifi_encryption_none) {
12755 memset(buf, 0, sizeof(buf));
12756 // wpa3 can use one or both configs as password, so we check sae_password first.
12757 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12758 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12759 security->u.key.type = wifi_security_key_type_sae;
12760 } else {
12761 security->u.key.type = wifi_security_key_type_psk;
12762 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12763 }
12764 strncpy(security->u.key.key, buf, sizeof(buf));
12765 security->u.key.key[255] = '\0';
12766 }
12767
developer587c1b62022-09-27 15:58:59 +080012768 memset(buf, 0, sizeof(buf));
12769 wifi_getApSecurityMFPConfig(ap_index, buf);
12770 if (strcmp(buf, "Disabled") == 0)
12771 security->mfp = wifi_mfp_cfg_disabled;
12772 else if (strcmp(buf, "Optional") == 0)
12773 security->mfp = wifi_mfp_cfg_optional;
12774 else if (strcmp(buf, "Required") == 0)
12775 security->mfp = wifi_mfp_cfg_required;
12776
12777 memset(buf, 0, sizeof(buf));
12778 security->wpa3_transition_disable = FALSE;
12779 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12780 disable = strtol(buf, NULL, 16);
12781 if (disable != 0)
12782 security->wpa3_transition_disable = TRUE;
12783
12784 memset(buf, 0, sizeof(buf));
12785 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12786 if (strlen(buf) == 0)
12787 security->rekey_interval = 86400;
12788 else
12789 security->rekey_interval = strtol(buf, NULL, 10);
12790
12791 memset(buf, 0, sizeof(buf));
12792 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12793 if (strlen(buf) == 0)
12794 security->strict_rekey = 1;
12795 else
12796 security->strict_rekey = strtol(buf, NULL, 10);
12797
12798 memset(buf, 0, sizeof(buf));
12799 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12800 if (strlen(buf) == 0)
12801 security->eapol_key_retries = 4;
12802 else
12803 security->eapol_key_retries = strtol(buf, NULL, 10);
12804
12805 memset(buf, 0, sizeof(buf));
12806 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12807 if (strlen(buf) == 0)
12808 security->disable_pmksa_caching = FALSE;
12809 else
12810 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12811
12812 /* TODO
12813 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12814 */
12815 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12816 security->eap_identity_req_timeout = 0;
12817 security->eap_identity_req_retries = 0;
12818 security->eap_req_timeout = 0;
12819 security->eap_req_retries = 0;
12820 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012821 return RETURN_OK;
12822}
12823
12824#endif /* WIFI_HAL_VERSION_3 */
12825
12826#ifdef WIFI_HAL_VERSION_3_PHASE2
12827INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12828{
developer13df9332022-09-27 16:53:22 +080012829 char cmd[128] = {0};
12830 char buf[128] = {0};
12831 char *mac_addr = NULL;
12832 BOOL status = FALSE;
12833 size_t len = 0;
12834
12835 if(ap_index > MAX_APS)
12836 return RETURN_ERR;
12837
12838 *output_numDevices = 0;
12839 wifi_getApEnable(ap_index, &status);
12840 if (status == FALSE)
12841 return RETURN_OK;
12842
12843 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12844 _syscmd(cmd, buf, sizeof(buf));
12845
12846 mac_addr = strtok(buf, "\n");
12847 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12848 *output_numDevices = i + 1;
12849 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12850 addr_ptr = output_deviceMacAddressArray[i];
12851 mac_addr_aton(addr_ptr, mac_addr);
12852 mac_addr = strtok(NULL, "\n");
12853 }
12854
12855 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012856}
12857#else
12858INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12859{
12860 char cmd[128];
12861 BOOL status = false;
12862
12863 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12864 return RETURN_ERR;
12865
12866 output_buf[0] = '\0';
12867
12868 wifi_getApEnable(ap_index,&status);
12869 if (!status)
12870 return RETURN_OK;
12871
12872 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12873 _syscmd(cmd, output_buf, output_buf_size);
12874
12875 return RETURN_OK;
12876}
12877#endif
developer2f513ab2022-09-13 14:26:06 +080012878
12879INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12880{
12881 char output[16]={'\0'};
12882 char config_file[MAX_BUF_SIZE] = {0};
12883
12884 if (!enable)
12885 return RETURN_ERR;
12886
12887 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12888 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12889
12890 if (strlen(output) == 0)
12891 *enable = FALSE;
12892 else if (strncmp(output, "1", 1) == 0)
12893 *enable = TRUE;
12894 else
12895 *enable = FALSE;
12896
12897 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12898 return RETURN_OK;
12899}
developer2d9c30f2022-09-13 15:06:14 +080012900
12901INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12902{
developer804c64f2022-10-19 13:54:40 +080012903 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080012904 return RETURN_ERR;
12905 *output_enable=TRUE;
12906 return RETURN_OK;
12907}
developerfd7d2892022-09-13 16:44:53 +080012908
12909INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12910{
12911 char cmd[128] = {0};
12912 char buf[128] = {0};
12913 char line[128] = {0};
12914 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080012915 FILE *f = NULL;
12916 int index = 0;
12917 int exp = 0;
12918 int mantissa = 0;
12919 int duration = 0;
12920 int radio_index = 0;
12921 int max_radio_num = 0;
12922 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080012923 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080012924 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12925
12926 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080012927
developerfd7d2892022-09-13 16:44:53 +080012928 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080012929
12930 phyId = radio_index_to_phy(radio_index);
12931 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080012932 _syscmd(cmd, buf, sizeof(buf));
12933 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12934 if (*numSessionReturned > maxNumberSessions)
12935 *numSessionReturned = maxNumberSessions;
12936 else if (*numSessionReturned < 1) {
12937 *numSessionReturned = 0;
12938 return RETURN_OK;
12939 }
12940
developer033b37b2022-10-18 11:27:46 +080012941 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
developerfd7d2892022-09-13 16:44:53 +080012942 if ((f = popen(cmd, "r")) == NULL) {
12943 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12944 return RETURN_ERR;
12945 }
12946
12947 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080012948 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080012949 char *tmp = NULL;
12950 strcpy(buf, line);
12951 tmp = strtok(buf, " ");
12952 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12953 tmp = strtok(NULL, " ");
12954 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12955 tmp = strtok(NULL, " ");
12956 if (strstr(tmp, "t")) {
12957 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12958 }
12959 if (strstr(tmp, "a")) {
12960 twtSessions[index].twtParameters.operation.announced = TRUE;
12961 }
12962 tmp = strtok(NULL, " ");
12963 exp = strtol(tmp, NULL, 10);
12964 tmp = strtok(NULL, " ");
12965 mantissa = strtol(tmp, NULL, 10);
12966 tmp = strtok(NULL, " ");
12967 duration = strtol(tmp, NULL, 10);
12968
12969 // only implicit supported
12970 twtSessions[index].twtParameters.operation.implicit = TRUE;
12971 // only individual agreement supported
12972 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12973
12974 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12975 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080012976 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080012977 // Overflow handling
12978 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12979 } else {
12980 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12981 }
12982 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12983 index++;
12984 }
12985
12986 pclose(f);
12987 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12988 return RETURN_OK;
12989}