blob: fdb581700644fc4bb6aee1e5bd11e3775f3f650a [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"
developer431128d2022-12-16 15:30:41 +080071#define ACL_PREFIX "/nvram/hostapd-acl"
72#define DENY_PREFIX "/nvram/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"
developer431128d2022-12-16 15:30:41 +080075#define VAP_STATUS_FILE "/nvram/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"
developer431128d2022-12-16 15:30:41 +080081#define PSK_FILE "/nvram/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) {
developer431128d2022-12-16 15:30:41 +0800463 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
developer033b37b2022-10-18 11:27:46 +0800464 return RETURN_ERR;
465 }
466 sscanf(buf, "phy%d", &phyIndex);
467
468 return phyIndex;
469}
developer026ac9e2022-11-07 13:46:24 +0800470
developer431128d2022-12-16 15:30:41 +0800471INT wifi_getMaxRadioNumber(INT *max_radio_num)
472{
473 char cmd[64] = {0};
474 char buf[4] = {0};
475
476 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
477
478 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
479 _syscmd(cmd, buf, sizeof(buf));
480 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
481
482 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
483
484 return RETURN_OK;
485}
486
487wifi_band wifi_index_to_band(int apIndex)
developerc707e972022-09-13 15:38:02 +0800488{
489 char cmd[128] = {0};
490 char buf[64] = {0};
developer026ac9e2022-11-07 13:46:24 +0800491 int nl80211_band = 0;
developer5884e982022-10-06 10:52:50 +0800492 int i = 0;
developer026ac9e2022-11-07 13:46:24 +0800493 int phyIndex = 0;
developer431128d2022-12-16 15:30:41 +0800494 int radioIndex = 0;
495 int max_radio_num = 0;
developerc707e972022-09-13 15:38:02 +0800496 wifi_band band = band_invalid;
497
498 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer026ac9e2022-11-07 13:46:24 +0800499
developer431128d2022-12-16 15:30:41 +0800500 wifi_getMaxRadioNumber(&max_radio_num);
501 radioIndex = apIndex % max_radio_num;
developer026ac9e2022-11-07 13:46:24 +0800502 phyIndex = radio_index_to_phy(radioIndex);
developer5884e982022-10-06 10:52:50 +0800503 while(i < 10){
developer026ac9e2022-11-07 13:46:24 +0800504 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 +0800505 _syscmd(cmd, buf, sizeof(buf));
developer026ac9e2022-11-07 13:46:24 +0800506 nl80211_band = strtol(buf, NULL, 10);
507 if (nl80211_band == 1)
developer5884e982022-10-06 10:52:50 +0800508 band = band_2_4;
developer026ac9e2022-11-07 13:46:24 +0800509 else if (nl80211_band == 2)
developer5884e982022-10-06 10:52:50 +0800510 band = band_5;
developer026ac9e2022-11-07 13:46:24 +0800511 else if (nl80211_band == 4) // band == 3 is 60GHz
developer5884e982022-10-06 10:52:50 +0800512 band = band_6;
513
514 if(band != band_invalid)
515 break;
516
517 i++;
518 sleep(1);
519 }
developerc707e972022-09-13 15:38:02 +0800520
521 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
522 return band;
523}
524
developer06a01d92022-09-07 16:32:39 +0800525static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
526{
527 char cmd[MAX_CMD_SIZE]={'\0'};
528 char buf[MAX_BUF_SIZE]={'\0'};
529 int ret = 0;
530
developerd946fd62022-12-08 18:03:28 +0800531 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
developer06a01d92022-09-07 16:32:39 +0800532 ret = _syscmd(cmd, buf, sizeof(buf));
533 if ((ret != 0) && (strlen(buf) == 0))
534 return -1;
535 snprintf(output, output_size, "%s", buf);
536
537 return 0;
538}
539
540static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
541{
542 char cmd[MAX_CMD_SIZE]={'\0'};
543 char buf[MAX_BUF_SIZE]={'\0'};
544
545 for(int i=0;i<item_count;i++)
546 {
547 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
548 if (strlen(buf) == 0) //Insert
549 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
550 else //Update
551 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 +0800552
developer06a01d92022-09-07 16:32:39 +0800553 if(_syscmd(cmd, buf, sizeof(buf)))
554 return -1;
555 }
556
557 return 0;
558}
559
developerd946fd62022-12-08 18:03:28 +0800560//For Getting Current Interface Name from corresponding hostapd configuration
561static int GetInterfaceName(int apIndex, char *interface_name)
562{
563 char config_file[128] = {0};
564
565 if (interface_name == NULL)
566 return RETURN_ERR;
567
568 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
569
570 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
571 wifi_hostapdRead(config_file, "interface", interface_name, 16);
572 if (strlen(interface_name) == 0)
573 return RETURN_ERR;
574
575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
576 return RETURN_OK;
577}
578
developer06a01d92022-09-07 16:32:39 +0800579static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
580{
developerd946fd62022-12-08 18:03:28 +0800581 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800582 if (multiple_set == TRUE)
583 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800584 char cmd[MAX_CMD_SIZE]="", output[32]="";
585 FILE *fp;
586 int i;
587 //NOTE RELOAD should be done in ApplySSIDSettings
developerd946fd62022-12-08 18:03:28 +0800588 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
589 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +0800590 for(i=0; i<item_count; i++, list++)
591 {
developerd946fd62022-12-08 18:03:28 +0800592 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer06a01d92022-09-07 16:32:39 +0800593 if((fp = popen(cmd, "r"))==NULL)
594 {
595 perror("popen failed");
596 return -1;
597 }
598 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
599 {
600 pclose(fp);
601 perror("fgets failed");
602 return -1;
603 }
604 pclose(fp);
605 }
606 return 0;
607}
608
609static int wifi_reloadAp(int apIndex)
610{
developerd946fd62022-12-08 18:03:28 +0800611 char interface_name[16] = {0};
developer1e5aa162022-09-13 16:06:24 +0800612 if (multiple_set == TRUE)
613 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800614 char cmd[MAX_CMD_SIZE]="";
615 char buf[MAX_BUF_SIZE]="";
616
developerd946fd62022-12-08 18:03:28 +0800617 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
618 return RETURN_ERR;
619 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
developer06a01d92022-09-07 16:32:39 +0800620 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
621 return RETURN_ERR;
622
developerd946fd62022-12-08 18:03:28 +0800623 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800624 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
625 return RETURN_ERR;
626
developerd946fd62022-12-08 18:03:28 +0800627 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
developer06a01d92022-09-07 16:32:39 +0800628 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
629 return RETURN_ERR;
630
631 return RETURN_OK;
632}
633
developer06a01d92022-09-07 16:32:39 +0800634INT File_Reading(CHAR *file, char *Value)
635{
636 FILE *fp = NULL;
637 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
638 int count = 0;
639
640 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
641 fp = popen(file,"r");
642 if(fp == NULL)
643 return RETURN_ERR;
644
645 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
646 {
647 for(count=0;buf[count]!='\n';count++)
648 copy_buf[count]=buf[count];
649 copy_buf[count]='\0';
650 }
651 strcpy(Value,copy_buf);
652 pclose(fp);
653 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
654
655 return RETURN_OK;
656}
657
658void wifi_RestartHostapd_2G()
659{
660 int Public2GApIndex = 4;
661
662 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
663 wifi_setApEnable(Public2GApIndex, FALSE);
664 wifi_setApEnable(Public2GApIndex, TRUE);
665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
666}
667
668void wifi_RestartHostapd_5G()
669{
670 int Public5GApIndex = 5;
671
672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
673 wifi_setApEnable(Public5GApIndex, FALSE);
674 wifi_setApEnable(Public5GApIndex, TRUE);
675 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
676}
677
678void wifi_RestartPrivateWifi_2G()
679{
680 int PrivateApIndex = 0;
681
682 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
683 wifi_setApEnable(PrivateApIndex, FALSE);
684 wifi_setApEnable(PrivateApIndex, TRUE);
685 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
686}
687
688void wifi_RestartPrivateWifi_5G()
689{
690 int Private5GApIndex = 1;
691
692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
693 wifi_setApEnable(Private5GApIndex, FALSE);
694 wifi_setApEnable(Private5GApIndex, TRUE);
695 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
696}
697
698static int writeBandWidth(int radioIndex,char *bw_value)
699{
700 char buf[MAX_BUF_SIZE];
701 char cmd[MAX_CMD_SIZE];
702
703 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
704 if(_syscmd(cmd, buf, sizeof(buf)))
705 {
706 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
707 _syscmd(cmd, buf, sizeof(buf));
708 return RETURN_OK;
709 }
710
711 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
712 _syscmd(cmd,buf,sizeof(buf));
713 return RETURN_OK;
714}
715
716static int readBandWidth(int radioIndex,char *bw_value)
717{
developer30423732022-12-01 16:17:49 +0800718 char buf[MAX_BUF_SIZE] = {0};
719 char cmd[MAX_CMD_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +0800720 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
721 _syscmd(cmd,buf,sizeof(buf));
722 if(NULL!=strstr(buf,"20MHz"))
723 {
724 strcpy(bw_value,"20MHz");
725 }
726 else if(NULL!=strstr(buf,"40MHz"))
727 {
728 strcpy(bw_value,"40MHz");
729 }
730 else if(NULL!=strstr(buf,"80MHz"))
731 {
732 strcpy(bw_value,"80MHz");
733 }
734 else
735 {
736 return RETURN_ERR;
737 }
738 return RETURN_OK;
739}
740
developer264159b2022-11-02 09:41:35 +0800741// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800742INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
743{
developer5f222492022-09-13 15:21:52 +0800744 struct params params={'\0'};
745 char config_file[MAX_BUF_SIZE] = {0};
746 char buf[MAX_BUF_SIZE] = {'\0'};
747
748 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer5f222492022-09-13 15:21:52 +0800749 // Copy the numeric value
developer264159b2022-11-02 09:41:35 +0800750 if (strlen (beaconRate) >= 5) {
751 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
752 buf[strlen(beaconRate) - 4] = '\0';
753 } else if (strlen(beaconRate) > 0)
754 strcpy(buf, beaconRate);
755 else
756 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +0800757
758 params.name = "beacon_rate";
759 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
760 if (strncmp(buf, "5.5", 3) == 0) {
761 snprintf(buf, sizeof(buf), "55");
762 params.value = buf;
763 } else {
764 strcat(buf, "0");
765 params.value = buf;
766 }
767
768 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
769 wifi_hostapdWrite(config_file, &params, 1);
770 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
771 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
772
773 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800774}
775
776INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
777{
developer1d57d002022-10-12 18:03:15 +0800778 char config_file[128] = {'\0'};
779 char temp_output[128] = {'\0'};
780 char buf[128] = {'\0'};
781 char cmd[128] = {'\0'};
782 int rate = 0;
developer033b37b2022-10-18 11:27:46 +0800783 int phyId = 0;
developer5f222492022-09-13 15:21:52 +0800784
785 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
786 if (NULL == beaconRate)
787 return RETURN_ERR;
788
789 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
790 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +0800791 phyId = radio_index_to_phy(radioIndex);
developer5f222492022-09-13 15:21:52 +0800792 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
793 if(strlen(buf) > 0) {
developer1d57d002022-10-12 18:03:15 +0800794 if (strncmp(buf, "55", 2) == 0)
795 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
796 else {
797 rate = strtol(buf, NULL, 10)/10;
798 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
799 }
developer5f222492022-09-13 15:21:52 +0800800 } else {
developer1d57d002022-10-12 18:03:15 +0800801 // config not set, so we would use lowest rate as default
developer033b37b2022-10-18 11:27:46 +0800802 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 +0800803 _syscmd(cmd, buf, sizeof(buf));
804 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
developer5f222492022-09-13 15:21:52 +0800805 }
806 strncpy(beaconRate, temp_output, sizeof(temp_output));
807 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
808
809 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800810}
811
812INT wifi_setLED(INT radioIndex, BOOL enable)
813{
814 return 0;
815}
816INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
817{
818 return RETURN_OK;
819}
820/**********************************************************************************
821 *
822 * Wifi Subsystem level function prototypes
823 *
824**********************************************************************************/
825//---------------------------------------------------------------------------------------------------
826//Wifi system api
827//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
828INT wifi_getHalVersion(CHAR *output_string) //RDKB
829{
830 if(!output_string)
831 return RETURN_ERR;
832 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
833
834 return RETURN_OK;
835}
836
837
838/* wifi_factoryReset() function */
839/**
840* @description Clears internal variables to implement a factory reset of the Wi-Fi
841* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
842*
843* @param None
844*
845* @return The status of the operation.
846* @retval RETURN_OK if successful.
847* @retval RETURN_ERR if any error is detected
848*
849* @execution Synchronous
850* @sideeffect None
851*
852* @note This function must not suspend and must not invoke any blocking system
853* calls. It should probably just send a message to a driver event handler task.
854*
855*/
856INT wifi_factoryReset()
857{
858 char cmd[128];
859
860 /*delete running hostapd conf files*/
861 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
862 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
863 system(cmd);
864 system("systemctl restart hostapd.service");
865
866 return RETURN_OK;
867}
868
869/* wifi_factoryResetRadios() function */
870/**
871* @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.
872*
873* @param None
874* @return The status of the operation
875* @retval RETURN_OK if successful
876* @retval RETURN_ERR if any error is detected
877*
878* @execution Synchronous
879*
880* @sideeffect None
881*
882* @note This function must not suspend and must not invoke any blocking system
883* calls. It should probably just send a message to a driver event handler task.
884*
885*/
886INT wifi_factoryResetRadios()
887{
888 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
889 return RETURN_OK;
890
891 return RETURN_ERR;
892}
893
894
895/* wifi_factoryResetRadio() function */
896/**
897* @description Restore selected radio parameters without touching access point parameters
898*
899* @param radioIndex - Index of Wi-Fi Radio channel
900*
901* @return The status of the operation.
902* @retval RETURN_OK if successful.
903* @retval RETURN_ERR if any error is detected
904*
905* @execution Synchronous.
906* @sideeffect None.
907*
908* @note This function must not suspend and must not invoke any blocking system
909* calls. It should probably just send a message to a driver event handler task.
910*
911*/
912INT wifi_factoryResetRadio(int radioIndex) //RDKB
913{
developer5ff7f5f2022-09-13 15:12:16 +0800914 system("systemctl stop hostapd.service");
915
developer06a01d92022-09-07 16:32:39 +0800916 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
917 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800918 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800919 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800920 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800921 else
922 return RETURN_ERR;
923
developer5ff7f5f2022-09-13 15:12:16 +0800924 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800925 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
926 return RETURN_OK;
927}
928
929/* wifi_initRadio() function */
930/**
931* Description: This function call initializes the specified radio.
932* Implementation specifics may dictate the functionality since
933* different hardware implementations may have different initilization requirements.
934* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
935*
936* @return The status of the operation.
937* @retval RETURN_OK if successful.
938* @retval RETURN_ERR if any error is detected
939*
940* @execution Synchronous.
941* @sideeffect None.
942*
943* @note This function must not suspend and must not invoke any blocking system
944* calls. It should probably just send a message to a driver event handler task.
945*
946*/
947INT wifi_initRadio(INT radioIndex)
948{
949 //TODO: Initializes the wifi subsystem (for specified radio)
950 return RETURN_OK;
951}
952void macfilter_init()
953{
954 char count[4]={'\0'};
955 char buf[253]={'\0'};
956 char tmp[19]={'\0'};
957 int dev_count,block,mac_entry=0;
958 char res[4]={'\0'};
959 char acl_file_path[64] = {'\0'};
960 FILE *fp = NULL;
961 int index=0;
962 char iface[10]={'\0'};
963 char config_file[MAX_BUF_SIZE] = {0};
964
965
966 sprintf(acl_file_path,"/tmp/mac_filter.sh");
967
968 fp=fopen(acl_file_path,"w+");
developer30423732022-12-01 16:17:49 +0800969 if (fp == NULL) {
970 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
971 return RETURN_ERR;
972 }
developer06a01d92022-09-07 16:32:39 +0800973 sprintf(buf,"#!/bin/sh \n");
974 fprintf(fp,"%s\n",buf);
975
976 system("chmod 0777 /tmp/mac_filter.sh");
977
978 for(index=0;index<=1;index++)
979 {
980 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
981 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
982 sprintf(buf,"syscfg get %dcountfilter",index);
983 _syscmd(buf,count,sizeof(count));
984 mac_entry=atoi(count);
985
986 sprintf(buf,"syscfg get %dblockall",index);
987 _syscmd(buf,res,sizeof(res));
988 block = atoi(res);
989
990 //Allow only those macs mentioned in ACL
991 if(block==1)
992 {
993 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
994 fprintf(fp,"%s\n",buf);
995 for(dev_count=1;dev_count<=mac_entry;dev_count++)
996 {
997 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
998 _syscmd(buf,tmp,sizeof(tmp));
999 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1000 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1001 fprintf(fp,"%s\n",buf);
1002 }
1003 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1004 fprintf(fp,"%s\n",buf);
1005 }
1006
1007 //Block all the macs mentioned in ACL
1008 else if(block==2)
1009 {
1010 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1011 fprintf(fp,"%s\n",buf);
1012
1013 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1014 {
1015 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1016 _syscmd(buf,tmp,sizeof(tmp));
1017 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1018 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1019 fprintf(fp,"%s\n",buf);
1020 }
1021 }
1022 }
1023 fclose(fp);
1024}
1025
1026// Initializes the wifi subsystem (all radios)
1027INT wifi_init() //RDKB
1028{
1029 char interface[MAX_BUF_SIZE]={'\0'};
1030 char bridge_name[MAX_BUF_SIZE]={'\0'};
1031 INT len=0;
1032
1033 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1034 //Not intitializing macfilter for Turris-Omnia Platform for now
1035 //macfilter_init();
1036
1037 system("/usr/sbin/iw reg set US");
1038 system("systemctl start hostapd.service");
1039 sleep(2);//sleep to wait for hostapd to start
1040
1041 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1042
1043 return RETURN_OK;
1044}
1045
1046/* wifi_reset() function */
1047/**
1048* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1049* Implementation specifics may dictate what is actualy reset since
1050* different hardware implementations may have different requirements.
1051* Parameters : None
1052*
1053* @return The status of the operation.
1054* @retval RETURN_OK if successful.
1055* @retval RETURN_ERR if any error is detected
1056*
1057* @execution Synchronous.
1058* @sideeffect None.
1059*
1060* @note This function must not suspend and must not invoke any blocking system
1061* calls. It should probably just send a message to a driver event handler task.
1062*
1063*/
1064INT wifi_reset()
1065{
1066 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +08001067 system("systemctl stop hostapd.service");
1068 sleep(2);
1069 system("systemctl start hostapd.service");
1070 sleep(5);
developer06a01d92022-09-07 16:32:39 +08001071 return RETURN_OK;
1072}
1073
1074/* wifi_down() function */
1075/**
1076* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1077* Implementation specifics may dictate some functionality since
1078* different hardware implementations may have different requirements.
1079*
1080* @param None
1081*
1082* @return The status of the operation
1083* @retval RETURN_OK if successful
1084* @retval RETURN_ERR if any error is detected
1085*
1086* @execution Synchronous
1087* @sideeffect None
1088*
1089* @note This function must not suspend and must not invoke any blocking system
1090* calls. It should probably just send a message to a driver event handler task.
1091*
1092*/
1093INT wifi_down()
1094{
1095 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001096 system("systemctl stop hostapd.service");
1097 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001098 return RETURN_OK;
1099}
1100
1101
1102/* wifi_createInitialConfigFiles() function */
1103/**
1104* @description This function creates wifi configuration files. The format
1105* and content of these files are implementation dependent. This function call is
1106* used to trigger this task if necessary. Some implementations may not need this
1107* function. If an implementation does not need to create config files the function call can
1108* do nothing and return RETURN_OK.
1109*
1110* @param None
1111*
1112* @return The status of the operation
1113* @retval RETURN_OK if successful
1114* @retval RETURN_ERR if any error is detected
1115*
1116* @execution Synchronous
1117* @sideeffect None
1118*
1119* @note This function must not suspend and must not invoke any blocking system
1120* calls. It should probably just send a message to a driver event handler task.
1121*
1122*/
1123INT wifi_createInitialConfigFiles()
1124{
1125 //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)
1126 return RETURN_OK;
1127}
1128
1129// outputs the country code to a max 64 character string
1130INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1131{
developerd946fd62022-12-08 18:03:28 +08001132 char interface_name[16] = {0};
developer7543b3b2022-09-13 13:47:17 +08001133 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer804c64f2022-10-19 13:54:40 +08001134 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
developer06a01d92022-09-07 16:32:39 +08001135 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001136
developerd946fd62022-12-08 18:03:28 +08001137 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1138 return RETURN_ERR;
1139 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
developer7543b3b2022-09-13 13:47:17 +08001140 _syscmd(cmd, buf, sizeof(buf));
1141 if(strlen(buf) > 0)
1142 snprintf(output_string, 64, "%s", buf);
1143 else
1144 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001145
1146 return RETURN_OK;
1147}
1148
1149INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1150{
1151 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001152 char str[MAX_BUF_SIZE]={'\0'};
1153 char cmd[MAX_CMD_SIZE]={'\0'};
1154 struct params params;
1155 char config_file[MAX_BUF_SIZE] = {0};
1156
1157 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1158 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1159 return RETURN_ERR;
1160
developerb86c6f32022-10-07 14:34:58 +08001161 if (strlen(CountryCode) == 0)
1162 strcpy(CountryCode, "US");
1163
developer7543b3b2022-09-13 13:47:17 +08001164 params.name = "country_code";
1165 params.value = CountryCode;
1166 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1167 int ret = wifi_hostapdWrite(config_file, &params, 1);
1168 if (ret) {
1169 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1170 ,__func__, ret);
1171 }
1172
1173 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1174 if (ret) {
1175 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1176 ,__func__, ret);
1177 }
developer7543b3b2022-09-13 13:47:17 +08001178 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1179
developer06a01d92022-09-07 16:32:39 +08001180 return RETURN_OK;
1181}
1182
developera748dcf2022-09-13 15:56:48 +08001183INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1184{
developerd946fd62022-12-08 18:03:28 +08001185 char interface_name[16] = {0};
developera748dcf2022-09-13 15:56:48 +08001186 char channel_util_file[64] = {0};
1187 char cmd[128] = {0};
1188 char buf[128] = {0};
1189 char line[128] = {0};
1190 char *param = NULL, *value = NULL;
1191 int read = 0;
1192 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1193 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1194 size_t len = 0;
1195 FILE *f = NULL;
1196
1197 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1198
developerd946fd62022-12-08 18:03:28 +08001199 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1200 return RETURN_ERR;
1201 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
developera748dcf2022-09-13 15:56:48 +08001202 _syscmd(cmd, buf, sizeof(buf));
1203 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1204
1205 memset(cmd, 0, sizeof(cmd));
1206 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08001207 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
developera748dcf2022-09-13 15:56:48 +08001208 if ((f = popen(cmd, "r")) == NULL) {
1209 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1210 return RETURN_ERR;
1211 }
1212
1213 read = getline(&line, &len, f);
1214 while (read != -1) {
1215 param = strtok(line, ":\t");
1216 value = strtok(NULL, " ");
1217 if(strstr(param, "frequency") != NULL) {
1218 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1219 }
1220 if(strstr(param, "noise") != NULL) {
1221 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1222 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1223 }
1224 if(strstr(param, "channel active time") != NULL) {
1225 ActiveTime = strtol(value, NULL, 10);
1226 }
1227 if(strstr(param, "channel busy time") != NULL) {
1228 BusyTime = strtol(value, NULL, 10);
1229 }
1230 if(strstr(param, "channel transmit time") != NULL) {
1231 TransmitTime = strtol(value, NULL, 10);
1232 }
1233 read = getline(&line, &len, f);
1234 }
1235 pclose(f);
1236
1237 // The file should store the last active, busy and transmit time
1238 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1239 f = fopen(channel_util_file, "r");
1240 if (f != NULL) {
1241 read = getline(&line, &len, f);
1242 preActiveTime = strtol(line, NULL, 10);
1243 read = getline(&line, &len, f);
1244 preBusyTime = strtol(line, NULL, 10);
1245 read = getline(&line, &len, f);
1246 preTransmitTime = strtol(line, NULL, 10);
1247 fclose(f);
1248 }
1249
1250 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1251 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1252
1253 f = fopen(channel_util_file, "w");
1254 if (f != NULL) {
1255 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1256 fclose(f);
1257 }
1258 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1259 return RETURN_OK;
1260}
1261
developer06a01d92022-09-07 16:32:39 +08001262/**********************************************************************************
1263 *
1264 * Wifi radio level function prototypes
1265 *
1266**********************************************************************************/
1267
1268//Get the total number of radios in this wifi subsystem
1269INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1270{
1271 if (NULL == output)
1272 return RETURN_ERR;
developer6372c2b2022-10-27 17:39:51 +08001273 *output = MAX_NUM_RADIOS;
developer06a01d92022-09-07 16:32:39 +08001274
1275 return RETURN_OK;
1276}
1277
1278//Get the total number of SSID entries in this wifi subsystem
1279INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1280{
1281 if (NULL == output)
1282 return RETURN_ERR;
1283 *output = MAX_APS;
1284
1285 return RETURN_OK;
1286}
1287
1288//Get the Radio enable config parameter
1289INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1290{
developerd946fd62022-12-08 18:03:28 +08001291 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001292 char interface_path[MAX_CMD_SIZE] = {0};
1293 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001294 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001295
1296 if (NULL == output_bool)
1297 return RETURN_ERR;
1298
1299 *output_bool = FALSE;
developer804c64f2022-10-19 13:54:40 +08001300 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
developer06a01d92022-09-07 16:32:39 +08001301 return RETURN_ERR;
1302
developer033b37b2022-10-18 11:27:46 +08001303 phyId = radio_index_to_phy(radioIndex);
1304
1305 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001306 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001307 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001308 {
developercf48e482022-09-13 14:49:50 +08001309 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001310 }
developerd946fd62022-12-08 18:03:28 +08001311 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001312 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001313 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
developerd946fd62022-12-08 18:03:28 +08001314 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1315 return RETURN_ERR;
1316 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
developercf48e482022-09-13 14:49:50 +08001317 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001318
developercf48e482022-09-13 14:49:50 +08001319 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1320 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08001321 return RETURN_OK;
1322}
1323
1324INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1325{
developerd946fd62022-12-08 18:03:28 +08001326 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08001327 char cmd[MAX_CMD_SIZE] = {0};
1328 char buf[MAX_CMD_SIZE] = {0};
1329 int apIndex, ret;
1330 FILE *fp = NULL;
developer033b37b2022-10-18 11:27:46 +08001331 int max_radio_num = 0;
1332 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08001333
1334 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer033b37b2022-10-18 11:27:46 +08001335
1336 phyId = radio_index_to_phy(radioIndex);
1337
1338 wifi_getMaxRadioNumber(&max_radio_num);
1339
developerd946fd62022-12-08 18:03:28 +08001340 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1341 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001342 if(enable==FALSE)
1343 {
developer033b37b2022-10-18 11:27:46 +08001344 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001345 {
1346 //Detaching %s%d from hostapd daemon
developerd946fd62022-12-08 18:03:28 +08001347 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08001348 _syscmd(cmd, buf, sizeof(buf));
1349 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001350 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
1351 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
developer06a01d92022-09-07 16:32:39 +08001352 _syscmd(cmd, buf, sizeof(buf));
1353 }
developer033b37b2022-10-18 11:27:46 +08001354 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001355 _syscmd(cmd, buf, sizeof(buf));
1356 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001357 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001358 }
1359 else
1360 {
developer033b37b2022-10-18 11:27:46 +08001361 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001362 _syscmd(cmd, buf, sizeof(buf));
1363 if(strlen(buf))
developer033b37b2022-10-18 11:27:46 +08001364 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001365 sleep(1);
developer033b37b2022-10-18 11:27:46 +08001366
1367 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
developer06a01d92022-09-07 16:32:39 +08001368 {
developer431128d2022-12-16 15:30:41 +08001369 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
developer06a01d92022-09-07 16:32:39 +08001370 ret = _syscmd(cmd, buf, sizeof(buf));
1371 if ( ret == RETURN_ERR)
1372 {
1373 fprintf(stderr, "VAP interface creation failed\n");
1374 continue;
1375 }
developerd946fd62022-12-08 18:03:28 +08001376 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08001377 _syscmd(cmd, buf, sizeof(buf));
1378 if(*buf == '1')
1379 {
1380 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
developer033b37b2022-10-18 11:27:46 +08001381 phyId, apIndex);
developer06a01d92022-09-07 16:32:39 +08001382 _syscmd(cmd, buf, sizeof(buf));
1383 if(strncmp(buf, "OK", 2))
developerd946fd62022-12-08 18:03:28 +08001384 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer06a01d92022-09-07 16:32:39 +08001385 }
1386 }
1387 }
1388
1389 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1390 return RETURN_OK;
1391}
1392
1393//Get the Radio enable status
1394INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1395{
1396 if (NULL == output_bool)
1397 return RETURN_ERR;
1398
1399 return wifi_getRadioEnable(radioIndex, output_bool);
1400}
1401
1402//Get the Radio Interface name from platform, eg "wlan0"
1403INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1404{
developer033b37b2022-10-18 11:27:46 +08001405 int phyId = 0;
developer804c64f2022-10-19 13:54:40 +08001406 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
developer06a01d92022-09-07 16:32:39 +08001407 return RETURN_ERR;
developer033b37b2022-10-18 11:27:46 +08001408 phyId = radio_index_to_phy(radioIndex);
1409 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08001410
1411 return RETURN_OK;
1412}
1413
1414//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1415//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.
1416INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1417{
developerbcc556a2022-09-22 20:02:45 +08001418 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1419 // For max bit rate, we should always choose the best MCS
1420 char mode[64] = {0};
developerdbbd6782022-12-16 14:26:20 +08001421 char channel_bandwidth_str[64] = {0};
developerbcc556a2022-09-22 20:02:45 +08001422 char *tmp = NULL;
1423 UINT mode_map = 0;
1424 UINT num_subcarrier = 0;
1425 UINT code_bits = 0;
1426 float code_rate = 0; // use max code rate
1427 int NSS = 0;
1428 UINT Symbol_duration = 0;
1429 UINT GI_duration = 0;
1430 wifi_band band = band_invalid;
1431 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1432 BOOL enable = FALSE;
1433 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001434
1435 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1436 if (NULL == output_string)
1437 return RETURN_ERR;
1438
developerbcc556a2022-09-22 20:02:45 +08001439 wifi_getRadioEnable(radioIndex, &enable);
1440 if (enable == FALSE) {
1441 snprintf(output_string, 64, "0 Mb/s");
1442 return RETURN_OK;
1443 }
1444
1445 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1446 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1447 return RETURN_ERR;
1448 }
1449
1450 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1451 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1452 return RETURN_ERR;
1453 }
1454
1455 if (gi == wifi_guard_interval_3200)
1456 GI_duration = 32;
1457 else if (gi == wifi_guard_interval_1600)
1458 GI_duration = 16;
1459 else if (gi == wifi_guard_interval_800)
1460 GI_duration = 8;
1461 else // auto, 400
1462 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001463
developerbcc556a2022-09-22 20:02:45 +08001464 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1465 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1466 return RETURN_ERR;
1467 }
1468
1469 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1470 strcpy(channel_bandwidth_str, "160");
1471
1472 if (mode_map & WIFI_MODE_AX) {
1473 if (strstr(channel_bandwidth_str, "160") != NULL)
1474 num_subcarrier = 1960;
1475 else if (strstr(channel_bandwidth_str, "80") != NULL)
1476 num_subcarrier = 980;
1477 else if (strstr(channel_bandwidth_str, "40") != NULL)
1478 num_subcarrier = 468;
1479 else if (strstr(channel_bandwidth_str, "20") != NULL)
1480 num_subcarrier = 234;
1481 code_bits = 10;
1482 code_rate = (float)5/6;
1483 Symbol_duration = 128;
1484 } else if (mode_map & WIFI_MODE_AC) {
1485 if (strstr(channel_bandwidth_str, "160") != NULL)
1486 num_subcarrier = 468;
1487 else if (strstr(channel_bandwidth_str, "80") != NULL)
1488 num_subcarrier = 234;
1489 else if (strstr(channel_bandwidth_str, "40") != NULL)
1490 num_subcarrier = 108;
1491 else if (strstr(channel_bandwidth_str, "20") != NULL)
1492 num_subcarrier = 52;
1493 code_bits = 8;
1494 code_rate = (float)5/6;
1495 Symbol_duration = 32;
1496 } else if (mode_map & WIFI_MODE_N) {
1497 if (strstr(channel_bandwidth_str, "160") != NULL)
1498 num_subcarrier = 468;
1499 else if (strstr(channel_bandwidth_str, "80") != NULL)
1500 num_subcarrier = 234;
1501 else if (strstr(channel_bandwidth_str, "40") != NULL)
1502 num_subcarrier = 108;
1503 else if (strstr(channel_bandwidth_str, "20") != NULL)
1504 num_subcarrier = 52;
1505 code_bits = 6;
1506 code_rate = (float)3/4;
1507 Symbol_duration = 32;
1508 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1509 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1510 snprintf(output_string, 64, "65 Mb/s");
1511 return RETURN_OK;
1512 } else {
1513 snprintf(output_string, 64, "0 Mb/s");
1514 return RETURN_OK;
1515 }
developer06a01d92022-09-07 16:32:39 +08001516
developerbcc556a2022-09-22 20:02:45 +08001517 // Spatial streams
1518 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1519 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1520 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001521 }
developerbcc556a2022-09-22 20:02:45 +08001522
1523 // multiple 10 is to align duration unit (0.1 us)
1524 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1525 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1526
developer06a01d92022-09-07 16:32:39 +08001527 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1528
1529 return RETURN_OK;
1530}
1531#if 0
1532INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1533{
1534 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1535 char cmd[64];
1536 char buf[1024];
1537 int apIndex;
1538
1539 if (NULL == output_string)
1540 return RETURN_ERR;
1541
1542 apIndex=(radioIndex==0)?0:1;
1543
developerd946fd62022-12-08 18:03:28 +08001544 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
developer06a01d92022-09-07 16:32:39 +08001545 _syscmd(cmd,buf, sizeof(buf));
1546
1547 snprintf(output_string, 64, "%s", buf);
1548 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1549 return RETURN_OK;
1550}
1551#endif
1552
1553
1554//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1555//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.
1556INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1557{
developer963da0c2022-09-13 15:58:27 +08001558 wifi_band band = band_invalid;
1559
developer06a01d92022-09-07 16:32:39 +08001560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1561 if (NULL == output_string)
1562 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001563
1564 band = wifi_index_to_band(radioIndex);
1565
1566 memset(output_string, 0, 10);
1567 if (band == band_2_4)
1568 strcpy(output_string, "2.4GHz");
1569 else if (band == band_5)
1570 strcpy(output_string, "5GHz");
1571 else if (band == band_6)
1572 strcpy(output_string, "6GHz");
1573 else
1574 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1576
1577 return RETURN_OK;
1578#if 0
1579 char buf[MAX_BUF_SIZE]={'\0'};
1580 char str[MAX_BUF_SIZE]={'\0'};
1581 char cmd[MAX_CMD_SIZE]={'\0'};
1582 char *ch=NULL;
1583 char *ch2=NULL;
1584
1585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1586 if (NULL == output_string)
1587 return RETURN_ERR;
1588
1589
1590 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1591
1592 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1593 {
1594 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1595 return RETURN_ERR;
1596 }
1597 ch=strchr(buf,'\n');
1598 *ch='\0';
1599 ch=strchr(buf,'=');
1600 if(ch==NULL)
1601 return RETURN_ERR;
1602
1603
1604 ch++;
1605
1606 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1607 strcpy(buf,"0");
1608 if(strlen(ch) == 1)
1609 ch=strcat(buf,ch);
1610
1611
1612 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1613
1614 if(_syscmd(cmd,str,64) == RETURN_ERR)
1615 {
1616 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1617 return RETURN_ERR;
1618 }
1619
1620
1621 ch2=strchr(str,'\n');
1622 //replace \n with \0
1623 *ch2='\0';
1624 ch2=strchr(str,'=');
1625 if(ch2==NULL)
1626 {
1627 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1628 return RETURN_ERR;
1629 }
1630 else
1631 wifi_dbg_printf("%s",ch2+1);
1632
1633
1634 ch2++;
1635
1636
1637 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1638
1639 memset(buf,'\0',sizeof(buf));
1640 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1641 {
1642 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1643 return RETURN_ERR;
1644 }
1645 if (strstr(buf,"2.4") != NULL )
1646 strcpy(output_string,"2.4GHz");
1647 else if(strstr(buf,"5.") != NULL )
1648 strcpy(output_string,"5GHz");
1649 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1650
1651 return RETURN_OK;
1652#endif
1653}
1654
1655//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1656//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.
1657INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1658{
developerb7593de2022-10-18 09:51:57 +08001659 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08001660 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1661 if (NULL == output_string)
1662 return RETURN_ERR;
developerb7593de2022-10-18 09:51:57 +08001663 band = wifi_index_to_band(radioIndex);
1664
1665 if (band == band_2_4)
1666 snprintf(output_string, 64, "2.4GHz");
1667 else if (band == band_5)
1668 snprintf(output_string, 64, "5GHz");
1669 else if (band == band_6)
1670 snprintf(output_string, 64, "6GHz");
1671
developer06a01d92022-09-07 16:32:39 +08001672 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1673
1674 return RETURN_OK;
1675#if 0
1676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1677 char buf[MAX_BUF_SIZE]={'\0'};
1678 char str[MAX_BUF_SIZE]={'\0'};
1679 char cmd[MAX_CMD_SIZE]={'\0'};
1680 char *ch=NULL;
1681 char *ch2=NULL;
1682 char ch1[5]="0";
1683
1684 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1685
1686 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1687 {
1688 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1689 return RETURN_ERR;
1690 }
1691
1692 ch=strchr(buf,'\n');
1693 *ch='\0';
1694 ch=strchr(buf,'=');
1695 if(ch==NULL)
1696 return RETURN_ERR;
1697 ch++;
1698
1699 if(strlen(ch)==1)
1700 {
1701 strcat(ch1,ch);
1702
1703 }
1704 else
1705 {
1706 strcpy(ch1,ch);
1707 }
1708
1709
1710
1711 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1712 if(_syscmd(cmd,str,64) == RETURN_ERR)
1713 {
1714 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1715 return RETURN_ERR;
1716 }
1717
1718
1719 ch2=strchr(str,'\n');
1720 //replace \n with \0
1721 *ch2='\0';
1722 ch2=strchr(str,'=');
1723 if(ch2==NULL)
1724 {
1725 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1726 return RETURN_ERR;
1727 }
1728 else
1729 wifi_dbg_printf("%s",ch2+1);
1730 ch2++;
1731
1732
1733 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1734 memset(buf,'\0',sizeof(buf));
1735 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1736 {
1737 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1738 return RETURN_ERR;
1739 }
1740
1741
1742 if(strstr(buf,"2.4")!=NULL)
1743 {
1744 strcpy(output_string,"2.4GHz");
1745 }
1746 if(strstr(buf,"5.")!=NULL)
1747 {
1748 strcpy(output_string,"5GHz");
1749 }
1750 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1751 return RETURN_OK;
1752#endif
1753}
1754
1755//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1756//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.
1757INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1758{
developer963da0c2022-09-13 15:58:27 +08001759 char cmd[128]={0};
1760 char buf[128]={0};
1761 char temp_output[128] = {0};
1762 wifi_band band;
developer033b37b2022-10-18 11:27:46 +08001763 int phyId = 0;
developer963da0c2022-09-13 15:58:27 +08001764
1765 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001766 if (NULL == output_string)
1767 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001768
1769 band = wifi_index_to_band(radioIndex);
1770 if (band == band_2_4) {
1771 strcat(temp_output, "b,g,");
1772 } else if (band == band_5) {
1773 strcat(temp_output, "a,");
1774 }
developer033b37b2022-10-18 11:27:46 +08001775 phyId = radio_index_to_phy(radioIndex);
developer963da0c2022-09-13 15:58:27 +08001776 // ht capabilities
developer033b37b2022-10-18 11:27:46 +08001777 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 +08001778 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001779 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
developer963da0c2022-09-13 15:58:27 +08001780 strcat(temp_output, "n,");
1781 }
developer06a01d92022-09-07 16:32:39 +08001782
developer963da0c2022-09-13 15:58:27 +08001783 // vht capabilities
1784 if (band == band_5) {
developer033b37b2022-10-18 11:27:46 +08001785 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 +08001786 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001787 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
developer963da0c2022-09-13 15:58:27 +08001788 strcat(temp_output, "ac,");
1789 }
1790 }
1791
1792 // he capabilities
developer033b37b2022-10-18 11:27:46 +08001793 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 +08001794 _syscmd(cmd, buf, sizeof(buf));
developer8f8f0172022-10-26 14:24:43 +08001795 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
developer963da0c2022-09-13 15:58:27 +08001796 strcat(temp_output, "ax,");
1797 }
1798
1799 // Remove the last comma
1800 if (strlen(temp_output) != 0)
1801 temp_output[strlen(temp_output)-1] = '\0';
1802 strncpy(output_string, temp_output, strlen(temp_output));
1803 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001804 return RETURN_OK;
1805}
1806
1807//Get the radio operating mode, and pure mode flag. eg: "ac"
1808//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.
1809INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1810{
1811 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1812 if (NULL == output_string)
1813 return RETURN_ERR;
1814
1815 if (radioIndex == 0) {
1816 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1817 *gOnly = FALSE;
1818 *nOnly = TRUE;
1819 *acOnly = FALSE;
1820 } else {
1821 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1822 *gOnly = FALSE;
1823 *nOnly = FALSE;
1824 *acOnly = FALSE;
1825 }
1826 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1827
1828 return RETURN_OK;
1829#if 0
1830 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1831 char buf[64] = {0};
1832 char config_file[MAX_BUF_SIZE] = {0};
1833
1834 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1835 return RETURN_ERR;
1836
1837 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1838 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1839
1840 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1841 if (strlen(buf) == 0)
1842 {
1843 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1844 return RETURN_ERR;
1845 }
1846 if(strcmp(buf,"g")==0)
1847 {
1848 wifi_dbg_printf("\nG\n");
1849 *gOnly=TRUE;
1850 *nOnly=FALSE;
1851 *acOnly=FALSE;
1852 }
1853 else if(strcmp(buf,"n")==0)
1854 {
1855 wifi_dbg_printf("\nN\n");
1856 *gOnly=FALSE;
1857 *nOnly=TRUE;
1858 *acOnly=FALSE;
1859 }
1860 else if(strcmp(buf,"ac")==0)
1861 {
1862 wifi_dbg_printf("\nac\n");
1863 *gOnly=FALSE;
1864 *nOnly=FALSE;
1865 *acOnly=TRUE;
1866 }
1867 /* hostapd-5G.conf has "a" as hw_mode */
1868 else if(strcmp(buf,"a")==0)
1869 {
1870 wifi_dbg_printf("\na\n");
1871 *gOnly=FALSE;
1872 *nOnly=FALSE;
1873 *acOnly=FALSE;
1874 }
1875 else
1876 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1877
1878 //for a,n mode
1879 if(radioIndex == 1)
1880 {
1881 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1882 if(strcmp(buf,"1")==0)
1883 {
1884 strncpy(output_string, "n", 1);
1885 *nOnly=FALSE;
1886 }
1887 }
1888
1889 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1890 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1891 return RETURN_OK;
1892#endif
1893}
1894
developerdb744382022-09-13 15:34:54 +08001895INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1896{
1897 char cmd[128] = {0};
1898 char buf[64] = {0};
1899 char config_file[64] = {0};
1900 wifi_band band;
1901
1902 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1903 if(NULL == output_string || NULL == pureMode)
1904 return RETURN_ERR;
1905
1906 // grep all of the ieee80211 protocol config set to 1
developer30423732022-12-01 16:17:49 +08001907 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerdb744382022-09-13 15:34:54 +08001908 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1909 _syscmd(cmd, buf, sizeof(buf));
1910
1911 band = wifi_index_to_band(radioIndex);
1912 // puremode is a bit map
1913 *pureMode = 0;
1914 if (band == band_2_4) {
1915 strcat(output_string, "b,g");
1916 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1917 if (strstr(buf, "n") != NULL) {
1918 strcat(output_string, ",n");
1919 *pureMode |= WIFI_MODE_N;
1920 }
1921 if (strstr(buf, "ax") != NULL) {
1922 strcat(output_string, ",ax");
1923 *pureMode |= WIFI_MODE_AX;
1924 }
1925 } else if (band == band_5) {
1926 strcat(output_string, "a");
1927 *pureMode |= WIFI_MODE_A;
1928 if (strstr(buf, "n") != NULL) {
1929 strcat(output_string, ",n");
1930 *pureMode |= WIFI_MODE_N;
1931 }
1932 if (strstr(buf, "ac") != NULL) {
1933 strcat(output_string, ",ac");
1934 *pureMode |= WIFI_MODE_AC;
1935 }
1936 if (strstr(buf, "ax") != NULL) {
1937 strcat(output_string, ",ax");
1938 *pureMode |= WIFI_MODE_AX;
1939 }
1940 } else if (band == band_6) {
1941 if (strstr(buf, "ax") != NULL) {
1942 strcat(output_string, "ax");
1943 *pureMode |= WIFI_MODE_AX;
1944 }
1945 }
1946
1947 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1948 return RETURN_OK;
1949}
1950
1951// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001952INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1953{
1954 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1955 if (strcmp (channelMode,"11A") == 0)
1956 {
1957 writeBandWidth(radioIndex,"20MHz");
1958 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1959 printf("\nChannel Mode is 802.11a (5GHz)\n");
1960 }
1961 else if (strcmp (channelMode,"11NAHT20") == 0)
1962 {
1963 writeBandWidth(radioIndex,"20MHz");
1964 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1965 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1966 }
1967 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1968 {
1969 writeBandWidth(radioIndex,"40MHz");
1970 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1971 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1972 }
1973 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1974 {
1975 writeBandWidth(radioIndex,"40MHz");
1976 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1977 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1978 }
1979 else if (strcmp (channelMode,"11ACVHT20") == 0)
1980 {
1981 writeBandWidth(radioIndex,"20MHz");
1982 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1983 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1984 }
1985 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1986 {
1987 writeBandWidth(radioIndex,"40MHz");
1988 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1989 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1990 }
1991 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1992 {
1993 writeBandWidth(radioIndex,"40MHz");
1994 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1995 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1996 }
1997 else if (strcmp (channelMode,"11ACVHT80") == 0)
1998 {
1999 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2000 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2001 }
2002 else if (strcmp (channelMode,"11ACVHT160") == 0)
2003 {
2004 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2005 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2006 }
2007 else if (strcmp (channelMode,"11B") == 0)
2008 {
2009 writeBandWidth(radioIndex,"20MHz");
2010 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2011 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2012 }
2013 else if (strcmp (channelMode,"11G") == 0)
2014 {
2015 writeBandWidth(radioIndex,"20MHz");
2016 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2017 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2018 }
2019 else if (strcmp (channelMode,"11NGHT20") == 0)
2020 {
2021 writeBandWidth(radioIndex,"20MHz");
2022 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2023 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2024 }
2025 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2026 {
2027 writeBandWidth(radioIndex,"40MHz");
2028 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2029 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2030 }
2031 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2032 {
2033 writeBandWidth(radioIndex,"40MHz");
2034 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2035 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2036 }
2037 else
2038 {
2039 return RETURN_ERR;
2040 }
2041 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2042
2043 return RETURN_OK;
2044}
2045
developerdb744382022-09-13 15:34:54 +08002046// Set the radio operating mode, and pure mode flag.
2047INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2048{
2049 int num_hostapd_support_mode = 3; // n, ac, ax
2050 struct params list[num_hostapd_support_mode];
2051 char config_file[64] = {0};
2052 char bandwidth[16] = {0};
2053 int mode_check_bit = 1 << 3; // n mode
developer517a9792022-10-05 19:37:42 +08002054
developerdb744382022-09-13 15:34:54 +08002055
2056 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2057 // Set radio mode
2058 list[0].name = "ieee80211n";
2059 list[1].name = "ieee80211ac";
2060 list[2].name = "ieee80211ax";
2061 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2062
2063 // check the bit map from n to ax, and set hostapd config
developer517a9792022-10-05 19:37:42 +08002064 if (pureMode & WIFI_MODE_N)
developerdb744382022-09-13 15:34:54 +08002065 list[0].value = "1";
2066 else
2067 list[0].value = "0";
developer517a9792022-10-05 19:37:42 +08002068 if (pureMode & WIFI_MODE_AC)
developerdb744382022-09-13 15:34:54 +08002069 list[1].value = "1";
2070 else
2071 list[1].value = "0";
developer517a9792022-10-05 19:37:42 +08002072 if (pureMode & WIFI_MODE_AX)
developerdb744382022-09-13 15:34:54 +08002073 list[2].value = "1";
2074 else
2075 list[2].value = "0";
2076 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2077
2078 if (channelMode == NULL || strlen(channelMode) == 0)
2079 return RETURN_OK;
2080 // Set bandwidth
2081 if (strstr(channelMode, "40") != NULL)
2082 strcpy(bandwidth, "40MHz");
2083 else if (strstr(channelMode, "80") != NULL)
2084 strcpy(bandwidth, "80MHz");
2085 else if (strstr(channelMode, "160") != NULL)
2086 strcpy(bandwidth, "160MHz");
2087 else // 11A, 11B, 11G....
2088 strcpy(bandwidth, "20MHz");
2089
2090 writeBandWidth(radioIndex, bandwidth);
2091 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2092
2093 wifi_reloadAp(radioIndex);
2094 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2095
2096 return RETURN_OK;
2097}
2098
developer1d12ebf2022-10-04 15:13:38 +08002099INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2100
2101 char config_file[64] = {0};
developeref938762022-10-19 17:21:01 +08002102 char buf[64] = {0};
developer1d12ebf2022-10-04 15:13:38 +08002103 struct params params = {0};
2104 wifi_band band = band_invalid;
2105
2106 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2107
2108 band = wifi_index_to_band(radioIndex);
developerc9e88f32022-10-06 17:09:56 +08002109
2110 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
developer1d12ebf2022-10-04 15:13:38 +08002111 return RETURN_ERR;
2112 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2113 return RETURN_ERR;
developerc9e88f32022-10-06 17:09:56 +08002114 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2115 return RETURN_ERR;
developer1d12ebf2022-10-04 15:13:38 +08002116
2117 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2118 params.name = "hw_mode";
2119 params.value = hw_mode;
2120 wifi_hostapdWrite(config_file, &params, 1);
2121 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2122
developeref938762022-10-19 17:21:01 +08002123 if (band == band_2_4) {
2124 if (strncmp(hw_mode, "b", 1) == 0) {
2125 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2126 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2127 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2128 snprintf(buf, sizeof(buf), "%s", "1,2");
2129 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2130 } else {
2131 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2132
2133 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2134 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2135 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2136 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2137 }
2138 }
2139
developer1d12ebf2022-10-04 15:13:38 +08002140 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2141 return RETURN_OK;
2142}
2143
developere8988ba2022-10-18 17:42:30 +08002144INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2145{
2146 char config_file[64] = {0};
2147 struct params params = {0};
2148 wifi_band band = band_invalid;
2149
2150 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2151
2152 band = wifi_index_to_band(radioIndex);
developer30423732022-12-01 16:17:49 +08002153 if (band != band_2_4)
2154 return RETURN_OK;
developere8988ba2022-10-18 17:42:30 +08002155
2156 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2157 params.name = "noscan";
2158 params.value = noscan;
2159 wifi_hostapdWrite(config_file, &params, 1);
2160 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2161
2162 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2163 return RETURN_OK;
2164}
2165
developer06a01d92022-09-07 16:32:39 +08002166//Get the list of supported channel. eg: "1-11"
2167//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.
2168INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2169{
developer6318ed52022-09-13 15:17:58 +08002170 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002171 if (NULL == output_string)
2172 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002173 char cmd[256] = {0};
2174 char buf[128] = {0};
2175 BOOL dfs_enable = false;
developer033b37b2022-10-18 11:27:46 +08002176 int phyId = 0;
2177
developer6318ed52022-09-13 15:17:58 +08002178 // Parse possible channel number and separate them with commas.
2179 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer033b37b2022-10-18 11:27:46 +08002180 phyId = radio_index_to_phy(radioIndex);
developer76989232022-10-04 14:13:19 +08002181 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
developer6318ed52022-09-13 15:17:58 +08002182 if (dfs_enable)
developer033b37b2022-10-18 11:27:46 +08002183 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 +08002184 else
developer033b37b2022-10-18 11:27:46 +08002185 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 +08002186
2187 _syscmd(cmd,buf,sizeof(buf));
2188 strncpy(output_string, buf, sizeof(buf));
2189
2190 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2191 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002192}
2193
2194//Get the list for used channel. eg: "1,6,9,11"
2195//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.
2196INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2197{
developerd946fd62022-12-08 18:03:28 +08002198 char interface_name[16] = {0};
developerf5745ee2022-10-05 16:09:53 +08002199 char cmd[128] = {0};
2200 char buf[128] = {0};
2201 char config_file[64] = {0};
2202 int channel = 0;
2203 int freq = 0;
2204 int bandwidth = 0;
2205 int center_freq = 0;
2206 int center_channel = 0;
2207 int channel_delta = 0;
2208 wifi_band band = band_invalid;
2209
2210 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2211
developer06a01d92022-09-07 16:32:39 +08002212 if (NULL == output_string)
2213 return RETURN_ERR;
2214
developerd946fd62022-12-08 18:03:28 +08002215 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2216 return RETURN_ERR;
2217 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
developerf5745ee2022-10-05 16:09:53 +08002218 _syscmd(cmd, buf, sizeof(buf));
2219 if (strlen(buf) == 0) {
2220 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2221 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002222 }
developerf5745ee2022-10-05 16:09:53 +08002223 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2224
2225 if (bandwidth == 20) {
2226 snprintf(output_string, 256, "%d", channel);
2227 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002228 }
developerf5745ee2022-10-05 16:09:53 +08002229
2230 center_channel = ieee80211_frequency_to_channel(center_freq);
2231
2232 band = wifi_index_to_band(radioIndex);
2233 if (band == band_2_4 && bandwidth == 40) {
2234 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2235 memset(buf, 0, sizeof(buf));
2236 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2237
2238 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel") == 0) && channel < 10) {
2239 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2240 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel") == 0) && channel > 4) {
2241 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2242 } else {
2243 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2244 return RETURN_ERR;
2245 }
2246 } else if (band == band_5 || band == band_6){
2247 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2248 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2249 channel_delta = (bandwidth-20)/10;
2250 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2251 } else
2252 return RETURN_ERR;
2253
2254 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002255 return RETURN_OK;
2256}
2257
2258//Get the running channel number
2259INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2260{
developer5b398df2022-11-17 20:39:48 +08002261 char channel_str[16] = {0};
2262 char config_file[128] = {0};
developer06a01d92022-09-07 16:32:39 +08002263
developer5b398df2022-11-17 20:39:48 +08002264 if (output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002265 return RETURN_ERR;
2266
developer5b398df2022-11-17 20:39:48 +08002267 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2268 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
developer06a01d92022-09-07 16:32:39 +08002269
developer5b398df2022-11-17 20:39:48 +08002270 *output_ulong = strtoul(channel_str, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08002271
developer06a01d92022-09-07 16:32:39 +08002272 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002273}
2274
2275
2276INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2277{
2278 char cmd[1024] = {0}, buf[5] = {0};
developerdbbd6782022-12-16 14:26:20 +08002279 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002280
2281 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2282 if (NULL == output_ulong)
2283 return RETURN_ERR;
2284
developer06a01d92022-09-07 16:32:39 +08002285 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
developerdbbd6782022-12-16 14:26:20 +08002286 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2287 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002288 _syscmd(cmd,buf,sizeof(buf));
2289 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2290 if (*output_ulong == 0) {
2291 return RETURN_ERR;
2292 }
2293
2294 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2295 return RETURN_OK;
2296}
2297
2298//Storing the previous channel value
2299INT wifi_storeprevchanval(INT radioIndex)
2300{
2301 char buf[256] = {0};
2302 char output[4]={'\0'};
2303 char config_file[MAX_BUF_SIZE] = {0};
2304 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2305 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2306 if(radioIndex == 0)
2307 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2308 else if(radioIndex == 1)
2309 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2310 system(buf);
2311 Radio_flag = FALSE;
2312 return RETURN_OK;
2313}
2314
2315//Set the running channel number
2316INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2317{
developer76989232022-10-04 14:13:19 +08002318 // We only write hostapd config here
2319 char str_channel[8]={0};
2320 char *list_channel;
2321 char config_file[128] = {0};
2322 char possible_channels[256] = {0};
2323 int max_radio_num = 0;
2324 struct params list = {0};
developer06a01d92022-09-07 16:32:39 +08002325
developer76989232022-10-04 14:13:19 +08002326 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002327
developer76989232022-10-04 14:13:19 +08002328 // Check valid
2329 sprintf(str_channel, "%lu", channel);
developer06a01d92022-09-07 16:32:39 +08002330
developer76989232022-10-04 14:13:19 +08002331 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2332 list_channel = strtok(possible_channels, ",");
2333 while(true)
developer06a01d92022-09-07 16:32:39 +08002334 {
developer76989232022-10-04 14:13:19 +08002335 if(list_channel == NULL) { // input not in the list
2336 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2337 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002338 }
developer76989232022-10-04 14:13:19 +08002339 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2340 break;
2341 list_channel = strtok(NULL, ",");
developer06a01d92022-09-07 16:32:39 +08002342 }
2343
developer76989232022-10-04 14:13:19 +08002344 list.name = "channel";
2345 list.value = str_channel;
2346 wifi_getMaxRadioNumber(&max_radio_num);
2347 for(int i=0; i<=MAX_APS/max_radio_num;i++)
developer06a01d92022-09-07 16:32:39 +08002348 {
developer76989232022-10-04 14:13:19 +08002349 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2350 wifi_hostapdWrite(config_file, &list, 1);
developer06a01d92022-09-07 16:32:39 +08002351 }
2352
developer76989232022-10-04 14:13:19 +08002353 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002354 return RETURN_OK;
developer76989232022-10-04 14:13:19 +08002355}
developer06a01d92022-09-07 16:32:39 +08002356
2357INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2358{
developer76989232022-10-04 14:13:19 +08002359 struct params list[2];
developer06a01d92022-09-07 16:32:39 +08002360 char str_idx[16];
developer76989232022-10-04 14:13:19 +08002361 char config_file[64];
2362 int max_num_radios = 0;
2363 wifi_band band = band_invalid;
2364
2365 band = wifi_index_to_band(radioIndex);
2366 if (band == band_2_4)
2367 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002368
developer30423732022-12-01 16:17:49 +08002369 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
developer76989232022-10-04 14:13:19 +08002370 list[0].name = "vht_oper_centr_freq_seg0_idx";
2371 list[0].value = str_idx;
2372 list[1].name = "he_oper_centr_freq_seg0_idx";
2373 list[1].value = str_idx;
developer06a01d92022-09-07 16:32:39 +08002374
developer76989232022-10-04 14:13:19 +08002375 wifi_getMaxRadioNumber(&max_num_radios);
2376 for(int i=0; i<=MAX_APS/max_num_radios; i++)
developer06a01d92022-09-07 16:32:39 +08002377 {
developer76989232022-10-04 14:13:19 +08002378 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2379 if (band == band_6)
2380 wifi_hostapdWrite(config_file, &list[1], 1);
2381 else
2382 wifi_hostapdWrite(config_file, list, 2);
developer06a01d92022-09-07 16:32:39 +08002383 }
2384
2385 return RETURN_OK;
2386}
2387
2388//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2389//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2390INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2391{
2392 //Set to wifi config only. Wait for wifi reset to apply.
2393 char buf[256] = {0};
2394 char str_channel[256] = {0};
2395 int count = 0;
2396 ULONG Value = 0;
2397 FILE *fp = NULL;
2398 if(enable == TRUE)
2399 {
developer06a01d92022-09-07 16:32:39 +08002400 wifi_setRadioChannel(radioIndex,Value);
developer06a01d92022-09-07 16:32:39 +08002401 }
developer5884e982022-10-06 10:52:50 +08002402 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002403}
2404
developer0b246d12022-09-30 15:24:20 +08002405INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2406{
2407 if (output_bool == NULL)
2408 return RETURN_ERR;
2409
2410 *output_bool = TRUE;
2411
2412 return RETURN_OK;
2413}
2414
developer06a01d92022-09-07 16:32:39 +08002415INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2416{
2417 if (NULL == output_bool)
2418 return RETURN_ERR;
2419 *output_bool=FALSE;
2420 return RETURN_OK;
2421}
2422
2423INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2424{
2425 if (NULL == output_bool)
2426 return RETURN_ERR;
2427 *output_bool=FALSE;
2428 return RETURN_OK;
2429}
2430
2431INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2432{
2433 //Set to wifi config only. Wait for wifi reset to apply.
2434 return RETURN_OK;
2435}
2436
2437INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2438{
2439 return RETURN_OK;
2440}
2441
2442INT wifi_factoryResetAP(int apIndex)
2443{
developer838cca92022-10-03 13:19:57 +08002444 char ap_config_file[64] = {0};
2445 char cmd[128] = {0};
2446
developer06a01d92022-09-07 16:32:39 +08002447 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002448
2449 wifi_setApEnable(apIndex, FALSE);
2450 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2451 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2452 wifi_setApEnable(apIndex, TRUE);
2453
developer06a01d92022-09-07 16:32:39 +08002454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002455
developer06a01d92022-09-07 16:32:39 +08002456 return RETURN_OK;
2457}
2458
2459//To set Band Steering AP group
2460//To-do
2461INT wifi_setBandSteeringApGroup(char *ApGroup)
2462{
2463 return RETURN_OK;
2464}
2465
developer1e5aa162022-09-13 16:06:24 +08002466INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2467{
2468 char config_file[128] = {'\0'};
2469 char buf[128] = {'\0'};
2470
2471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2472 if (dtimInterval == NULL)
2473 return RETURN_ERR;
2474
2475 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2476 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2477
2478 if (strlen(buf) == 0) {
2479 *dtimInterval = 2;
2480 } else {
2481 *dtimInterval = strtoul(buf, NULL, 10);
2482 }
2483
2484 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2485 return RETURN_OK;
2486}
2487
developer06a01d92022-09-07 16:32:39 +08002488INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2489{
developer5f222492022-09-13 15:21:52 +08002490 struct params params={0};
2491 char config_file[MAX_BUF_SIZE] = {'\0'};
2492 char buf[MAX_BUF_SIZE] = {'\0'};
2493
2494 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2495 if (dtimInterval < 1 || dtimInterval > 255) {
developer5f222492022-09-13 15:21:52 +08002496 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
developer30423732022-12-01 16:17:49 +08002497 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08002498 }
2499
2500 params.name = "dtim_period";
2501 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2502 params.value = buf;
2503
2504 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2505 wifi_hostapdWrite(config_file, &params, 1);
2506 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2507
2508 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2509 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002510}
2511
2512//Check if the driver support the Dfs
2513INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2514{
developer78a15382022-11-02 10:57:40 +08002515 wifi_band band = band_invalid;
developer06a01d92022-09-07 16:32:39 +08002516 if (NULL == output_bool)
2517 return RETURN_ERR;
developer78a15382022-11-02 10:57:40 +08002518 *output_bool=FALSE;
2519
2520 band = wifi_index_to_band(radioIndex);
2521 if (band == band_5)
2522 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08002523 return RETURN_OK;
2524}
2525
2526//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.
2527//The value of this parameter is a comma seperated list of channel number
2528INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2529{
2530 if (NULL == output_pool)
2531 return RETURN_ERR;
2532 if (radioIndex==1)
2533 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2534 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2535
2536 return RETURN_OK;
2537}
2538
2539INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2540{
2541 //Set to wifi config. And apply instantly.
2542 return RETURN_OK;
2543}
2544
2545INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2546{
2547 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2548 return RETURN_ERR;
2549 *output_interval_seconds=1800;
2550 *output_dwell_milliseconds=40;
2551
2552 return RETURN_OK;
2553}
2554
2555INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2556{
2557 //Set to wifi config. And apply instantly.
2558 return RETURN_OK;
2559}
2560
developerbfc18512022-10-05 17:54:28 +08002561INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2562{
2563 if (output_bool == NULL)
2564 return RETURN_ERR;
2565 *output_bool = true;
2566 return RETURN_OK;
2567}
2568
2569INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2570{
2571 return RETURN_OK;
2572}
2573
developer06a01d92022-09-07 16:32:39 +08002574//Get the Dfs enable status
2575INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2576{
developer9964b5b2022-09-13 15:59:34 +08002577 char buf[16] = {0};
2578 FILE *f = NULL;
developer9964b5b2022-09-13 15:59:34 +08002579
2580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2581
developer30423732022-12-01 16:17:49 +08002582 if (output_bool == NULL)
2583 return RETURN_ERR;
2584
developer9964b5b2022-09-13 15:59:34 +08002585 *output_bool = TRUE; // default
developer9964b5b2022-09-13 15:59:34 +08002586 f = fopen(DFS_ENABLE_FILE, "r");
2587 if (f != NULL) {
2588 fgets(buf, 2, f);
developer76989232022-10-04 14:13:19 +08002589 if (strncmp(buf, "0", 1) == 0)
developer9964b5b2022-09-13 15:59:34 +08002590 *output_bool = FALSE;
2591 fclose(f);
2592 }
2593 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002594 return RETURN_OK;
2595}
2596
2597//Set the Dfs enable status
2598INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2599{
developer9964b5b2022-09-13 15:59:34 +08002600 char config_file[128] = {0};
2601 FILE *f = NULL;
2602 struct params params={0};
developer9964b5b2022-09-13 15:59:34 +08002603
2604 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2605
developer9964b5b2022-09-13 15:59:34 +08002606 f = fopen(DFS_ENABLE_FILE, "w");
2607 if (f == NULL)
2608 return RETURN_ERR;
2609 fprintf(f, "%d", enable);
2610 fclose(f);
2611
2612 params.name = "acs_exclude_dfs";
developer76989232022-10-04 14:13:19 +08002613 params.value = enable?"0":"1";
developer9964b5b2022-09-13 15:59:34 +08002614 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2615 wifi_hostapdWrite(config_file, &params, 1);
2616 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2617
2618 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2619
developer9964b5b2022-09-13 15:59:34 +08002620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer76989232022-10-04 14:13:19 +08002621 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002622}
2623
2624//Check if the driver support the AutoChannelRefreshPeriod
2625INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2626{
2627 if (NULL == output_bool)
2628 return RETURN_ERR;
2629 *output_bool=FALSE; //not support
2630
2631 return RETURN_OK;
2632}
2633
2634//Get the ACS refresh period in seconds
2635INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2636{
2637 if (NULL == output_ulong)
2638 return RETURN_ERR;
2639 *output_ulong=300;
2640
2641 return RETURN_OK;
2642}
2643
2644//Set the ACS refresh period in seconds
2645INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2646{
2647 return RETURN_ERR;
2648}
2649
2650//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2651//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.
2652INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2653{
developer70490032022-09-13 15:45:20 +08002654 char cmd[128] = {0}, buf[64] = {0};
2655 char interface_name[64] = {0};
2656 int ret = 0, len=0;
2657 BOOL radio_enable = FALSE;
2658
2659 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2660
developer06a01d92022-09-07 16:32:39 +08002661 if (NULL == output_string)
2662 return RETURN_ERR;
2663
developer70490032022-09-13 15:45:20 +08002664 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2665 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002666
developer70490032022-09-13 15:45:20 +08002667 if (radio_enable != TRUE)
2668 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002669
developerd946fd62022-12-08 18:03:28 +08002670 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2671 return RETURN_ERR;
2672 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6", interface_name);
developer06a01d92022-09-07 16:32:39 +08002673 ret = _syscmd(cmd, buf, sizeof(buf));
2674 len = strlen(buf);
2675 if((ret != 0) || (len == 0))
2676 {
2677 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2678 return RETURN_ERR;
2679 }
2680
2681 buf[len-1] = '\0';
2682 snprintf(output_string, 64, "%sMHz", buf);
2683 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2684
2685#if 0
2686 //TODO: revisit below implementation
2687 char output_buf[8]={0};
2688 char bw_value[10];
2689 char config_file[MAX_BUF_SIZE] = {0};
2690
2691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2692 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2693 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2694 readBandWidth(radioIndex,bw_value);
2695
2696 if(strstr (output_buf,"0") != NULL )
2697 {
2698 strcpy(output_string,bw_value);
2699 }
2700 else if (strstr (output_buf,"1") != NULL)
2701 {
2702 strcpy(output_string,"80MHz");
2703 }
2704 else if (strstr (output_buf,"2") != NULL)
2705 {
2706 strcpy(output_string,"160MHz");
2707 }
2708 else if (strstr (output_buf,"3") != NULL)
2709 {
2710 strcpy(output_string,"80+80");
2711 }
2712 else
2713 {
2714 strcpy(output_string,"Auto");
2715 }
2716 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2717#endif
2718
2719 return RETURN_OK;
2720}
2721
2722//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002723INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002724{
developerf7a466e2022-09-29 11:55:56 +08002725 char config_file[128];
2726 char set_value[16];
2727 struct params params[2];
2728 int max_radio_num = 0;
2729
developer06a01d92022-09-07 16:32:39 +08002730 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002731
developerf7a466e2022-09-29 11:55:56 +08002732 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002733 return RETURN_ERR;
2734
developerf7a466e2022-09-29 11:55:56 +08002735 if(strstr(bandwidth,"80+80") != NULL)
2736 strcpy(set_value, "3");
2737 else if(strstr(bandwidth,"160") != NULL)
2738 strcpy(set_value, "2");
2739 else if(strstr(bandwidth,"80") != NULL)
2740 strcpy(set_value, "1");
2741 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2742 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002743 else
2744 {
developerf7a466e2022-09-29 11:55:56 +08002745 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002746 return RETURN_ERR;
2747 }
2748
developerf7a466e2022-09-29 11:55:56 +08002749 params[0].name = "vht_oper_chwidth";
2750 params[0].value = set_value;
2751 params[1].name = "he_oper_chwidth";
2752 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002753
developerf7a466e2022-09-29 11:55:56 +08002754 wifi_getMaxRadioNumber(&max_radio_num);
2755 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002756 {
developerf7a466e2022-09-29 11:55:56 +08002757 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2758 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002759 }
2760
2761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2762 return RETURN_OK;
2763}
2764
2765//Getting current radio extension channel
2766INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2767{
2768 CHAR buf[150] = {0};
2769 CHAR cmd[150] = {0};
2770 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2771 _syscmd(cmd, buf, sizeof(buf));
2772 if(NULL != strstr(buf,"HT40+"))
2773 strcpy(Value,"AboveControlChannel");
2774 else if(NULL != strstr(buf,"HT40-"))
2775 strcpy(Value,"BelowControlChannel");
2776 return RETURN_OK;
2777}
2778
2779//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2780//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.
2781INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2782{
2783 if (NULL == output_string)
2784 return RETURN_ERR;
2785
2786 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2787#if 0
2788 CHAR Value[100] = {0};
2789 if (NULL == output_string)
2790 return RETURN_ERR;
2791 if(radioIndex == 0)
2792 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2793 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2794 {
2795 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2796 if(strcmp(Value,"40MHz") == 0)
2797 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2798 else
2799 strcpy(Value,"Auto");
2800 }
2801 strcpy(output_string,Value);
2802#endif
2803
2804 return RETURN_OK;
2805}
2806
2807//Set the extension channel.
2808INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2809{
2810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2811 struct params params={'\0'};
2812 char config_file[MAX_BUF_SIZE] = {0};
2813 char ext_channel[127]={'\0'};
developer033b37b2022-10-18 11:27:46 +08002814 int max_radio_num =0;
developer06a01d92022-09-07 16:32:39 +08002815 params.name = "ht_capab";
2816
developer033b37b2022-10-18 11:27:46 +08002817 if(NULL!= strstr(string,"Above"))
2818 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
2819 else if(NULL!= strstr(string,"Below"))
2820 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
2821 else
2822 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
2823
developer06a01d92022-09-07 16:32:39 +08002824
2825 params.value = ext_channel;
developer033b37b2022-10-18 11:27:46 +08002826
2827 wifi_getMaxRadioNumber(&max_radio_num);
2828 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002829 {
developer033b37b2022-10-18 11:27:46 +08002830 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer06a01d92022-09-07 16:32:39 +08002831 wifi_hostapdWrite(config_file, &params, 1);
2832 }
2833
2834 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2835 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2836 return RETURN_OK;
2837}
2838
2839//Get the guard interval value. eg "400nsec" or "800nsec"
2840//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.
2841INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2842{
developer454b9462022-09-13 15:29:16 +08002843 wifi_guard_interval_t GI;
2844
2845 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2846
2847 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002848 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002849
2850 if (GI == wifi_guard_interval_400)
2851 strcpy(output_string, "400nsec");
2852 else if (GI == wifi_guard_interval_800)
2853 strcpy(output_string, "800nsec");
2854 else if (GI == wifi_guard_interval_1600)
2855 strcpy(output_string, "1600nsec");
2856 else if (GI == wifi_guard_interval_3200)
2857 strcpy(output_string, "3200nsec");
2858 else
developer78a15382022-11-02 10:57:40 +08002859 strcpy(output_string, "Auto");
developer06a01d92022-09-07 16:32:39 +08002860
developer454b9462022-09-13 15:29:16 +08002861 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002862 return RETURN_OK;
2863}
2864
2865//Set the guard interval value.
2866INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2867{
developer454b9462022-09-13 15:29:16 +08002868 wifi_guard_interval_t GI;
2869 int ret = 0;
2870
2871 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2872
2873 if (strcmp(string, "400nsec") == 0)
2874 GI = wifi_guard_interval_400;
developer254882b2022-09-30 17:12:31 +08002875 else if (strcmp(string , "800nsec") == 0)
developer454b9462022-09-13 15:29:16 +08002876 GI = wifi_guard_interval_800;
2877 else if (strcmp(string , "1600nsec") == 0)
2878 GI = wifi_guard_interval_1600;
2879 else if (strcmp(string , "3200nsec") == 0)
2880 GI = wifi_guard_interval_3200;
developer254882b2022-09-30 17:12:31 +08002881 else
2882 GI = wifi_guard_interval_auto;
developer454b9462022-09-13 15:29:16 +08002883
2884 ret = wifi_setGuardInterval(radioIndex, GI);
2885
2886 if (ret == RETURN_ERR) {
2887 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2888 return RETURN_ERR;
2889 }
2890
2891 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2892 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002893}
2894
2895//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2896INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2897{
developerf49437e2022-09-29 19:58:21 +08002898 char buf[32]={0};
2899 char mcs_file[64] = {0};
2900 char cmd[64] = {0};
2901 int mode_bitmap = 0;
2902
2903 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2904 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002905 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002906 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2907
2908 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2909 _syscmd(cmd, buf, sizeof(buf));
2910 if (strlen(buf) > 0)
2911 *output_int = strtol(buf, NULL, 10);
2912 else {
2913 // output the max MCS for the current radio mode
2914 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2915 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2916 return RETURN_ERR;
2917 }
2918 if (mode_bitmap & WIFI_MODE_AX) {
2919 *output_int = 11;
2920 } else if (mode_bitmap & WIFI_MODE_AC) {
2921 *output_int = 9;
2922 } else if (mode_bitmap & WIFI_MODE_N) {
2923 *output_int = 7;
2924 }
2925 }
2926 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002927
2928 return RETURN_OK;
2929}
2930
2931//Set the Modulation Coding Scheme index
2932INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2933{
developerf49437e2022-09-29 19:58:21 +08002934 // 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).
2935 char config_file[64] = {0};
2936 char set_value[16] = {0};
2937 char mcs_file[32] = {0};
2938 wifi_band band = band_invalid;
2939 struct params set_config = {0};
2940 FILE *f = NULL;
2941
2942 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2943
2944 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2945
developer78a15382022-11-02 10:57:40 +08002946 // -1 means auto
2947 if (MCS > 15 || MCS < -1) {
developerf49437e2022-09-29 19:58:21 +08002948 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2949 return RETURN_ERR;
2950 }
2951
developer78a15382022-11-02 10:57:40 +08002952 if (MCS > 9 || MCS == -1)
2953 strcpy(set_value, "2");
2954 else if (MCS > 7)
developerf49437e2022-09-29 19:58:21 +08002955 strcpy(set_value, "1");
2956 else
developer78a15382022-11-02 10:57:40 +08002957 strcpy(set_value, "0");
developerf49437e2022-09-29 19:58:21 +08002958
2959 set_config.name = "he_basic_mcs_nss_set";
2960 set_config.value = set_value;
2961
2962 wifi_hostapdWrite(config_file, &set_config, 1);
2963 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2964
2965 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2966 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2967 f = fopen(mcs_file, "w");
2968 if (f == NULL) {
2969 fprintf(stderr, "%s: fopen failed\n", __func__);
2970 return RETURN_ERR;
2971 }
2972 fprintf(f, "%d", MCS);
2973 fclose(f);
2974
2975 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2976 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002977}
2978
2979//Get supported Transmit Power list, eg : "0,25,50,75,100"
2980//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.
2981INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2982{
2983 if (NULL == output_list)
2984 return RETURN_ERR;
2985 snprintf(output_list, 64,"0,25,50,75,100");
2986 return RETURN_OK;
2987}
2988
developera5005b62022-09-13 15:43:35 +08002989//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002990//The transmite power level is in units of full power for this radio.
2991INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2992{
developerd946fd62022-12-08 18:03:28 +08002993 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08002994 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002995 char buf[16]={0};
2996 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002997
developera5005b62022-09-13 15:43:35 +08002998 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002999 return RETURN_ERR;
3000
developerd946fd62022-12-08 18:03:28 +08003001 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3002 return RETURN_ERR;
3003 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08003004 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003005
developera5005b62022-09-13 15:43:35 +08003006 *output_ulong = strtol(buf, NULL, 10);
3007
3008 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003009 return RETURN_OK;
3010}
3011
3012//Set Transmit Power
3013//The transmite power level is in units of full power for this radio.
3014INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3015{
developerd946fd62022-12-08 18:03:28 +08003016 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +08003017 char *support;
developer06a01d92022-09-07 16:32:39 +08003018 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08003019 char buf[128]={0};
3020 char txpower_str[64] = {0};
3021 int txpower = 0;
3022 int maximum_tx = 0;
developer033b37b2022-10-18 11:27:46 +08003023 int phyId = 0;
developera5005b62022-09-13 15:43:35 +08003024
3025 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003026
developerd946fd62022-12-08 18:03:28 +08003027 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3028 return RETURN_ERR;
3029 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08003030 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08003031 maximum_tx = strtol(buf, NULL, 10);
3032
3033 // Get the Tx power supported list and check that is the input in the list
3034 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3035 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3036 support = strtok(buf, ",");
3037 while(true)
3038 {
3039 if(support == NULL) { // input not in the list
3040 wifi_dbg_printf("Input value is invalid.\n");
3041 return RETURN_ERR;
3042 }
3043 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3044 break;
3045 }
3046 support = strtok(NULL, ",");
3047 }
3048 txpower = TransmitPower*maximum_tx/100;
developer033b37b2022-10-18 11:27:46 +08003049 phyId = radio_index_to_phy(radioIndex);
3050 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
developera5005b62022-09-13 15:43:35 +08003051 _syscmd(cmd, buf, sizeof(buf));
3052 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003053
3054 return RETURN_OK;
3055}
3056
3057//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3058INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3059{
3060 if (NULL == Supported)
3061 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003062 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08003063
3064 return RETURN_OK;
3065}
3066
3067//Get 80211h feature enable
3068INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3069{
developer3885fec2022-09-13 15:13:47 +08003070 char buf[64]={'\0'};
3071 char config_file[64] = {'\0'};
3072
3073 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3074 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08003075 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08003076
3077 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3078 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08003079
developer3885fec2022-09-13 15:13:47 +08003080 if (strncmp(buf, "1", 1) == 0)
3081 *enable = TRUE;
3082 else
3083 *enable = FALSE;
3084
3085 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003086 return RETURN_OK;
3087}
3088
3089//Set 80211h feature enable
3090INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3091{
developer3885fec2022-09-13 15:13:47 +08003092 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3093 struct params params={'\0'};
3094 char config_file[MAX_BUF_SIZE] = {0};
3095
3096 params.name = "ieee80211h";
3097
3098 if (enable) {
3099 params.value = "1";
3100 } else {
3101 params.value = "0";
3102 }
3103
3104 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3105 wifi_hostapdWrite(config_file, &params, 1);
3106
3107 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3108 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3109 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003110}
3111
3112//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.
3113INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3114{
3115 if (NULL == output)
3116 return RETURN_ERR;
3117 *output=100;
3118
3119 return RETURN_OK;
3120}
3121
3122//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.
3123INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3124{
3125 if (NULL == output)
3126 return RETURN_ERR;
3127 *output = -99;
3128
3129 return RETURN_OK;
3130}
3131
3132INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3133{
3134 return RETURN_ERR;
3135}
3136
3137
3138//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3139INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3140{
developerd946fd62022-12-08 18:03:28 +08003141 char interface_name[16] = {0};
developer5f222492022-09-13 15:21:52 +08003142 char cmd[MAX_BUF_SIZE]={'\0'};
3143 char buf[MAX_CMD_SIZE]={'\0'};
3144
3145 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3146 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003147 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003148
developerd946fd62022-12-08 18:03:28 +08003149 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3150 return RETURN_ERR;
3151 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer5f222492022-09-13 15:21:52 +08003152 _syscmd(cmd, buf, sizeof(buf));
3153 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003154
developer5f222492022-09-13 15:21:52 +08003155 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003156 return RETURN_OK;
3157}
3158
3159INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3160{
developer5f222492022-09-13 15:21:52 +08003161 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3162 struct params params={'\0'};
3163 char buf[MAX_BUF_SIZE] = {'\0'};
3164 char config_file[MAX_BUF_SIZE] = {'\0'};
3165
developer5b398df2022-11-17 20:39:48 +08003166 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3167 return RETURN_ERR;
3168
developer5f222492022-09-13 15:21:52 +08003169 params.name = "beacon_int";
3170 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3171 params.value = buf;
3172
3173 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3174 wifi_hostapdWrite(config_file, &params, 1);
3175
3176 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3177 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3178 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003179}
3180
3181//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.
3182INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3183{
developer06a01d92022-09-07 16:32:39 +08003184 //TODO: need to revisit below implementation
3185 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003186 char temp_output[128] = {0};
3187 char temp_TransmitRates[64] = {0};
3188 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003189
3190 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3191 if (NULL == output)
3192 return RETURN_ERR;
3193 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003194 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3195
3196 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3197 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3198 } else {
3199 temp = strtok(temp_TransmitRates," ");
3200 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003201 {
developere9d0abd2022-09-13 15:40:57 +08003202 // Convert 100 kbps to Mbps
3203 temp[strlen(temp)-1]=0;
3204 if((temp[0]=='5') && (temp[1]=='\0'))
3205 {
3206 temp="5.5";
3207 }
3208 strcat(temp_output,temp);
3209 temp = strtok(NULL," ");
3210 if(temp!=NULL)
3211 {
3212 strcat(temp_output,",");
3213 }
developer06a01d92022-09-07 16:32:39 +08003214 }
developere9d0abd2022-09-13 15:40:57 +08003215 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003216 }
developer06a01d92022-09-07 16:32:39 +08003217 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003218 return RETURN_OK;
3219}
3220
3221INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3222{
3223 char *temp;
3224 char temp1[128];
3225 char temp_output[128];
3226 char temp_TransmitRates[128];
3227 char set[128];
3228 char sub_set[128];
3229 int set_count=0,subset_count=0;
3230 int set_index=0,subset_index=0;
3231 char *token;
3232 int flag=0, i=0;
3233 struct params params={'\0'};
3234 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08003235 wifi_band band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +08003236
3237 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3238 if(NULL == TransmitRates)
3239 return RETURN_ERR;
3240 strcpy(sub_set,TransmitRates);
3241
3242 //Allow only supported Data transmit rate to be set
3243 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3244 token = strtok(sub_set,",");
3245 while( token != NULL ) /* split the basic rate to be set, by comma */
3246 {
3247 sub_set[subset_count]=atoi(token);
3248 subset_count++;
3249 token=strtok(NULL,",");
3250 }
3251 token=strtok(set,",");
3252 while(token!=NULL) /* split the supported rate by comma */
3253 {
3254 set[set_count]=atoi(token);
3255 set_count++;
3256 token=strtok(NULL,",");
3257 }
3258 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3259 {
3260 for(set_index=0;set_index < set_count;set_index++)
3261 {
3262 flag=0;
3263 if(sub_set[subset_index]==set[set_index])
3264 break;
3265 else
3266 flag=1; /* No match found */
3267 }
3268 if(flag==1)
3269 return RETURN_ERR; //If value not found return Error
3270 }
3271 strcpy(temp_TransmitRates,TransmitRates);
3272
3273 for(i=0;i<strlen(temp_TransmitRates);i++)
3274 {
3275 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
developeref938762022-10-19 17:21:01 +08003276 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08003277 {
3278 continue;
3279 }
3280 else
3281 {
3282 return RETURN_ERR;
3283 }
3284 }
3285 strcpy(temp_output,"");
3286 temp = strtok(temp_TransmitRates,",");
3287 while(temp!=NULL)
3288 {
3289 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08003290 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08003291 {
developeref938762022-10-19 17:21:01 +08003292 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08003293 {
3294 return RETURN_ERR;
3295 }
3296 }
3297
3298 if(strcmp(temp,"5.5")==0)
3299 {
3300 strcpy(temp1,"55");
3301 }
3302 else
3303 {
3304 strcat(temp1,"0");
3305 }
3306 strcat(temp_output,temp1);
3307 temp = strtok(NULL,",");
3308 if(temp!=NULL)
3309 {
3310 strcat(temp_output," ");
3311 }
3312 }
3313 strcpy(TransmitRates,temp_output);
3314
3315 params.name= "basic_rates";
3316 params.value =TransmitRates;
3317
3318 wifi_dbg_printf("\n%s:",__func__);
3319 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3320 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3321 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3322 wifi_hostapdWrite(config_file,&params,1);
3323 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3324 return RETURN_OK;
3325}
3326
3327//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3328INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3329{
3330 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3331 FILE *fp = NULL;
3332 char path[256] = {0}, output_string[256] = {0};
3333 int count = 0;
3334 char *interface = NULL;
3335
3336 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3337 if (fp == NULL)
3338 {
3339 printf("Failed to run command in Function %s\n", __FUNCTION__);
3340 return RETURN_ERR;
3341 }
3342 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3343 {
3344 interface = strchr(path, '=');
3345
3346 if (interface != NULL)
3347 {
3348 strcpy(output_string, interface + 1);
3349 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3350 interface_name[count] = output_string[count];
3351
3352 interface_name[count] = '\0';
3353 }
3354 }
3355 pclose(fp);
3356 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3357 return RETURN_OK;
3358}
3359
3360INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3361{
3362 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3363 output_struct->radio_BytesSent = 0;
3364 output_struct->radio_BytesReceived = 0;
3365 output_struct->radio_PacketsSent = 0;
3366 output_struct->radio_PacketsReceived = 0;
3367 output_struct->radio_ErrorsSent = 0;
3368 output_struct->radio_ErrorsReceived = 0;
3369 output_struct->radio_DiscardPacketsSent = 0;
3370 output_struct->radio_DiscardPacketsReceived = 0;
3371 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3372 return RETURN_OK;
3373}
3374
3375
3376INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3377{
3378 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3379 CHAR buf[MAX_CMD_SIZE] = {0};
3380 CHAR Value[MAX_BUF_SIZE] = {0};
3381 FILE *fp = NULL;
3382
3383 if (ifname == NULL || strlen(ifname) <= 1)
3384 return RETURN_OK;
3385
3386 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3387 system(buf);
3388
3389 fp = fopen("/tmp/Radio_Stats.txt", "r");
3390 if(fp == NULL)
3391 {
3392 printf("/tmp/Radio_Stats.txt not exists \n");
3393 return RETURN_ERR;
3394 }
3395 fclose(fp);
3396
3397 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3398 File_Reading(buf, Value);
3399 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3400
3401 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3402 File_Reading(buf, Value);
3403 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3404
3405 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3406 File_Reading(buf, Value);
3407 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3408
3409 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3410 File_Reading(buf, Value);
3411 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3412
3413 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3414 File_Reading(buf, Value);
3415 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3416
3417 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3418 File_Reading(buf, Value);
3419 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3420
3421 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3422 File_Reading(buf, Value);
3423 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3424
3425 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3426 File_Reading(buf, Value);
3427 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3428
3429 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3430 return RETURN_OK;
3431}
3432
3433INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3434{
3435 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3436 CHAR buf[MAX_CMD_SIZE] = {0};
3437 FILE *fp = NULL;
3438 INT count = 0;
3439
3440 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3441 {
3442 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3443 File_Reading(buf, status);
3444 }
3445 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3446 return RETURN_OK;
3447}
3448
3449//Get detail radio traffic static info
3450INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3451{
3452
3453#if 0
3454 //ifconfig radio_x
3455 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3456 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3457 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3458 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3459
3460 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3461 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3462 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.
3463 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.
3464
3465 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3466 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].
3467 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3468 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.
3469 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
3470 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
3471 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
3472 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
3473 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
3474
3475 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
3476 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
3477 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
3478 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.
3479
3480 return RETURN_OK;
3481#endif
3482
developera91d99f2022-09-29 15:59:10 +08003483 CHAR interface_name[64] = {0};
developera91d99f2022-09-29 15:59:10 +08003484 BOOL iface_status = FALSE;
3485 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003486
3487 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3488 if (NULL == output_struct)
3489 return RETURN_ERR;
3490
developerdbbd6782022-12-16 14:26:20 +08003491 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3492 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003493
developera91d99f2022-09-29 15:59:10 +08003494 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003495
developera91d99f2022-09-29 15:59:10 +08003496 if (iface_status == TRUE)
3497 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3498 else
3499 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003500
developera91d99f2022-09-29 15:59:10 +08003501 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3502 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3503 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3504 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3505 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3506 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3507 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3508 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003509
3510 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3511 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].
3512 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3513 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.
3514 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
3515 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
3516 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
3517 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
3518 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
3519
3520 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
3521 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
3522 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
3523 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.
3524
3525 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3526
3527 return RETURN_OK;
3528}
3529
3530//Set radio traffic static Measureing rules
3531INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3532{
3533 //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
3534 // Else, save the MeasuringRate and MeasuringInterval for future usage
3535
3536 return RETURN_OK;
3537}
3538
3539//To start or stop RadioTrafficStats
3540INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3541{
3542 //zqiu: If the RadioTrafficStats process running
3543 // if(enable)
3544 // return RETURN_OK.
3545 // else
3546 // Stop RadioTrafficStats process
3547 // Else
3548 // if(enable)
3549 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3550 // else
3551 // return RETURN_OK.
3552
3553 return RETURN_OK;
3554}
3555
3556//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
3557INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3558{
3559 //zqiu: Please ignor signalIndex.
3560 if (NULL == SignalLevel)
3561 return RETURN_ERR;
3562 *SignalLevel=(radioIndex==0)?-19:-19;
3563
3564 return RETURN_OK;
3565}
3566
3567//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3568INT wifi_applyRadioSettings(INT radioIndex)
3569{
3570 return RETURN_OK;
3571}
3572
3573//Get the radio index assocated with this SSID entry
3574INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3575{
developer5b398df2022-11-17 20:39:48 +08003576 if(NULL == radioIndex)
developer06a01d92022-09-07 16:32:39 +08003577 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08003578 int max_radio_num = 0;
3579 wifi_getMaxRadioNumber(&max_radio_num);
3580 *radioIndex = ssidIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003581 return RETURN_OK;
3582}
3583
3584//Device.WiFi.SSID.{i}.Enable
3585//Get SSID enable configuration parameters (not the SSID enable status)
3586INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3587{
3588 if (NULL == output_bool)
3589 return RETURN_ERR;
3590
developer06a01d92022-09-07 16:32:39 +08003591 return wifi_getApEnable(ssidIndex, output_bool);
3592}
3593
3594//Device.WiFi.SSID.{i}.Enable
3595//Set SSID enable configuration parameters
3596INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3597{
developer06a01d92022-09-07 16:32:39 +08003598 return wifi_setApEnable(ssidIndex, enable);
3599}
3600
3601//Device.WiFi.SSID.{i}.Status
3602//Get the SSID enable status
3603INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3604{
3605 char cmd[MAX_CMD_SIZE]={0};
3606 char buf[MAX_BUF_SIZE]={0};
3607 BOOL output_bool;
3608
3609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3610 if (NULL == output_string)
3611 return RETURN_ERR;
developer804c64f2022-10-19 13:54:40 +08003612
developer06a01d92022-09-07 16:32:39 +08003613 wifi_getApEnable(ssidIndex,&output_bool);
3614 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3615
3616 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3617 return RETURN_OK;
3618}
3619
3620// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3621INT wifi_getSSIDName(INT apIndex, CHAR *output)
3622{
3623 char config_file[MAX_BUF_SIZE] = {0};
3624
3625 if (NULL == output)
3626 return RETURN_ERR;
3627
3628 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3629 wifi_hostapdRead(config_file,"ssid",output,32);
3630
3631 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3632 return RETURN_OK;
3633}
3634
3635// Set a max 32 byte string and sets an internal variable to the SSID name
3636INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3637{
3638 char str[MAX_BUF_SIZE]={'\0'};
3639 char cmd[MAX_CMD_SIZE]={'\0'};
3640 struct params params;
3641 char config_file[MAX_BUF_SIZE] = {0};
3642
3643 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3644 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3645 return RETURN_ERR;
3646
3647 params.name = "ssid";
3648 params.value = ssid_string;
3649 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3650 wifi_hostapdWrite(config_file, &params, 1);
3651 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3653
3654 return RETURN_OK;
3655}
3656
3657//Get the BSSID
3658INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3659{
3660 char cmd[MAX_CMD_SIZE]="";
3661
3662 if (NULL == output_string)
3663 return RETURN_ERR;
3664
3665 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3666 {
developer1d57d002022-10-12 18:03:15 +08003667 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 +08003668 _syscmd(cmd, output_string, 64);
3669 return RETURN_OK;
3670 }
3671 strncpy(output_string, "\0", 1);
3672
3673 return RETURN_ERR;
3674}
3675
3676//Get the MAC address associated with this Wifi SSID
3677INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3678{
3679 wifi_getBaseBSSID(ssidIndex,output_string);
3680 return RETURN_OK;
3681}
3682
3683//Get the basic SSID traffic static info
3684//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3685//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3686INT wifi_applySSIDSettings(INT ssidIndex)
3687{
developerd946fd62022-12-08 18:03:28 +08003688 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08003689 BOOL status = false;
3690 char cmd[MAX_CMD_SIZE] = {0};
3691 char buf[MAX_CMD_SIZE] = {0};
3692 int apIndex, ret;
developer033b37b2022-10-18 11:27:46 +08003693 int max_radio_num = 0;
3694 int radioIndex = 0;
3695
3696 wifi_getMaxRadioNumber(&max_radio_num);
3697
3698 radioIndex = ssidIndex % max_radio_num;
developer06a01d92022-09-07 16:32:39 +08003699
3700 wifi_getApEnable(ssidIndex,&status);
3701 // Do not apply when ssid index is disabled
3702 if (status == false)
3703 return RETURN_OK;
3704
3705 /* Doing full remove and add for ssid Index
3706 * Not all hostapd options are supported with reload
3707 * for example macaddr_acl
3708 */
3709 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3710 return RETURN_ERR;
3711
3712 ret = wifi_setApEnable(ssidIndex,true);
3713
3714 /* Workaround for hostapd issue with multiple bss definitions
3715 * when first created interface will be removed
3716 * then all vaps other vaps on same phy are removed
3717 * after calling setApEnable to false readd all enabled vaps */
developer033b37b2022-10-18 11:27:46 +08003718 for(int i=0; i < MAX_APS/max_radio_num; i++) {
developerd946fd62022-12-08 18:03:28 +08003719 apIndex = max_radio_num*i+radioIndex;
3720 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
3721 return RETURN_ERR;
3722 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
developer06a01d92022-09-07 16:32:39 +08003723 _syscmd(cmd, buf, sizeof(buf));
3724 if(*buf == '1')
3725 wifi_setApEnable(apIndex, true);
3726 }
3727
3728 return ret;
3729}
3730
developera3c68b92022-09-13 15:27:29 +08003731struct channels_noise {
3732 int channel;
3733 int noise;
3734};
3735
3736// Return noise array for each channel
3737int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3738{
developerd946fd62022-12-08 18:03:28 +08003739 char interface_name[16] = {0};
developera3c68b92022-09-13 15:27:29 +08003740 FILE *f = NULL;
3741 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003742 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003743 size_t len = 0;
3744 ssize_t read = 0;
3745 int tmp = 0, arr_index = -1;
3746
developerd946fd62022-12-08 18:03:28 +08003747 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3748 return RETURN_ERR;
3749 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
developera3c68b92022-09-13 15:27:29 +08003750
3751 if ((f = popen(cmd, "r")) == NULL) {
3752 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3753 return RETURN_ERR;
3754 }
developer5550e242022-09-30 09:59:32 +08003755
3756 while(fgets(line, sizeof(line), f) != NULL) {
3757 if(arr_index < channels_num){
3758 sscanf(line, "%d", &tmp);
3759 if (tmp > 0) { // channel frequency, the first line must be frequency
3760 arr_index++;
3761 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3762 } else { // noise
3763 channels_noise_arr[arr_index].noise = tmp;
3764 }
3765 }else{
3766 break;
developera3c68b92022-09-13 15:27:29 +08003767 }
3768 }
developera3c68b92022-09-13 15:27:29 +08003769 pclose(f);
3770 return RETURN_OK;
3771}
3772
developer06a01d92022-09-07 16:32:39 +08003773//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3774//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3775INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3776{
developera3c68b92022-09-13 15:27:29 +08003777 int index = -1;
3778 wifi_neighbor_ap2_t *scan_array = NULL;
3779 char cmd[256]={0};
3780 char buf[128]={0};
3781 char file_name[32] = {0};
3782 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003783 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08003784 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08003785 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003786 int freq=0;
3787 FILE *f = NULL;
3788 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003789 int channels_num = 0;
3790 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003791 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003792 bool filter_enable = false;
3793 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08003794 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08003795
developer615510b2022-09-27 10:14:35 +08003796 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003797
developerd946fd62022-12-08 18:03:28 +08003798 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3799 return RETURN_ERR;
3800
developera3c68b92022-09-13 15:27:29 +08003801 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3802 f = fopen(file_name, "r");
3803 if (f != NULL) {
3804 fgets(filter_SSID, sizeof(file_name), f);
3805 if (strlen(filter_SSID) != 0)
3806 filter_enable = true;
3807 fclose(f);
3808 }
3809
developer033b37b2022-10-18 11:27:46 +08003810 phyId = radio_index_to_phy(radioIndex);
3811 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer06a01d92022-09-07 16:32:39 +08003812 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003813 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003814
developer5550e242022-09-30 09:59:32 +08003815
developer06a01d92022-09-07 16:32:39 +08003816
developerd946fd62022-12-08 18:03:28 +08003817 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3818 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
developera3c68b92022-09-13 15:27:29 +08003819 fprintf(stderr, "cmd: %s\n", cmd);
3820 if ((f = popen(cmd, "r")) == NULL) {
3821 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3822 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003823 }
developer5550e242022-09-30 09:59:32 +08003824
3825 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3826 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3827
developer615510b2022-09-27 10:14:35 +08003828 ret = fgets(line, sizeof(line), f);
3829 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003830 if(strstr(line, "BSS") != NULL) { // new neighbor info
3831 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3832 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3833 // 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 +08003834
developera3c68b92022-09-13 15:27:29 +08003835 if (!filter_BSS) {
3836 index++;
3837 wifi_neighbor_ap2_t *tmp;
3838 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3839 if (tmp == NULL) { // no more memory to use
3840 index--;
3841 wifi_dbg_printf("%s: realloc failed\n", __func__);
3842 break;
3843 }
3844 scan_array = tmp;
3845 }
3846 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3847
3848 filter_BSS = false;
3849 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3850 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3851 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3852 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3853 } else if (strstr(line, "freq") != NULL) {
3854 sscanf(line," freq: %d", &freq);
3855 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3856
3857 if (freq >= 2412 && freq <= 2484) {
3858 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3859 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3860 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3861 }
3862 else if (freq >= 5160 && freq <= 5805) {
3863 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3864 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3865 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3866 }
3867
3868 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003869 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003870 for (int i = 0; i < channels_num; i++) {
3871 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3872 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3873 break;
3874 }
3875 }
3876 }
3877 } else if (strstr(line, "beacon interval") != NULL) {
3878 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3879 } else if (strstr(line, "signal") != NULL) {
3880 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3881 } else if (strstr(line,"SSID") != NULL) {
3882 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3883 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3884 filter_BSS = true;
3885 }
3886 } else if (strstr(line, "Supported rates") != NULL) {
3887 char SRate[80] = {0}, *tmp = NULL;
3888 memset(buf, 0, sizeof(buf));
3889 strcpy(SRate, line);
3890 tmp = strtok(SRate, ":");
3891 tmp = strtok(NULL, ":");
3892 strcpy(buf, tmp);
3893 memset(SRate, 0, sizeof(SRate));
3894
3895 tmp = strtok(buf, " \n");
3896 while (tmp != NULL) {
3897 strcat(SRate, tmp);
3898 if (SRate[strlen(SRate) - 1] == '*') {
3899 SRate[strlen(SRate) - 1] = '\0';
3900 }
3901 strcat(SRate, ",");
3902
3903 tmp = strtok(NULL, " \n");
3904 }
3905 SRate[strlen(SRate) - 1] = '\0';
3906 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3907 } else if (strstr(line, "DTIM") != NULL) {
3908 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3909 } else if (strstr(line, "VHT capabilities") != NULL) {
3910 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3911 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3912 } else if (strstr(line, "HT capabilities") != NULL) {
3913 strcat(scan_array[index].ap_SupportedStandards, ",n");
3914 strcpy(scan_array[index].ap_OperatingStandards, "n");
3915 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003916 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003917 sscanf(line," * channel width: %d", &vht_channel_width);
3918 if(vht_channel_width == 1) {
3919 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3920 } else {
3921 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3922 }
3923 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3924 continue;
3925 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003926 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003927 sscanf(line," * secondary channel offset: %s", &buf);
3928 if (!strcmp(buf, "above")) {
3929 //40Mhz +
3930 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3931 }
3932 else if (!strcmp(buf, "below")) {
3933 //40Mhz -
3934 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3935 } else {
3936 //20Mhz
3937 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3938 }
3939 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3940 continue;
3941 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003942 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3943 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3944 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003945 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3946 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003947 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003948 else
developer615510b2022-09-27 10:14:35 +08003949 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003950 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003951 if (strstr(line, "HE80/5GHz") != NULL) {
3952 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3953 ret = fgets(line, sizeof(line), f);
3954 } else
3955 continue;
developera3c68b92022-09-13 15:27:29 +08003956 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003957 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003958 }
developer615510b2022-09-27 10:14:35 +08003959 continue;
developera3c68b92022-09-13 15:27:29 +08003960 } else if (strstr(line, "WPA") != NULL) {
3961 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3962 } else if (strstr(line, "RSN") != NULL) {
3963 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3964 } else if (strstr(line, "Group cipher") != NULL) {
3965 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3966 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3967 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3968 }
3969 }
developer615510b2022-09-27 10:14:35 +08003970 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003971 }
3972
3973 if (!filter_BSS) {
3974 *output_array_size = index + 1;
3975 } else {
3976 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3977 *output_array_size = index;
3978 }
3979 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003980 pclose(f);
developer5550e242022-09-30 09:59:32 +08003981 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003982 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003983 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003984}
3985
3986//>> Deprecated: used for old RDKB code.
3987INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3988{
3989 INT status = RETURN_ERR;
3990
3991 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3992 output_struct->wifi_PLCPErrorCount = 0;
3993 output_struct->wifi_FCSErrorCount = 0;
3994 output_struct->wifi_InvalidMACCount = 0;
3995 output_struct->wifi_PacketsOtherReceived = 0;
3996 output_struct->wifi_Noise = 0;
3997 status = RETURN_OK;
3998 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3999 return status;
4000}
4001
4002INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4003{
developerd946fd62022-12-08 18:03:28 +08004004 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004005 char cmd[128] = {0};
4006 char buf[1280] = {0};
developer06a01d92022-09-07 16:32:39 +08004007 char *pos = NULL;
4008
4009 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4010 if (NULL == output_struct)
4011 return RETURN_ERR;
4012
developerd946fd62022-12-08 18:03:28 +08004013 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4014 return RETURN_ERR;
4015
developer06a01d92022-09-07 16:32:39 +08004016 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4017
developerd946fd62022-12-08 18:03:28 +08004018 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004019 _syscmd(cmd, buf, sizeof(buf));
4020
4021 pos = buf;
4022 if ((pos = strstr(pos, "RX packets:")) == NULL)
4023 return RETURN_ERR;
4024 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4025
4026 if ((pos = strstr(pos, "TX packets:")) == NULL)
4027 return RETURN_ERR;
4028 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4029
4030 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4031 return RETURN_ERR;
4032 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4033
4034 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4035 return RETURN_ERR;
4036 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4037
developerd946fd62022-12-08 18:03:28 +08004038 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08004039 _syscmd(cmd, buf, sizeof(buf));
4040 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4041
4042#if 0
4043 //TODO: need to revisit below implementation
4044 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4045 char interface_name[MAX_BUF_SIZE] = {0};
4046 char interface_status[MAX_BUF_SIZE] = {0};
4047 char Value[MAX_BUF_SIZE] = {0};
4048 char buf[MAX_CMD_SIZE] = {0};
4049 char cmd[MAX_CMD_SIZE] = {0};
4050 FILE *fp = NULL;
4051
4052 if (NULL == output_struct) {
4053 return RETURN_ERR;
4054 }
4055
4056 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4057
4058 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4059 {
4060 if(apIndex == 0) //private_wifi for 2.4G
4061 {
4062 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4063 }
4064 else if(apIndex == 1) //private_wifi for 5G
4065 {
4066 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4067 }
4068 else if(apIndex == 4) //public_wifi for 2.4G
4069 {
4070 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4071 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4072 {
4073 return RETURN_ERR;
4074 }
4075 if(buf[0] == '#')//tp-link
4076 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4077 else//tenda
4078 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4079 }
4080 else if(apIndex == 5) //public_wifi for 5G
4081 {
4082 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4083 }
4084
4085 GetIfacestatus(interface_name, interface_status);
4086
4087 if(0 != strcmp(interface_status, "1"))
4088 return RETURN_ERR;
4089
4090 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4091 system(cmd);
4092
4093 fp = fopen("/tmp/SSID_Stats.txt", "r");
4094 if(fp == NULL)
4095 {
4096 printf("/tmp/SSID_Stats.txt not exists \n");
4097 return RETURN_ERR;
4098 }
4099 fclose(fp);
4100
4101 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4102 File_Reading(buf, Value);
4103 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4104
4105 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4106 File_Reading(buf, Value);
4107 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4108
4109 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4110 File_Reading(buf, Value);
4111 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4112
4113 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4114 File_Reading(buf, Value);
4115 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4116
4117 /* There is no specific parameter from caller to associate the value wifi_Associations */
4118 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4119 //_syscmd(cmd, buf, sizeof(buf));
4120 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4121 }
4122#endif
4123 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4124 return RETURN_OK;
4125}
4126
4127INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4128{
4129 char interface_name[MAX_BUF_SIZE] = {0};
4130 char interface_status[MAX_BUF_SIZE] = {0};
4131 char Value[MAX_BUF_SIZE] = {0};
4132 char buf[MAX_CMD_SIZE] = {0};
4133 char cmd[MAX_CMD_SIZE] = {0};
4134 FILE *fp = NULL;
4135
4136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4137 if (NULL == output_struct)
4138 return RETURN_ERR;
4139
4140 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4141
developerdbbd6782022-12-16 14:26:20 +08004142 if (GetInterfaceName(apIndex,interface_name) != RETURN_OK)
4143 return RETURN_ERR;
4144 GetIfacestatus(interface_name, interface_status);
developer06a01d92022-09-07 16:32:39 +08004145
developerd946fd62022-12-08 18:03:28 +08004146 if(0 != strcmp(interface_status, "1"))
4147 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08004148
developerd946fd62022-12-08 18:03:28 +08004149 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4150 system(cmd);
developer06a01d92022-09-07 16:32:39 +08004151
developerd946fd62022-12-08 18:03:28 +08004152 fp = fopen("/tmp/SSID_Stats.txt", "r");
4153 if(fp == NULL)
4154 {
4155 printf("/tmp/SSID_Stats.txt not exists \n");
4156 return RETURN_ERR;
4157 }
4158 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08004159
developerd946fd62022-12-08 18:03:28 +08004160 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4161 File_Reading(buf, Value);
4162 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004163
developerd946fd62022-12-08 18:03:28 +08004164 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4165 File_Reading(buf, Value);
4166 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004167
developerd946fd62022-12-08 18:03:28 +08004168 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4169 File_Reading(buf, Value);
4170 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004171
developerd946fd62022-12-08 18:03:28 +08004172 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4173 File_Reading(buf, Value);
4174 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08004175
4176 output_struct->wifi_UnicastPacketsSent = 0;
4177 output_struct->wifi_UnicastPacketsReceived = 0;
4178 output_struct->wifi_MulticastPacketsSent = 0;
4179 output_struct->wifi_MulticastPacketsReceived = 0;
4180 output_struct->wifi_BroadcastPacketsSent = 0;
4181 output_struct->wifi_BroadcastPacketsRecevied = 0;
4182 output_struct->wifi_UnknownPacketsReceived = 0;
4183
4184 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4185 return RETURN_OK;
4186}
4187
4188INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4189{
4190 INT status = RETURN_ERR;
4191
4192 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4193 //Below values should get updated from hal
4194 output_struct->wifi_RetransCount=0;
4195 output_struct->wifi_FailedRetransCount=0;
4196 output_struct->wifi_RetryCount=0;
4197 output_struct->wifi_MultipleRetryCount=0;
4198 output_struct->wifi_ACKFailureCount=0;
4199 output_struct->wifi_AggregatedPacketCount=0;
4200
4201 status = RETURN_OK;
4202 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4203
4204 return status;
4205}
4206
4207INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4208{
4209 INT status = RETURN_ERR;
4210 UINT index;
4211 wifi_neighbor_ap_t *pt=NULL;
4212
4213 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4214 *output_array_size=2;
4215 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4216 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4217 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4218 strcpy(pt->ap_Radio,"");
4219 strcpy(pt->ap_SSID,"");
4220 strcpy(pt->ap_BSSID,"");
4221 strcpy(pt->ap_Mode,"");
4222 pt->ap_Channel=1;
4223 pt->ap_SignalStrength=0;
4224 strcpy(pt->ap_SecurityModeEnabled,"");
4225 strcpy(pt->ap_EncryptionMode,"");
4226 strcpy(pt->ap_OperatingFrequencyBand,"");
4227 strcpy(pt->ap_SupportedStandards,"");
4228 strcpy(pt->ap_OperatingStandards,"");
4229 strcpy(pt->ap_OperatingChannelBandwidth,"");
4230 pt->ap_BeaconPeriod=1;
4231 pt->ap_Noise=0;
4232 strcpy(pt->ap_BasicDataTransferRates,"");
4233 strcpy(pt->ap_SupportedDataTransferRates,"");
4234 pt->ap_DTIMPeriod=1;
4235 pt->ap_ChannelUtilization = 1;
4236 }
4237
4238 status = RETURN_OK;
4239 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4240
4241 return status;
4242}
4243
4244//----------------- AP HAL -------------------------------
4245
4246//>> Deprecated: used for old RDKB code.
4247INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4248{
4249 if (NULL == output_ulong || NULL == output_struct)
4250 return RETURN_ERR;
4251 *output_ulong = 0;
4252 *output_struct = NULL;
4253 return RETURN_OK;
4254}
4255
4256#ifdef HAL_NETLINK_IMPL
4257static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4258 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4259 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4260 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4261 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4262 char mac_addr[20];
4263 static int count=0;
4264 int rate=0;
4265
4266 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4267
4268 nla_parse(tb,
4269 NL80211_ATTR_MAX,
4270 genlmsg_attrdata(gnlh, 0),
4271 genlmsg_attrlen(gnlh, 0),
4272 NULL);
4273
4274 if(!tb[NL80211_ATTR_STA_INFO]) {
4275 fprintf(stderr, "sta stats missing!\n");
4276 return NL_SKIP;
4277 }
4278
4279
4280 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4281 fprintf(stderr, "failed to parse nested attributes!\n");
4282 return NL_SKIP;
4283 }
4284
4285 //devIndex starts from 1
4286 if( ++count == out->wifi_devIndex )
4287 {
4288 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4289 //Getting the mac addrress
4290 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4291
4292 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4293 fprintf(stderr, "failed to parse nested rate attributes!");
4294 return NL_SKIP;
4295 }
4296
4297 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4298 if(rinfo[NL80211_RATE_INFO_BITRATE])
4299 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4300 out->wifi_devTxRate = rate/10;
4301 }
4302
4303 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4304 fprintf(stderr, "failed to parse nested rate attributes!");
4305 return NL_SKIP;
4306 }
4307
4308 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4309 if(rinfo[NL80211_RATE_INFO_BITRATE])
4310 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4311 out->wifi_devRxRate = rate/10;
4312 }
4313 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4314 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4315
4316 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4317 count = 0; //starts the count for next cycle
4318 return NL_STOP;
4319 }
4320
4321 return NL_SKIP;
4322
4323}
4324#endif
4325
4326INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4327{
4328#ifdef HAL_NETLINK_IMPL
developer30423732022-12-01 16:17:49 +08004329 Netlink nl = {0};
4330 char if_name[10] = {0};
developerd946fd62022-12-08 18:03:28 +08004331 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004332
developer30423732022-12-01 16:17:49 +08004333 wifi_device_info_t info = {0};
developer06a01d92022-09-07 16:32:39 +08004334 info.wifi_devIndex = devIndex;
4335
developerd946fd62022-12-08 18:03:28 +08004336 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4337 return RETURN_ERR;
4338
4339 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004340
4341 nl.id = initSock80211(&nl);
4342
4343 if (nl.id < 0) {
4344 fprintf(stderr, "Error initializing netlink \n");
4345 return -1;
4346 }
4347
4348 struct nl_msg* msg = nlmsg_alloc();
4349
4350 if (!msg) {
4351 fprintf(stderr, "Failed to allocate netlink message.\n");
4352 nlfree(&nl);
4353 return -2;
4354 }
4355
4356 genlmsg_put(msg,
4357 NL_AUTO_PORT,
4358 NL_AUTO_SEQ,
4359 nl.id,
4360 0,
4361 NLM_F_DUMP,
4362 NL80211_CMD_GET_STATION,
4363 0);
4364
4365 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4366 nl_send_auto(nl.socket, msg);
4367 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4368 nl_recvmsgs(nl.socket, nl.cb);
4369 nlmsg_free(msg);
4370 nlfree(&nl);
4371
4372 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4373 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4374 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4375 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4376 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4377 return RETURN_OK;
4378#else
4379 //iw utility to retrieve station information
4380#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4381#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4382#define MACFILE "/tmp/wifi_AssoMac.txt"
4383#define TXRATEFILE "/tmp/wifi_txrate.txt"
4384#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4385 FILE *file = NULL;
4386 char if_name[10] = {'\0'};
4387 char pipeCmd[256] = {'\0'};
developer30423732022-12-01 16:17:49 +08004388 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08004389 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08004390 int count = 0, device = 0;
developer06a01d92022-09-07 16:32:39 +08004391
developerd946fd62022-12-08 18:03:28 +08004392 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4393 return RETURN_ERR;
4394
4395 snprintf(if_name,sizeof(if_name),"%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004396
4397 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4398 file = popen(pipeCmd, "r");
4399
4400 if(file == NULL)
4401 return RETURN_ERR; //popen failed
4402
4403 fgets(line, sizeof line, file);
4404 device = atoi(line);
4405 pclose(file);
4406
4407 if(device == 0)
4408 return RETURN_ERR; //No devices are connected
4409
4410 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4411 system(pipeCmd);
4412
4413 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4414
4415 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4416
4417 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4418
4419 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4420
4421 //devIndex starts from 1, ++count
4422 if((file = fopen(SIGNALFILE, "r")) != NULL )
4423 {
4424 for(count =0;fgets(line, sizeof line, file) != NULL;)
4425 {
4426 if (++count == devIndex)
4427 {
4428 output_struct->wifi_devSignalStrength = atoi(line);
4429 break;
4430 }
4431 }
4432 fclose(file);
4433 }
4434 else
4435 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4436
4437 if((file = fopen(MACFILE, "r")) != NULL )
4438 {
4439 for(count =0;fgets(line, sizeof line, file) != NULL;)
4440 {
4441 if (++count == devIndex)
4442 {
4443 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]);
4444 break;
4445 }
4446 }
4447 fclose(file);
4448 }
4449 else
4450 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4451
4452 if((file = fopen(TXRATEFILE, "r")) != NULL )
4453 {
4454 for(count =0;fgets(line, sizeof line, file) != NULL;)
4455 {
4456 if (++count == devIndex)
4457 {
4458 output_struct->wifi_devTxRate = atoi(line);
4459 break;
4460 }
4461 }
4462 fclose(file);
4463 }
4464 else
4465 fprintf(stderr,"fopen wifi_txrate.txt failed");
4466
4467 if((file = fopen(RXRATEFILE, "r")) != NULL)
4468 {
4469 for(count =0;fgets(line, sizeof line, file) != NULL;)
4470 {
4471 if (++count == devIndex)
4472 {
4473 output_struct->wifi_devRxRate = atoi(line);
4474 break;
4475 }
4476 }
4477 fclose(file);
4478 }
4479 else
4480 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4481
4482 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4483
4484 return RETURN_OK;
4485#endif
4486}
4487
4488INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4489{
4490 if (NULL == device)
4491 return RETURN_ERR;
4492 return RETURN_OK;
4493}
4494//<<
4495
4496
4497//--------------wifi_ap_hal-----------------------------
4498//enables CTS protection for the radio used by this AP
4499INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4500{
4501 //save config and Apply instantly
4502 return RETURN_ERR;
4503}
4504
4505// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4506INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4507{
developer463d39a2022-09-13 15:32:51 +08004508 char config_file[64] = {'\0'};
4509 char buf[64] = {'\0'};
4510 struct params list;
4511
4512 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4513 list.name = "ht_coex";
4514 snprintf(buf, sizeof(buf), "%d", enable);
4515 list.value = buf;
4516
4517 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4518 wifi_hostapdWrite(config_file, &list, 1);
4519 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4520
4521 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4522
4523 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004524}
4525
4526//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4527INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4528{
developerea4bcce2022-09-13 15:26:13 +08004529 char config_file[MAX_BUF_SIZE] = {'\0'};
4530 char buf[MAX_BUF_SIZE] = {'\0'};
4531 struct params list;
4532
4533 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4534 if (threshold < 256 || threshold > 2346 )
4535 return RETURN_ERR;
4536 list.name = "fragm_threshold";
4537 snprintf(buf, sizeof(buf), "%d", threshold);
4538 list.value = buf;
4539
4540 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4541 wifi_hostapdWrite(config_file, &list, 1);
4542 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004543
developerea4bcce2022-09-13 15:26:13 +08004544 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004545
4546 return RETURN_OK;
4547}
4548
4549// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4550INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4551{
developer51a927d2022-09-13 15:42:22 +08004552 char config_file[64] = {'\0'};
4553 char cmd[128] = {'\0'};
4554 char buf[64] = {'\0'};
4555 char stbc_config[16] = {'\0'};
4556 wifi_band band;
4557 int iterator = 0;
4558 BOOL current_stbc = FALSE;
4559
4560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4561
4562 band = wifi_index_to_band(radioIndex);
4563 if (band == band_invalid)
4564 return RETURN_ERR;
4565
4566 if (band == band_2_4)
4567 iterator = 1;
4568 else if (band == band_5)
4569 iterator = 2;
4570 else
4571 return RETURN_OK;
4572
4573 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4574
4575 // set ht and vht config
4576 for (int i = 0; i < iterator; i++) {
4577 memset(stbc_config, 0, sizeof(stbc_config));
4578 memset(cmd, 0, sizeof(cmd));
4579 memset(buf, 0, sizeof(buf));
4580 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4581 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4582 _syscmd(cmd, buf, sizeof(buf));
4583 if (strlen(buf) != 0)
4584 current_stbc = TRUE;
4585 if (current_stbc == STBC_Enable)
4586 continue;
4587
4588 if (STBC_Enable == TRUE) {
4589 // Append the STBC flags in capab config
4590 memset(cmd, 0, sizeof(cmd));
4591 if (i == 0)
developer6372c2b2022-10-27 17:39:51 +08004592 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004593 else
developer6372c2b2022-10-27 17:39:51 +08004594 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 +08004595 _syscmd(cmd, buf, sizeof(buf));
4596 } else if (STBC_Enable == FALSE) {
4597 // Remove the STBC flags and remain other flags in capab
4598 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004599 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004600 _syscmd(cmd, buf, sizeof(buf));
4601 memset(cmd, 0, sizeof(cmd));
developer6372c2b2022-10-27 17:39:51 +08004602 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
developer51a927d2022-09-13 15:42:22 +08004603 _syscmd(cmd, buf, sizeof(buf));
4604 }
4605 }
4606
4607 wifi_reloadAp(radioIndex);
4608
4609 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4610 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004611}
4612
4613// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4614INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4615{
developer54e6b9f2022-09-28 14:41:20 +08004616 char AMSDU_file_path[64] = {0};
4617
4618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4619
4620 if(output_bool == NULL)
4621 return RETURN_ERR;
4622
4623 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4624
4625 if (access(AMSDU_file_path, F_OK) == 0)
4626 *output_bool = TRUE;
4627 else
4628 *output_bool = FALSE;
4629
4630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4631 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004632}
4633
4634// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4635INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4636{
developerd946fd62022-12-08 18:03:28 +08004637 char interface_name[16] = {0};
developer54e6b9f2022-09-28 14:41:20 +08004638 char cmd[64]={0};
4639 char buf[64]={0};
4640 char AMSDU_file_path[64] = {0};
4641
4642 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4643
developerd946fd62022-12-08 18:03:28 +08004644 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4645 return RETURN_ERR;
4646 sprintf(cmd, "mt76-vendor %s set ap_wireless amsdu=%d", interface_name, amsduEnable);
developer54e6b9f2022-09-28 14:41:20 +08004647 _syscmd(cmd, buf, sizeof(buf));
4648
4649 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4650 memset(cmd, 0, sizeof(cmd));
4651 if (amsduEnable == TRUE)
4652 sprintf(cmd, "touch %s", AMSDU_file_path);
4653 else
4654 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4655 _syscmd(cmd, buf, sizeof(buf));
4656
4657 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4658 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004659}
4660
4661//P2 // outputs the number of Tx streams
4662INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4663{
developer2de97692022-09-26 14:00:03 +08004664 char buf[8] = {0};
4665 char cmd[128] = {0};
developer033b37b2022-10-18 11:27:46 +08004666 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004667
4668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4669
4670 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4671 _syscmd(cmd, buf, sizeof(buf));
4672
developer033b37b2022-10-18 11:27:46 +08004673 phyId = radio_index_to_phy(radioIndex);
developer2de97692022-09-26 14:00:03 +08004674 // if there is no record, output the max number of spatial streams
4675 if (strlen(buf) == 0) {
developer033b37b2022-10-18 11:27:46 +08004676 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 +08004677 _syscmd(cmd, buf, sizeof(buf));
4678 }
4679
4680 *output_int = (INT)strtol(buf, NULL, 10);
4681
4682 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4683
4684 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004685}
4686
4687//P2 // sets the number of Tx streams to an enviornment variable
4688INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4689{
developer2de97692022-09-26 14:00:03 +08004690 char cmd[128] = {0};
4691 char buf[128] = {0};
4692 char chain_mask_file[128] = {0};
4693 FILE *f = NULL;
developer033b37b2022-10-18 11:27:46 +08004694 int phyId = 0;
developer2de97692022-09-26 14:00:03 +08004695
4696 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4697
4698 if (numStreams == 0) {
developer30423732022-12-01 16:17:49 +08004699 fprintf(stderr, "The mask did not support 0 (auto).\n");
developer2de97692022-09-26 14:00:03 +08004700 return RETURN_ERR;
4701 }
4702 wifi_setRadioEnable(radioIndex, FALSE);
developer033b37b2022-10-18 11:27:46 +08004703
4704 phyId = radio_index_to_phy(radioIndex);
4705 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
developer2de97692022-09-26 14:00:03 +08004706 _syscmd(cmd, buf, sizeof(buf));
4707
4708 if (strlen(buf) > 0) {
4709 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4710 return RETURN_ERR;
4711 }
4712 wifi_setRadioEnable(radioIndex, TRUE);
4713
4714 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4715 f = fopen(chain_mask_file, "w");
4716 if (f == NULL) {
4717 fprintf(stderr, "%s: fopen failed.\n", __func__);
4718 return RETURN_ERR;
4719 }
4720 fprintf(f, "%d", numStreams);
4721 fclose(f);
4722 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4723 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004724}
4725
4726//P2 // outputs the number of Rx streams
4727INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4728{
developer2de97692022-09-26 14:00:03 +08004729 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4730 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4731 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004732 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004733 }
4734 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004735 return RETURN_OK;
4736}
4737
4738//P2 // sets the number of Rx streams to an enviornment variable
4739INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4740{
developer2de97692022-09-26 14:00:03 +08004741 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4742 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4743 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4744 return RETURN_ERR;
4745 }
4746 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004747 return RETURN_ERR;
4748}
4749
4750//Get radio RDG enable setting
4751INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4752{
4753 if (NULL == output_bool)
4754 return RETURN_ERR;
4755 *output_bool = TRUE;
4756 return RETURN_OK;
4757}
4758
4759//Get radio RDG enable setting
4760INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4761{
4762 if (NULL == output_bool)
4763 return RETURN_ERR;
4764 *output_bool = TRUE;
4765 return RETURN_OK;
4766}
4767
4768//Set radio RDG enable setting
4769INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4770{
4771 return RETURN_ERR;
4772}
4773
4774//Get radio ADDBA enable setting
4775INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4776{
4777 if (NULL == output_bool)
4778 return RETURN_ERR;
4779 *output_bool = TRUE;
4780 return RETURN_OK;
4781}
4782
4783//Set radio ADDBA enable setting
4784INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4785{
4786 return RETURN_ERR;
4787}
4788
4789//Get radio auto block ack enable setting
4790INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4791{
4792 if (NULL == output_bool)
4793 return RETURN_ERR;
4794 *output_bool = TRUE;
4795 return RETURN_OK;
4796}
4797
4798//Set radio auto block ack enable setting
4799INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4800{
4801 return RETURN_ERR;
4802}
4803
4804//Get radio 11n pure mode enable support
4805INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4806{
4807 if (NULL == output_bool)
4808 return RETURN_ERR;
4809 *output_bool = TRUE;
4810 return RETURN_OK;
4811}
4812
4813//Get radio 11n pure mode enable setting
4814INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4815{
4816 if (NULL == output_bool)
4817 return RETURN_ERR;
4818 *output_bool = TRUE;
4819 return RETURN_OK;
4820}
4821
4822//Set radio 11n pure mode enable setting
4823INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4824{
4825 return RETURN_ERR;
4826}
4827
4828//Get radio IGMP snooping enable setting
4829INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4830{
developerd946fd62022-12-08 18:03:28 +08004831 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08004832 char cmd[128]={0};
4833 char buf[4]={0};
4834 bool bridge = FALSE, mac80211 = FALSE;
4835 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4836
4837 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004838 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004839
4840 *output_bool = FALSE;
4841
4842 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4843 _syscmd(cmd, buf, sizeof(buf));
4844 if (strncmp(buf, "1", 1) == 0)
4845 bridge = TRUE;
4846
developerd946fd62022-12-08 18:03:28 +08004847 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4848 return RETURN_ERR;
4849 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
developer81bf2ed2022-09-13 15:31:14 +08004850 _syscmd(cmd, buf, sizeof(buf));
4851 if (strncmp(buf, "1", 1) == 0)
4852 mac80211 = TRUE;
4853
4854 if (bridge && mac80211)
4855 *output_bool = TRUE;
4856
4857 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004858 return RETURN_OK;
4859}
4860
4861//Set radio IGMP snooping enable setting
4862INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4863{
developerd946fd62022-12-08 18:03:28 +08004864 char interface_name[16] = {0};
developer81bf2ed2022-09-13 15:31:14 +08004865 char cmd[128]={0};
4866 char buf[4]={0};
developer804c64f2022-10-19 13:54:40 +08004867 int max_num_radios =0;
developer81bf2ed2022-09-13 15:31:14 +08004868 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4869
4870 // bridge
4871 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4872 _syscmd(cmd, buf, sizeof(buf));
4873
developer804c64f2022-10-19 13:54:40 +08004874 wifi_getMaxRadioNumber(&max_num_radios);
developer81bf2ed2022-09-13 15:31:14 +08004875 // mac80211
developer804c64f2022-10-19 13:54:40 +08004876 for (int i = 0; i < max_num_radios; i++) {
developerd946fd62022-12-08 18:03:28 +08004877 if (GetInterfaceName(i, interface_name) != RETURN_OK)
4878 return RETURN_ERR;
4879 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
developer81bf2ed2022-09-13 15:31:14 +08004880 _syscmd(cmd, buf, sizeof(buf));
4881 }
4882 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4883 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004884}
4885
4886//Get the Reset count of radio
4887INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4888{
4889 if (NULL == output_int)
4890 return RETURN_ERR;
4891 *output_int = (radioIndex==0)? 1: 3;
4892
4893 return RETURN_OK;
4894}
4895
4896
4897//---------------------------------------------------------------------------------------------------
4898//
4899// Additional Wifi AP level APIs used for Access Point devices
4900//
4901//---------------------------------------------------------------------------------------------------
4902
4903// creates a new ap and pushes these parameters to the hardware
4904INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4905{
developerd946fd62022-12-08 18:03:28 +08004906 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004907 char buf[1024];
4908 char cmd[128];
developer033b37b2022-10-18 11:27:46 +08004909 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08004910
4911 if (NULL == essid)
4912 return RETURN_ERR;
4913
developerd946fd62022-12-08 18:03:28 +08004914 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4915 return RETURN_ERR;
4916
developer033b37b2022-10-18 11:27:46 +08004917 phyId = radio_index_to_phy(radioIndex);
developerd946fd62022-12-08 18:03:28 +08004918 snprintf(cmd,sizeof(cmd), "wlanconfig %s create wlandev %s%d wlanmode ap", interface_name, RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +08004919 _syscmd(cmd, buf, sizeof(buf));
4920
developerd946fd62022-12-08 18:03:28 +08004921 snprintf(cmd,sizeof(cmd), "iwconfig %s essid %s mode master", interface_name, essid);
developer06a01d92022-09-07 16:32:39 +08004922 _syscmd(cmd, buf, sizeof(buf));
4923
4924 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4925
developerd946fd62022-12-08 18:03:28 +08004926 snprintf(cmd,sizeof(cmd), "ifconfig %s txqueuelen 1000", interface_name);
developer06a01d92022-09-07 16:32:39 +08004927 _syscmd(cmd, buf, sizeof(buf));
4928
4929 return RETURN_OK;
4930}
4931
4932// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4933INT wifi_deleteAp(INT apIndex)
4934{
developerd946fd62022-12-08 18:03:28 +08004935 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004936 char buf[1024];
4937 char cmd[128];
4938
developerd946fd62022-12-08 18:03:28 +08004939 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4940 return RETURN_ERR;
4941 snprintf(cmd,sizeof(cmd), "wlanconfig %s destroy", interface_name);
developer06a01d92022-09-07 16:32:39 +08004942 _syscmd(cmd, buf, sizeof(buf));
4943
4944 wifi_removeApSecVaribles(apIndex);
4945
4946 return RETURN_OK;
4947}
4948
4949// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4950INT wifi_getApName(INT apIndex, CHAR *output_string)
4951{
developerd946fd62022-12-08 18:03:28 +08004952 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08004953 if(NULL == output_string)
4954 return RETURN_ERR;
4955
developerd946fd62022-12-08 18:03:28 +08004956 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4957 memset(output_string, 0, 16);
4958 else
4959 snprintf(output_string, 16, "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08004960 return RETURN_OK;
4961}
4962
4963// Outputs the index number in that corresponds to the SSID string
4964INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4965{
developerd946fd62022-12-08 18:03:28 +08004966 char cmd [128] = {0};
4967 char buf[32] = {0};
4968 char *apIndex_str = NULL;
4969 INT apIndex = 0;
4970 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +08004971
developerd946fd62022-12-08 18:03:28 +08004972 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
4973 _syscmd(cmd, buf, sizeof(buf));
4974 // May get multiple output, so we need to check which ap is enable.
4975 apIndex_str = strtok(buf, "\n");
4976 while (apIndex_str != NULL) {
4977 apIndex = strtoul(apIndex_str, NULL, 10);
4978 wifi_getApEnable(apIndex, &enable);
4979 if (enable == TRUE) {
4980 *output_int = apIndex;
4981 return RETURN_OK;
4982 }
4983 apIndex_str = strtok(NULL, "\n");
developer06a01d92022-09-07 16:32:39 +08004984 }
developerd946fd62022-12-08 18:03:28 +08004985 *output_int = -1;
4986 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004987}
4988
4989INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4990{
4991 return wifi_getIndexFromName(inputSsidString, output_int);
4992}
4993
4994// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4995INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4996{
4997 char buf[MAX_BUF_SIZE] = {0};
4998 char cmd[MAX_CMD_SIZE] = {0};
4999 char config_file[MAX_BUF_SIZE] = {0};
5000
5001 if(NULL == output_string)
5002 return RETURN_ERR;
5003
5004 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5005 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5006 if((strcmp(buf,"3")==0))
5007 snprintf(output_string, 32, "WPAand11i");
5008 else if((strcmp(buf,"2")==0))
5009 snprintf(output_string, 32, "11i");
5010 else if((strcmp(buf,"1")==0))
5011 snprintf(output_string, 32, "WPA");
5012 else
5013 snprintf(output_string, 32, "None");
5014
5015 return RETURN_OK;
5016}
5017
5018// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5019INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5020{
5021 char config_file[MAX_BUF_SIZE] = {0};
5022 struct params list;
5023
5024 if (NULL == beaconTypeString)
5025 return RETURN_ERR;
5026 list.name = "wpa";
5027 list.value = "0";
5028
5029 if((strcmp(beaconTypeString,"WPAand11i")==0))
5030 list.value="3";
5031 else if((strcmp(beaconTypeString,"11i")==0))
5032 list.value="2";
5033 else if((strcmp(beaconTypeString,"WPA")==0))
5034 list.value="1";
5035
5036 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5037 wifi_hostapdWrite(config_file, &list, 1);
5038 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5039 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5040 return RETURN_OK;
5041}
5042
5043// sets the beacon interval on the hardware for this AP
5044INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5045{
developer5f222492022-09-13 15:21:52 +08005046 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5047 struct params params={'\0'};
5048 char buf[MAX_BUF_SIZE] = {'\0'};
5049 char config_file[MAX_BUF_SIZE] = {'\0'};
5050
5051 params.name = "beacon_int";
5052 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5053 params.value = buf;
5054
5055 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5056 wifi_hostapdWrite(config_file, &params, 1);
5057
5058 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5059 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5060 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005061}
5062
5063INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5064{
developer5b398df2022-11-17 20:39:48 +08005065 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5066 return RETURN_ERR;
5067 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005068}
5069
5070// Get the packet size threshold supported.
5071INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5072{
5073 //save config and apply instantly
5074 if (NULL == output_bool)
5075 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005076 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005077 return RETURN_OK;
5078}
5079
5080// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5081INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5082{
developerd946fd62022-12-08 18:03:28 +08005083 char interface_name[16] = {0};
developer514406b2022-12-05 17:20:21 +08005084 char buf[16] = {0};
5085 char config_file[128] = {0};
5086 struct params param = {0};
5087
5088 if (threshold > 65535) {
5089 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5090 return RETURN_ERR;
5091 }
developer06a01d92022-09-07 16:32:39 +08005092
developerd946fd62022-12-08 18:03:28 +08005093 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5094 return RETURN_ERR;
5095 snprintf(config_file, sizeof(config_file), "%s.conf", interface_name);
developer514406b2022-12-05 17:20:21 +08005096 snprintf(buf, sizeof(buf), "%u", threshold);
5097 param.name = "rts_threshold";
5098 param.value = buf;
5099 wifi_hostapdWrite(config_file, &param, 1);
5100 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5101 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005102
5103 return RETURN_OK;
5104}
5105
5106// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5107INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5108{
5109 if (NULL == output_string)
5110 return RETURN_ERR;
5111 snprintf(output_string, 32, "TKIPandAESEncryption");
5112 return RETURN_OK;
5113
5114}
5115
5116// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5117INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5118{
5119 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005120 char *param_name = NULL;
5121 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005122
5123 if(NULL == output_string)
5124 return RETURN_ERR;
5125
5126 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5127 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5128
5129 if(strcmp(buf,"0")==0)
5130 {
5131 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5132 snprintf(output_string, 32, "None");
5133 return RETURN_OK;
5134 }
5135 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5136 param_name = "rsn_pairwise";
5137 else if((strcmp(buf,"1")==0))
5138 param_name = "wpa_pairwise";
5139 else
5140 return RETURN_ERR;
5141 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005142 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005143 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5144 param_name = "wpa_pairwise";
5145 memset(output_string, '\0', 32);
5146 wifi_hostapdRead(config_file, param_name, output_string, 32);
5147 }
developer06a01d92022-09-07 16:32:39 +08005148 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5149
5150 if(strcmp(output_string,"TKIP") == 0)
5151 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5152 else if(strcmp(output_string,"CCMP") == 0)
5153 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5154 else if(strcmp(output_string,"TKIP CCMP") == 0)
5155 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5156
5157 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5158 return RETURN_OK;
5159}
5160
5161// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5162INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5163{
5164 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5165 struct params params={'\0'};
5166 char output_string[32];
5167 char config_file[MAX_BUF_SIZE] = {0};
5168
5169 memset(output_string,'\0',32);
5170 wifi_getApWpaEncryptionMode(apIndex,output_string);
5171
5172 if(strcmp(encMode, "TKIPEncryption") == 0)
5173 params.value = "TKIP";
5174 else if(strcmp(encMode,"AESEncryption") == 0)
5175 params.value = "CCMP";
5176 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5177 params.value = "TKIP CCMP";
5178
5179 if((strcmp(output_string,"WPAand11i")==0))
5180 {
5181 params.name = "wpa_pairwise";
5182 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5183 wifi_hostapdWrite(config_file, &params, 1);
5184 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5185
developer30423732022-12-01 16:17:49 +08005186 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005187 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5188 wifi_hostapdWrite(config_file, &params, 1);
5189 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5190
5191 return RETURN_OK;
5192 }
5193 else if((strcmp(output_string,"11i")==0))
5194 {
5195 params.name = "rsn_pairwise";
5196 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5197 wifi_hostapdWrite(config_file, &params, 1);
5198 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5199 return RETURN_OK;
5200 }
5201 else if((strcmp(output_string,"WPA")==0))
5202 {
5203 params.name = "wpa_pairwise";
5204 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5205 wifi_hostapdWrite(config_file, &params, 1);
5206 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5207 return RETURN_OK;
5208 }
5209
5210 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5211 return RETURN_OK;
5212}
5213
5214// deletes internal security varable settings for this ap
5215INT wifi_removeApSecVaribles(INT apIndex)
5216{
5217 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005218 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005219 //_syscmd(cmd, buf, sizeof(buf));
5220
developerd946fd62022-12-08 18:03:28 +08005221 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005222 //_syscmd(cmd, buf, sizeof(buf));
5223 return RETURN_ERR;
5224}
5225
5226// changes the hardware settings to disable encryption on this ap
5227INT wifi_disableApEncryption(INT apIndex)
5228{
5229 //Apply instantly
5230 return RETURN_ERR;
5231}
5232
5233// set the authorization mode on this ap
5234// mode mapping as: 1: open, 2: shared, 4:auto
5235INT wifi_setApAuthMode(INT apIndex, INT mode)
5236{
developeraf95c502022-09-13 16:18:22 +08005237 struct params params={0};
5238 char config_file[64] = {0};
5239 int ret;
5240
5241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5242
5243 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5244 params.name = "auth_algs";
5245
5246 if (mode & 1 && mode & 2)
5247 params.value = "3";
5248 else if (mode & 2)
5249 params.value = "2";
5250 else if (mode & 1)
5251 params.value = "1";
5252 else
5253 params.value = "0";
5254
5255 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5256 wifi_hostapdWrite(config_file, &params, 1);
5257 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5258 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5259
5260 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005261}
5262
5263// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5264INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5265{
5266 //save to wifi config, and wait for wifi restart to apply
5267 struct params params={'\0'};
5268 char config_file[MAX_BUF_SIZE] = {0};
5269 int ret;
5270
5271 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5272 if(authMode == NULL)
5273 return RETURN_ERR;
5274
5275 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5276 params.name = "wpa_key_mgmt";
5277
5278 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5279 params.value = "WPA-PSK";
5280 else if(strcmp(authMode,"EAPAuthentication") == 0)
5281 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005282 else if (strcmp(authMode, "SAEAuthentication") == 0)
5283 params.value = "SAE";
5284 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5285 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005286 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5287 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005288 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5289 return RETURN_OK; //This is taken careof in beaconType
5290
5291 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5292 ret=wifi_hostapdWrite(config_file,&params,1);
5293 if(!ret)
5294 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5295 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5296
5297 return ret;
5298}
5299
5300// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5301INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5302{
5303 //save to wifi config, and wait for wifi restart to apply
5304 char BeaconType[50] = {0};
5305 char config_file[MAX_BUF_SIZE] = {0};
5306
5307 *authMode = 0;
5308 wifi_getApBeaconType(apIndex,BeaconType);
5309 printf("%s____%s \n",__FUNCTION__,BeaconType);
5310
5311 if(strcmp(BeaconType,"None") == 0)
5312 strcpy(authMode,"None");
5313 else
5314 {
5315 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5316 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5317 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5318 if(strcmp(authMode,"WPA-PSK") == 0)
5319 strcpy(authMode,"SharedAuthentication");
5320 else if(strcmp(authMode,"WPA-EAP") == 0)
5321 strcpy(authMode,"EAPAuthentication");
5322 }
5323
5324 return RETURN_OK;
5325}
5326
5327// Outputs the number of stations associated per AP
5328INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5329{
developerd946fd62022-12-08 18:03:28 +08005330 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005331 char cmd[128]={0};
5332 char buf[128]={0};
5333 BOOL status = false;
5334
5335 if(apIndex > MAX_APS)
5336 return RETURN_ERR;
5337
5338 wifi_getApEnable(apIndex,&status);
5339 if (!status)
5340 return RETURN_OK;
5341
developerd946fd62022-12-08 18:03:28 +08005342 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
5343 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5344 return RETURN_ERR;
5345 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005346 _syscmd(cmd, buf, sizeof(buf));
5347 sscanf(buf,"%lu", output_ulong);
5348
5349 return RETURN_OK;
5350}
5351
5352// manually removes any active wi-fi association with the device specified on this ap
5353INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5354{
developerd946fd62022-12-08 18:03:28 +08005355 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005356 char buf[126]={'\0'};
5357
developerd946fd62022-12-08 18:03:28 +08005358 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5359 return RETURN_ERR;
5360 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005361 system(buf);
5362
5363 return RETURN_OK;
5364}
5365
5366// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5367INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5368{
5369 if(NULL == output_int)
5370 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005371 int max_radio_num = 0;
5372 wifi_getMaxRadioNumber(&max_radio_num);
5373 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005374 return RETURN_OK;
5375}
5376
5377// sets the radio index for the specific ap
5378INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5379{
5380 //set to config only and wait for wifi reset to apply settings
5381 return RETURN_ERR;
5382}
5383
5384// Get the ACL MAC list per AP
5385INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5386{
developerd946fd62022-12-08 18:03:28 +08005387 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005388 char cmd[MAX_CMD_SIZE]={'\0'};
5389 int ret = 0;
5390
developerd946fd62022-12-08 18:03:28 +08005391 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5392 return RETURN_ERR;
5393 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005394 ret = _syscmd(cmd,macArray,buf_size);
5395 if (ret != 0)
5396 return RETURN_ERR;
5397
5398 return RETURN_OK;
5399}
5400
developere6aafda2022-09-13 14:59:28 +08005401INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5402{
developerd946fd62022-12-08 18:03:28 +08005403 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005404 char cmd[MAX_CMD_SIZE]={'\0'};
5405 int ret = 0;
5406
developerd946fd62022-12-08 18:03:28 +08005407 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5408 return RETURN_ERR;
5409 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005410 ret = _syscmd(cmd,macArray,buf_size);
5411 if (ret != 0)
5412 return RETURN_ERR;
5413
5414 return RETURN_OK;
5415}
5416
5417
developer06a01d92022-09-07 16:32:39 +08005418// Get the list of stations associated per AP
5419INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5420{
developerd946fd62022-12-08 18:03:28 +08005421 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005422 char cmd[128];
5423
5424 if(apIndex > 3) //Currently supporting apIndex upto 3
5425 return RETURN_ERR;
developerd946fd62022-12-08 18:03:28 +08005426 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5427 return RETURN_ERR;
5428 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5429 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005430 _syscmd(cmd, macArray, buf_size);
5431
5432 return RETURN_OK;
5433}
5434
5435// adds the mac address to the filter list
5436//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5437INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5438{
5439 char cmd[MAX_CMD_SIZE]={'\0'};
5440 char buf[MAX_BUF_SIZE]={'\0'};
5441
5442#if 0
developerd946fd62022-12-08 18:03:28 +08005443 sprintf(cmd, "hostapd_cli -i %s accept_acl ADD_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005444 if(_syscmd(cmd,buf,sizeof(buf)))
5445 return RETURN_ERR;
5446#endif
5447 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5448 if(_syscmd(cmd,buf,sizeof(buf)))
5449 return RETURN_ERR;
5450
5451 return RETURN_OK;
5452}
5453
5454// deletes the mac address from the filter list
5455//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5456INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5457{
5458 char cmd[MAX_CMD_SIZE]={'\0'};
5459 char buf[MAX_BUF_SIZE]={'\0'};
5460
5461#if 0
developerd946fd62022-12-08 18:03:28 +08005462 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005463 if(_syscmd(cmd,buf,sizeof(buf)))
5464 return RETURN_ERR;
5465
5466#endif
5467 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5468 if(_syscmd(cmd,buf,sizeof(buf)))
5469 return RETURN_ERR;
5470
5471 return RETURN_OK;
5472}
5473
5474// outputs the number of devices in the filter list
5475INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5476{
developere6aafda2022-09-13 14:59:28 +08005477 char cmd[MAX_BUF_SIZE]={0};
5478 char buf[MAX_CMD_SIZE]={0};
5479
5480 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5481 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005482 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005483
5484 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5485 _syscmd(cmd, buf, sizeof(buf));
5486
5487 *output_uint = atoi(buf);
5488
5489 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5490 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005491}
5492
5493INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5494{
5495 char cmd[128]={'\0'};
5496 char buf[128]={'\0'};
5497
5498 if(strcmp(action,"DENY")==0)
5499 {
5500 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5501 system(buf);
5502 return RETURN_OK;
5503 }
5504
5505 if(strcmp(action,"ALLOW")==0)
5506 {
5507 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5508 system(buf);
5509 return RETURN_OK;
5510 }
5511
5512 return RETURN_ERR;
5513
5514}
5515
5516// enable kick for devices on acl black list
5517INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5518{
5519 char aclArray[512] = {0}, *acl = NULL;
5520 char assocArray[512] = {0}, *asso = NULL;
5521
developere6aafda2022-09-13 14:59:28 +08005522 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005523 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5524
5525 // if there are no devices connected there is nothing to do
5526 if (strlen(assocArray) < 17)
5527 return RETURN_OK;
5528
5529 if (enable == TRUE)
5530 {
5531 //kick off the MAC which is in ACL array (deny list)
5532 acl = strtok(aclArray, "\r\n");
5533 while (acl != NULL) {
5534 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5535 wifi_kickApAssociatedDevice(apIndex, acl);
5536
5537 acl = strtok(NULL, "\r\n");
5538 }
developere6aafda2022-09-13 14:59:28 +08005539 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005540 }
5541 else
5542 {
developere6aafda2022-09-13 14:59:28 +08005543 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005544 }
5545
5546#if 0
5547 //TODO: need to revisit below implementation
5548 char aclArray[512]={0}, *acl=NULL;
5549 char assocArray[512]={0}, *asso=NULL;
5550 char buf[256]={'\0'};
5551 char action[10]={'\0'};
5552 FILE *fr=NULL;
5553 char interface[10]={'\0'};
5554 char config_file[MAX_BUF_SIZE] = {0};
5555
5556 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5557 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5558 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5559 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5560
5561 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5562 system(buf);
5563 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5564 system(buf);
5565 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5566 system(buf);
5567 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5568 system(buf);
5569 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5570 system(buf);
5571
5572 if ( enable == TRUE )
5573 {
5574 int device_count=0;
5575 strcpy(action,"DENY");
5576 //kick off the MAC which is in ACL array (deny list)
5577 acl = strtok (aclArray,",");
5578 while (acl != NULL) {
5579 if(strlen(acl)>=17)
5580 {
5581 apply_rules(apIndex, acl,action,interface);
5582 device_count++;
5583 //Register mac to be blocked ,in syscfg.db persistent storage
5584 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5585 system(buf);
5586 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5587 system(buf);
5588 system("syscfg commit");
5589
5590 wifi_kickApAssociatedDevice(apIndex, acl);
5591 }
5592 acl = strtok (NULL, ",");
5593 }
5594 }
5595 else
5596 {
5597 int device_count=0;
5598 char cmdmac[20]={'\0'};
5599 strcpy(action,"ALLOW");
5600 //kick off the MAC which is not in ACL array (allow list)
5601 acl = strtok (aclArray,",");
5602 while (acl != NULL) {
5603 if(strlen(acl)>=17)
5604 {
5605 apply_rules(apIndex, acl,action,interface);
5606 device_count++;
5607 //Register mac to be Allowed ,in syscfg.db persistent storage
5608 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5609 system(buf);
5610 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5611 system(buf);
5612 sprintf(cmdmac,"%s",acl);
5613 }
5614 acl = strtok (NULL, ",");
5615 }
5616 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5617 system(buf);
5618
5619 //Disconnect the mac which is not in ACL
5620 asso = strtok (assocArray,",");
5621 while (asso != NULL) {
5622 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5623 wifi_kickApAssociatedDevice(apIndex, asso);
5624 asso = strtok (NULL, ",");
5625 }
5626 }
5627#endif
5628 return RETURN_OK;
5629}
5630
5631INT wifi_setPreferPrivateConnection(BOOL enable)
5632{
developer06a01d92022-09-07 16:32:39 +08005633 return RETURN_OK;
5634}
5635
5636// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5637INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5638{
developerd946fd62022-12-08 18:03:28 +08005639 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005640 int items = 1;
5641 struct params list[2];
5642 char buf[MAX_BUF_SIZE] = {0};
5643 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005644 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005645
5646 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005647
developer10adcc12022-09-13 14:39:17 +08005648 if (filterMode == 0) {
5649 sprintf(buf, "%d", 0);
5650 list[0].value = buf;
5651
5652 char cmd[128], rtn[128];
developerd946fd62022-12-08 18:03:28 +08005653 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5654 return RETURN_ERR;
5655 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR", interface_name);
developer10adcc12022-09-13 14:39:17 +08005656 _syscmd(cmd, rtn, sizeof(rtn));
5657 memset(cmd,0,sizeof(cmd));
5658 // Delete deny_mac_file in hostapd configuration
5659 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5660 _syscmd(cmd, rtn, sizeof(rtn));
5661 }
5662 else if (filterMode == 1) {
5663 sprintf(buf, "%d", filterMode);
5664 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005665 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5666 list[1].name = "accept_mac_file";
5667 list[1].value = acl_file;
5668 items = 2;
developer10adcc12022-09-13 14:39:17 +08005669 } else if (filterMode == 2) {
5670 //TODO: deny_mac_file
5671 sprintf(buf, "%d", 0);
5672 list[0].value = buf;
5673 list[1].name = "deny_mac_file";
5674 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5675 list[1].value = deny_file;
5676 items = 2;
5677 } else {
5678 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005679 }
developer10adcc12022-09-13 14:39:17 +08005680
developer06a01d92022-09-07 16:32:39 +08005681 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5682 wifi_hostapdWrite(config_file, list, items);
5683
5684 return RETURN_OK;
5685
5686#if 0
5687 if(apIndex==0 || apIndex==1)
5688 {
5689 //set the filtermode
5690 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5691 system(buf);
5692 system("syscfg commit");
5693
5694 if(filterMode==0)
5695 {
5696 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5697 system(buf);
5698 return RETURN_OK;
5699 }
5700 }
5701 return RETURN_OK;
5702#endif
5703}
5704
5705// 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.
5706INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5707{
5708 return RETURN_ERR;
5709}
5710
5711// gets the vlan ID for this ap from an internal enviornment variable
5712INT wifi_getApVlanID(INT apIndex, INT *output_int)
5713{
developer30423732022-12-01 16:17:49 +08005714 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08005715 {
5716 *output_int=100;
5717 return RETURN_OK;
5718 }
5719
5720 return RETURN_ERR;
5721}
5722
5723// sets the vlan ID for this ap to an internal enviornment variable
5724INT wifi_setApVlanID(INT apIndex, INT vlanId)
5725{
5726 //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)
5727 return RETURN_ERR;
5728}
5729
5730// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5731INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5732{
5733 snprintf(bridgeName, 32, "brlan0");
5734 snprintf(IP, 32, "10.0.0.1");
5735 snprintf(subnet, 32, "255.255.255.0");
5736
5737 return RETURN_OK;
5738}
5739
5740//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5741INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5742{
5743 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5744 return RETURN_ERR;
5745}
5746
5747// reset the vlan configuration for this ap
5748INT wifi_resetApVlanCfg(INT apIndex)
5749{
developerf5fef612022-09-20 19:38:26 +08005750 char original_config_file[64] = {0};
5751 char current_config_file[64] = {0};
5752 char buf[64] = {0};
5753 char cmd[64] = {0};
5754 char vlan_file[64] = {0};
5755 char vlan_tagged_interface[16] = {0};
5756 char vlan_bridge[16] = {0};
5757 char vlan_naming[16] = {0};
5758 struct params list[4] = {0};
5759 wifi_band band;
5760
5761 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5762
5763 band = wifi_index_to_band(apIndex);
5764 if (band == band_2_4)
5765 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08005766 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08005767 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08005768 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08005769 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5770
5771 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5772
5773 if (strlen(vlan_file) == 0)
5774 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005775
developerf5fef612022-09-20 19:38:26 +08005776 // The file should exist or this vap would not work.
5777 if (access(vlan_file, F_OK) != 0) {
5778 sprintf(cmd, "touch %s", vlan_file);
5779 _syscmd(cmd, buf, sizeof(buf));
5780 }
5781 list[0].name = "vlan_file";
5782 list[0].value = vlan_file;
5783
5784 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5785 list[1].name = "vlan_tagged_interface";
5786 list[1].value = vlan_tagged_interface;
5787
5788 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5789 list[2].name = "vlan_bridge";
5790 list[2].value = vlan_bridge;
5791
5792 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5793 list[3].name = "vlan_naming";
5794 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005795
developerf5fef612022-09-20 19:38:26 +08005796 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5797 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005798 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005799 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005800
developerf5fef612022-09-20 19:38:26 +08005801 // restart this ap
5802 wifi_setApEnable(apIndex, FALSE);
5803 wifi_setApEnable(apIndex, TRUE);
5804
5805 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5806
5807 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005808}
5809
5810// 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.
5811INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5812{
5813 return RETURN_ERR;
5814}
5815
5816// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5817INT wifi_startHostApd()
5818{
5819 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5820 system("systemctl start hostapd.service");
5821 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5822 return RETURN_OK;
5823 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5824}
5825
5826// stops hostapd
5827INT wifi_stopHostApd()
5828{
5829 char cmd[128] = {0};
5830 char buf[128] = {0};
5831
5832 sprintf(cmd,"systemctl stop hostapd");
5833 _syscmd(cmd, buf, sizeof(buf));
5834
5835 return RETURN_OK;
5836}
5837
5838// restart hostapd dummy function
5839INT wifi_restartHostApd()
5840{
5841 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5842 system("systemctl restart hostapd-global");
5843 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5844
5845 return RETURN_OK;
5846}
5847
5848static int align_hostapd_config(int index)
5849{
5850 ULONG lval;
5851 wifi_getRadioChannel(index%2, &lval);
5852 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08005853 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005854}
5855
5856// sets the AP enable status variable for the specified ap.
5857INT wifi_setApEnable(INT apIndex, BOOL enable)
5858{
developerd946fd62022-12-08 18:03:28 +08005859 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005860 char config_file[MAX_BUF_SIZE] = {0};
5861 char cmd[MAX_CMD_SIZE] = {0};
5862 char buf[MAX_BUF_SIZE] = {0};
5863 BOOL status;
developer033b37b2022-10-18 11:27:46 +08005864 int max_radio_num = 0;
5865 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08005866
5867 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08005868
5869 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08005870 if (enable == status)
5871 return RETURN_OK;
5872
developerd946fd62022-12-08 18:03:28 +08005873 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5874 return RETURN_ERR;
5875
developer06a01d92022-09-07 16:32:39 +08005876 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08005877 int radioIndex = apIndex % max_radio_num;
5878 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08005879 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5880 //Hostapd will bring up this interface
developerd946fd62022-12-08 18:03:28 +08005881 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005882 _syscmd(cmd, buf, sizeof(buf));
developer033b37b2022-10-18 11:27:46 +08005883 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08005884 _syscmd(cmd, buf, sizeof(buf));
5885 }
5886 else {
developerd946fd62022-12-08 18:03:28 +08005887 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005888 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08005889 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08005890 _syscmd(cmd, buf, sizeof(buf));
5891 }
developer431128d2022-12-16 15:30:41 +08005892 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08005893 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08005894 _syscmd(cmd, buf, sizeof(buf));
5895 //Wait for wifi up/down to apply
5896 return RETURN_OK;
5897}
5898
5899// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5900INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5901{
developerd946fd62022-12-08 18:03:28 +08005902 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005903 char cmd[MAX_CMD_SIZE] = {'\0'};
5904 char buf[MAX_BUF_SIZE] = {'\0'};
5905
5906 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5907 return RETURN_ERR;
5908
5909 *output_bool = 0;
5910
5911 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5912 {
developerd946fd62022-12-08 18:03:28 +08005913 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
5914 *output_bool = FALSE;
5915 return RETURN_OK;
5916 }
5917 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08005918 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5919 }
5920
5921 return RETURN_OK;
5922}
5923
5924// Outputs the AP "Enabled" "Disabled" status from driver
5925INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5926{
5927 char cmd[128] = {0};
5928 char buf[128] = {0};
5929 BOOL output_bool;
5930
5931 if ( NULL == output_string)
5932 return RETURN_ERR;
5933 wifi_getApEnable(apIndex,&output_bool);
5934
5935 if(output_bool == 1)
5936 snprintf(output_string, 32, "Up");
5937 else
5938 snprintf(output_string, 32, "Disable");
5939
5940 return RETURN_OK;
5941}
5942
5943//Indicates whether or not beacons include the SSID name.
5944// outputs a 1 if SSID on the AP is enabled, else outputs 0
5945INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5946{
5947 //get the running status
5948 char config_file[MAX_BUF_SIZE] = {0};
5949 char buf[16] = {0};
5950
5951 if (!output)
5952 return RETURN_ERR;
5953
5954 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5955 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005956 // default is enable
5957 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
5958 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08005959
5960 return RETURN_OK;
5961}
5962
5963// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5964INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5965{
5966 //store the config, apply instantly
5967 char config_file[MAX_BUF_SIZE] = {0};
5968 struct params list;
5969
5970 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5971 list.name = "ignore_broadcast_ssid";
5972 list.value = enable?"0":"1";
5973
5974 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5975 wifi_hostapdWrite(config_file, &list, 1);
5976 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5977 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005978 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005979 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5980
5981 return RETURN_OK;
5982}
5983
5984//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5985INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5986{
5987 //get the running status
5988 if(!output_uint)
5989 return RETURN_ERR;
5990 *output_uint=16;
5991 return RETURN_OK;
5992}
5993
5994INT wifi_setApRetryLimit(INT apIndex, UINT number)
5995{
5996 //apply instantly
5997 return RETURN_ERR;
5998}
5999
6000//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6001INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6002{
6003 if(!output)
6004 return RETURN_ERR;
6005 *output=TRUE;
6006 return RETURN_OK;
6007}
6008
6009//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6010INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6011{
6012 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006013 char cmd[128] = {0};
6014 char buf[128] = {0};
6015 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006016 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006017
developer0b246d12022-09-30 15:24:20 +08006018 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006019
developer0b246d12022-09-30 15:24:20 +08006020 wifi_getMaxRadioNumber(&max_radio_num);
6021 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006022 phyId = radio_index_to_phy(radioIndex);
6023 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006024 _syscmd(cmd,buf, sizeof(buf));
6025
6026 if (strlen(buf) > 0)
6027 *output = true;
6028
6029 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006030
developer06a01d92022-09-07 16:32:39 +08006031 return RETURN_OK;
6032}
6033
6034//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6035INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6036{
6037 //get the running status from driver
6038 if(!output)
6039 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006040
6041 char config_file[MAX_BUF_SIZE] = {0};
6042 char buf[16] = {0};
6043
6044 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6045 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006046 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006047 *output = TRUE;
6048 else
6049 *output = FALSE;
6050
developer06a01d92022-09-07 16:32:39 +08006051 return RETURN_OK;
6052}
6053
6054// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6055INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6056{
6057 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006058 char config_file[MAX_BUF_SIZE] = {0};
6059 struct params list;
6060
6061 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6062 list.name = "wmm_enabled";
6063 list.value = enable?"1":"0";
6064
6065 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6066 wifi_hostapdWrite(config_file, &list, 1);
6067 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6068 wifi_reloadAp(apIndex);
6069 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6070
6071 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006072}
6073
6074//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.
6075INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6076{
6077 //get the running status from driver
6078 if(!output)
6079 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006080
6081 char config_file[128] = {0};
6082 char buf[16] = {0};
6083
6084 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6085 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6086 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6087 *output = TRUE;
6088 else
6089 *output = FALSE;
6090
developer06a01d92022-09-07 16:32:39 +08006091 return RETURN_OK;
6092}
6093
6094// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6095INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6096{
6097 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006098 char config_file[MAX_BUF_SIZE] = {0};
6099 struct params list;
6100
6101 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6102 list.name = "uapsd_advertisement_enabled";
6103 list.value = enable?"1":"0";
6104
6105 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6106 wifi_hostapdWrite(config_file, &list, 1);
6107 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6108 wifi_reloadAp(apIndex);
6109 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6110
6111 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006112}
6113
developer6daeb3f2022-09-30 13:36:39 +08006114// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006115INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6116{
developerd946fd62022-12-08 18:03:28 +08006117 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006118 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6119 char cmd[128] = {0};
6120 char buf[128] = {0};
6121 char ack_filepath[128] = {0};
6122 uint16_t bitmap = 0;
6123 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6124 FILE *f = NULL;
6125
6126 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6127
6128 // Get current setting
6129 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6130 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6131 _syscmd(cmd, buf, sizeof(buf));
6132 if (strlen(buf) > 0)
6133 bitmap = strtoul(buf, NULL, 10);
6134
6135 bitmap = strtoul(buf, NULL, 10);
6136
6137 if (ackPolicy == TRUE) { // True, unset this class
6138 bitmap &= ~class_map[class];
6139 } else { // False, set this class
6140 bitmap |= class_map[class];
6141 }
6142
6143 f = fopen(ack_filepath, "w");
6144 if (f == NULL) {
6145 fprintf(stderr, "%s: fopen failed\n", __func__);
6146 return RETURN_ERR;
6147 }
6148 fprintf(f, "%hu", bitmap);
6149 fclose(f);
6150
developerd946fd62022-12-08 18:03:28 +08006151 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6152 return RETURN_ERR;
6153 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006154 _syscmd(cmd, buf, sizeof(buf));
6155
6156 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6157 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006158}
6159
6160//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.
6161INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6162{
6163 //get the running status from driver
6164 if(!output_uint)
6165 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006166
6167 char output[16]={'\0'};
6168 char config_file[MAX_BUF_SIZE] = {0};
6169
6170 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6171 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6172 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6173 else {
6174 int device_num = atoi(output);
6175 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6176 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6177 return RETURN_ERR;
6178 }
6179 else {
6180 *output_uint = device_num;
6181 }
6182 }
6183
developer06a01d92022-09-07 16:32:39 +08006184 return RETURN_OK;
6185}
6186
6187INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6188{
6189 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006190 char str[MAX_BUF_SIZE]={'\0'};
6191 char cmd[MAX_CMD_SIZE]={'\0'};
6192 struct params params;
6193 char config_file[MAX_BUF_SIZE] = {0};
6194
6195 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006196 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006197 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6198 return RETURN_ERR;
6199 }
6200 sprintf(str, "%d", number);
6201 params.name = "max_num_sta";
6202 params.value = str;
6203
6204 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6205 int ret = wifi_hostapdWrite(config_file, &params, 1);
6206 if (ret) {
6207 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6208 ,__func__, ret);
6209 }
6210
6211 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6212 if (ret) {
6213 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6214 ,__func__, ret);
6215 }
6216 wifi_reloadAp(apIndex);
6217 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6218
6219 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006220}
6221
6222//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.
6223INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6224{
6225 //get the current threshold
6226 if(!output_uint)
6227 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006228 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6229 if (*output_uint == 0)
6230 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006231 return RETURN_OK;
6232}
6233
6234INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6235{
6236 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006237 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6238 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006239 return RETURN_ERR;
6240}
6241
6242//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.
6243INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6244{
6245 if(!output_uint)
6246 return RETURN_ERR;
6247 *output_uint = 3;
6248 return RETURN_OK;
6249}
6250
6251//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6252INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6253{
6254 if(!output_uint)
6255 return RETURN_ERR;
6256 *output_uint = 3;
6257 return RETURN_OK;
6258}
6259
6260//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.
6261INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6262{
6263 if(!output_in_seconds)
6264 return RETURN_ERR;
6265 *output_in_seconds = 0;
6266 return RETURN_OK;
6267}
6268
6269//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
6270INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6271{
6272 if(!output || apIndex>=MAX_APS)
6273 return RETURN_ERR;
6274 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006275 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006276 return RETURN_OK;
6277}
6278
6279//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6280INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6281{
developer587c1b62022-09-27 15:58:59 +08006282 char config_file[128] = {0};
6283 char wpa[16] = {0};
6284 char key_mgmt[64] = {0};
6285 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006286 if (!output)
6287 return RETURN_ERR;
6288
6289 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006290 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006291
developer587c1b62022-09-27 15:58:59 +08006292 strcpy(output, "None");//Copying "None" to output string for default case
6293 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006294 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006295 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006296 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006297 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006298 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006299 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006300 snprintf(output, 32, "WPA-WPA2-Personal");
6301
6302 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006303 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006304 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006305 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006306 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006307 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006308 snprintf(output, 32, "WPA-WPA2-Enterprise");
6309 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006310 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006311 snprintf(output, 32, "WPA3-Personal");
6312 else
developer4a359672022-10-13 15:30:46 +08006313 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006314 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6315 snprintf(output, 32, "WPA3-Enterprise");
6316 }
developer06a01d92022-09-07 16:32:39 +08006317
6318 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6319 return RETURN_OK;
6320#if 0
6321 //TODO: need to revisit below implementation
6322 char securityType[32], authMode[32];
6323 int enterpriseMode=0;
6324
6325 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6326 if(!output)
6327 return RETURN_ERR;
6328
6329 wifi_getApBeaconType(apIndex, securityType);
6330 strcpy(output,"None");//By default, copying "None" to output string
6331 if (strncmp(securityType,"None", strlen("None")) == 0)
6332 return RETURN_OK;
6333
6334 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6335 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6336
6337 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6338 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6339 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6340 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6341 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6342 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6343 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6344
6345 return RETURN_OK;
6346#endif
6347}
6348
6349INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6350{
6351 char securityType[32];
6352 char authMode[32];
6353
6354 //store settings and wait for wifi up to apply
6355 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6356 if(!encMode)
6357 return RETURN_ERR;
6358
developer06a01d92022-09-07 16:32:39 +08006359 if (strcmp(encMode, "None")==0)
6360 {
6361 strcpy(securityType,"None");
6362 strcpy(authMode,"None");
6363 }
6364 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6365 {
6366 strcpy(securityType,"WPAand11i");
6367 strcpy(authMode,"PSKAuthentication");
6368 }
6369 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6370 {
6371 strcpy(securityType,"WPAand11i");
6372 strcpy(authMode,"EAPAuthentication");
6373 }
6374 else if (strcmp(encMode, "WPA-Personal")==0)
6375 {
6376 strcpy(securityType,"WPA");
6377 strcpy(authMode,"PSKAuthentication");
6378 }
6379 else if (strcmp(encMode, "WPA-Enterprise")==0)
6380 {
6381 strcpy(securityType,"WPA");
6382 strcpy(authMode,"EAPAuthentication");
6383 }
6384 else if (strcmp(encMode, "WPA2-Personal")==0)
6385 {
6386 strcpy(securityType,"11i");
6387 strcpy(authMode,"PSKAuthentication");
6388 }
6389 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6390 {
6391 strcpy(securityType,"11i");
6392 strcpy(authMode,"EAPAuthentication");
6393 }
developer587c1b62022-09-27 15:58:59 +08006394 else if (strcmp(encMode, "WPA3-Personal") == 0)
6395 {
6396 strcpy(securityType,"11i");
6397 strcpy(authMode,"SAEAuthentication");
6398 }
developer4a359672022-10-13 15:30:46 +08006399 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006400 {
6401 strcpy(securityType, "11i");
6402 strcpy(authMode, "PSK-SAEAuthentication");
6403 }
developer587c1b62022-09-27 15:58:59 +08006404 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6405 {
6406 strcpy(securityType,"11i");
6407 strcpy(authMode,"EAP_192-bit_Authentication");
6408 }
developer06a01d92022-09-07 16:32:39 +08006409 else
6410 {
6411 strcpy(securityType,"None");
6412 strcpy(authMode,"None");
6413 }
6414 wifi_setApBeaconType(apIndex, securityType);
6415 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6416 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6417
6418 return RETURN_OK;
6419}
6420
6421
6422//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6423// output_string must be pre-allocated as 64 character string by caller
6424// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6425INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6426{
developer30423732022-12-01 16:17:49 +08006427 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006428 char config_file[MAX_BUF_SIZE] = {0};
6429
6430 if(output_string==NULL)
6431 return RETURN_ERR;
6432
6433 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6434 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6435
6436 if(strcmp(buf,"0")==0)
6437 {
6438 printf("wpa_mode is %s ......... \n",buf);
6439 return RETURN_ERR;
6440 }
6441
6442 wifi_dbg_printf("\nFunc=%s\n",__func__);
6443 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6444 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6445 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6446
6447 return RETURN_OK;
6448}
6449
6450// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6451// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6452INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6453{
6454 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6455 struct params params={'\0'};
6456 int ret;
6457 char config_file[MAX_BUF_SIZE] = {0};
6458
6459 if(NULL == preSharedKey)
6460 return RETURN_ERR;
6461
6462 params.name = "wpa_passphrase";
6463
6464 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6465 {
6466 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6467 return RETURN_ERR;
6468 }
6469 params.value = preSharedKey;
6470 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6471 ret = wifi_hostapdWrite(config_file, &params, 1);
6472 if(!ret)
6473 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6474 return ret;
6475 //TODO: call hostapd_cli for dynamic_config_control
6476}
6477
6478//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6479// outputs the passphrase, maximum 63 characters
6480INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6481{
6482 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6483
6484 wifi_dbg_printf("\nFunc=%s\n",__func__);
6485 if (NULL == output_string)
6486 return RETURN_ERR;
6487
6488 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6489 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6490 if(strcmp(buf,"0")==0)
6491 {
6492 printf("wpa_mode is %s ......... \n",buf);
6493 return RETURN_ERR;
6494 }
6495
6496 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6497 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6498
6499 return RETURN_OK;
6500}
6501
6502// sets the passphrase enviornment variable, max 63 characters
6503INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6504{
6505 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6506 struct params params={'\0'};
6507 char config_file[MAX_BUF_SIZE] = {0};
6508 int ret;
6509
6510 if(NULL == passPhrase)
6511 return RETURN_ERR;
6512
6513 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6514 {
6515 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6516 return RETURN_ERR;
6517 }
6518 params.name = "wpa_passphrase";
6519 params.value = passPhrase;
6520 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6521 ret=wifi_hostapdWrite(config_file,&params,1);
6522 if(!ret)
6523 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6524
6525 return ret;
6526}
6527
6528//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.
6529INT wifi_setApSecurityReset(INT apIndex)
6530{
developer8d583982022-09-20 11:28:22 +08006531 char original_config_file[64] = {0};
6532 char current_config_file[64] = {0};
6533 char buf[64] = {0};
6534 char cmd[64] = {0};
6535 char wpa[4] = {0};
6536 char wpa_psk[64] = {0};
6537 char wpa_passphrase[64] = {0};
6538 char wpa_psk_file[128] = {0};
6539 char wpa_key_mgmt[64] = {0};
6540 char wpa_pairwise[32] = {0};
6541 wifi_band band;
6542 struct params list[6];
6543
6544 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6545
6546 band = wifi_index_to_band(apIndex);
6547 if (band == band_2_4)
6548 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006549 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006550 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006551 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006552 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6553 else
6554 return RETURN_ERR;
6555
6556 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6557 list[0].name = "wpa";
6558 list[0].value = wpa;
6559
6560 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6561 list[1].name = "wpa_psk";
6562 list[1].value = wpa_psk;
6563
6564 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6565 list[2].name = "wpa_passphrase";
6566 list[2].value = wpa_passphrase;
6567
6568 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6569
6570 if (strlen(wpa_psk_file) == 0)
6571 strcpy(wpa_psk_file, PSK_FILE);
6572
6573 if (access(wpa_psk_file, F_OK) != 0) {
6574 sprintf(cmd, "touch %s", wpa_psk_file);
6575 _syscmd(cmd, buf, sizeof(buf));
6576 }
6577 list[3].name = "wpa_psk_file";
6578 list[3].value = wpa_psk_file;
6579
6580 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6581 list[4].name = "wpa_key_mgmt";
6582 list[4].value = wpa_key_mgmt;
6583
6584 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6585 list[5].name = "wpa_pairwise";
6586 list[5].value = wpa_pairwise;
6587
6588 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6589 wifi_hostapdWrite(current_config_file, list, 6);
6590
6591 wifi_setApEnable(apIndex, FALSE);
6592 wifi_setApEnable(apIndex, TRUE);
6593
6594 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6595 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006596}
6597
6598//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).
6599INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6600{
developer8f2ddd52022-09-13 15:39:24 +08006601 char config_file[64] = {0};
6602 char buf[64] = {0};
6603 char cmd[256] = {0};
6604
6605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6606
developer06a01d92022-09-07 16:32:39 +08006607 if(!IP_output || !Port_output || !RadiusSecret_output)
6608 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006609
developer8f2ddd52022-09-13 15:39:24 +08006610 // Read the first matched config
6611 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6612 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6613 _syscmd(cmd, buf, sizeof(buf));
6614 strncpy(IP_output, buf, 64);
6615
6616 memset(buf, 0, sizeof(buf));
6617 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6618 _syscmd(cmd, buf, sizeof(buf));
6619 *Port_output = atoi(buf);
6620
6621 memset(buf, 0, sizeof(buf));
6622 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6623 _syscmd(cmd, buf, sizeof(buf));
6624 strncpy(RadiusSecret_output, buf, 64);
6625
6626 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006627 return RETURN_OK;
6628}
6629
6630INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6631{
developer8f2ddd52022-09-13 15:39:24 +08006632 char config_file[64] = {0};
6633 char port_str[8] = {0};
6634 char cmd[256] = {0};
6635 char buf[128] = {0};
6636
6637 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6638
6639 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6640
6641 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6642 _syscmd(cmd, buf, sizeof(buf));
6643 memset(cmd, 0, sizeof(cmd));
6644
6645 snprintf(port_str, sizeof(port_str), "%d", port);
6646 if (strlen(buf) == 0)
6647 // Append
6648 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6649 "auth_server_addr=%s\\n"
6650 "auth_server_port=%s\\n"
6651 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6652 else {
6653 // Delete the three lines setting after the "# radius 1" comment
6654 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6655 _syscmd(cmd, buf, sizeof(buf));
6656 memset(cmd, 0, sizeof(cmd));
6657 // Use "# radius 1" comment to find the location to insert the radius setting
6658 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6659 "# radius 1\\n"
6660 "auth_server_addr=%s\\n"
6661 "auth_server_port=%s\\n"
6662 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6663 }
6664 if(_syscmd(cmd, buf, sizeof(buf))) {
6665 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6666 return RETURN_ERR;
6667 }
6668
6669 wifi_reloadAp(apIndex);
6670 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6671 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006672}
6673
6674INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6675{
developer8f2ddd52022-09-13 15:39:24 +08006676 char config_file[64] = {0};
6677 char buf[64] = {0};
6678 char cmd[256] = {0};
6679
6680 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6681
developer06a01d92022-09-07 16:32:39 +08006682 if(!IP_output || !Port_output || !RadiusSecret_output)
6683 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006684
6685 // Read the second matched config
6686 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6687 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6688 _syscmd(cmd, buf, sizeof(buf));
6689 strncpy(IP_output, buf, 64);
6690
6691 memset(buf, 0, sizeof(buf));
6692 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6693 _syscmd(cmd, buf, sizeof(buf));
6694 *Port_output = atoi(buf);
6695
6696 memset(buf, 0, sizeof(buf));
6697 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6698 _syscmd(cmd, buf, sizeof(buf));
6699 strncpy(RadiusSecret_output, buf, 64);
6700
6701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006702 return RETURN_OK;
6703}
6704
6705INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6706{
developer8f2ddd52022-09-13 15:39:24 +08006707 char config_file[64] = {0};
6708 char port_str[8] = {0};
6709 char cmd[256] = {0};
6710 char buf[128] = {0};
6711
6712 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6713
6714 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6715
6716 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6717 _syscmd(cmd, buf, sizeof(buf));
6718 memset(cmd, 0, sizeof(cmd));
6719
6720 snprintf(port_str, sizeof(port_str), "%d", port);
6721 if (strlen(buf) == 0)
6722 // Append
6723 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6724 "auth_server_addr=%s\\n"
6725 "auth_server_port=%s\\n"
6726 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6727 else {
6728 // Delete the three lines setting after the "# radius 2" comment
6729 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6730 _syscmd(cmd, buf, sizeof(buf));
6731 memset(cmd, 0, sizeof(cmd));
6732 // Use "# radius 2" comment to find the location to insert the radius setting
6733 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6734 "# radius 2\\n"
6735 "auth_server_addr=%s\\n"
6736 "auth_server_port=%s\\n"
6737 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6738 }
6739 if(_syscmd(cmd, buf, sizeof(buf))) {
6740 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6741 return RETURN_ERR;
6742 }
6743
6744 wifi_reloadAp(apIndex);
6745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6746 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006747}
6748
6749//RadiusSettings
6750INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6751{
6752 if(!output)
6753 return RETURN_ERR;
6754
6755 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6756 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6757 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6758 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6759 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6760 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.
6761 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6762 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6763 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6764 //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.
6765
6766 return RETURN_OK;
6767}
6768
6769INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6770{
6771 //store the paramters, and apply instantly
6772 return RETURN_ERR;
6773}
6774
6775//Device.WiFi.AccessPoint.{i}.WPS.Enable
6776//Enables or disables WPS functionality for this access point.
6777// outputs the WPS enable state of this ap in output_bool
6778INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6779{
developerd946fd62022-12-08 18:03:28 +08006780 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006781 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer5b398df2022-11-17 20:39:48 +08006782 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08006783 return RETURN_ERR;
developerd946fd62022-12-08 18:03:28 +08006784 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6785 return RETURN_ERR;
6786 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08006787 _syscmd(cmd, buf, sizeof(buf));
6788 if(strstr(buf, "configured"))
6789 *output_bool=TRUE;
6790 else
6791 *output_bool=FALSE;
6792
6793 return RETURN_OK;
6794}
6795
6796//Device.WiFi.AccessPoint.{i}.WPS.Enable
6797// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6798INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6799{
6800 char config_file[MAX_BUF_SIZE] = {0};
6801 struct params params;
6802
developer06a01d92022-09-07 16:32:39 +08006803 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6804 //store the paramters, and wait for wifi up to apply
6805 params.name = "wps_state";
6806 params.value = enable ? "2":"0";
6807
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_reloadAp(apIndex);
6812
6813 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6814 return RETURN_OK;
6815}
6816
6817//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
6818INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6819{
6820 if(!output)
6821 return RETURN_ERR;
6822 snprintf(output, 128, "PushButton,PIN");
6823 return RETURN_OK;
6824}
6825
6826//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6827//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.
6828// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6829INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6830{
6831 if(!output)
6832 return RETURN_ERR;
6833 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6834
6835 return RETURN_OK;
6836}
6837
6838//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6839// 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
6840INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6841{
6842 //apply instantly. No setting need to be stored.
6843 char methods[MAX_BUF_SIZE], *token, *next_token;
6844 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6845 struct params params;
6846
developer5b398df2022-11-17 20:39:48 +08006847 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08006848 return RETURN_ERR;
6849 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6850 //store the paramters, and wait for wifi up to apply
6851
6852 snprintf(methods, sizeof(methods), "%s", methodString);
6853 for(token=methods; *token; token=next_token)
6854 {
6855 strtok_r(token, ",", &next_token);
6856 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6857 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6858 else if(*token=='E')
6859 {
6860 if(!strcmp(methods, "Ethernet"))
6861 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6862 else if(!strcmp(methods, "ExternalNFCToken"))
6863 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6864 else
6865 printf("%s: Unknown WpsConfigMethod\n", __func__);
6866 }
6867 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6868 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6869 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6870 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6871 else if(*token=='P' )
6872 {
6873 if(!strcmp(token, "PushButton"))
6874 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6875 else if(!strcmp(token, "PIN"))
6876 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6877 else
6878 printf("%s: Unknown WpsConfigMethod\n", __func__);
6879 }
6880 else
6881 printf("%s: Unknown WpsConfigMethod\n", __func__);
6882 }
6883 params.name = "config_methods";
6884 params.value = config_methods;
6885 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6886 wifi_hostapdWrite(config_file, &params, 1);
6887 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6888 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6889
6890 return RETURN_OK;
6891}
6892
6893// outputs the pin value, ulong_pin must be allocated by the caller
6894INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6895{
6896 char buf[MAX_BUF_SIZE] = {0};
6897 char cmd[MAX_CMD_SIZE] = {0};
6898
developer5b398df2022-11-17 20:39:48 +08006899 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08006900 return RETURN_ERR;
6901 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6902 _syscmd(cmd, buf, sizeof(buf));
6903 if(strlen(buf) > 0)
6904 *output_ulong=strtoul(buf, NULL, 10);
6905
6906 return RETURN_OK;
6907}
6908
6909// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6910INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6911{
6912 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6913 char ap_pin[16] = {0};
6914 char buf[MAX_BUF_SIZE] = {0};
6915 char config_file[MAX_BUF_SIZE] = {0};
6916 ULONG prev_pin = 0;
6917 struct params params;
6918
developer06a01d92022-09-07 16:32:39 +08006919 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6920 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6921 params.name = "ap_pin";
6922 params.value = ap_pin;
6923 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6924 wifi_hostapdWrite(config_file, &params, 1);
6925 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6926 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6927
6928 return RETURN_OK;
6929}
6930
6931// Output string is either Not configured or Configured, max 32 characters
6932INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6933{
developerd946fd62022-12-08 18:03:28 +08006934 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006935 char cmd[MAX_CMD_SIZE];
6936 char buf[MAX_BUF_SIZE]={0};
6937
developer5b398df2022-11-17 20:39:48 +08006938 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08006939 return RETURN_ERR;
6940 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6941 snprintf(output_string, 32, "Not configured");
developerd946fd62022-12-08 18:03:28 +08006942 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6943 return RETURN_ERR;
6944 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08006945 _syscmd(cmd, buf, sizeof(buf));
6946
developer348e3d92022-09-13 14:48:41 +08006947 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006948 snprintf(output_string, 32, "Configured");
6949 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6950
6951 return RETURN_OK;
6952}
6953
6954// sets the WPS pin for this AP
6955INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6956{
developerd946fd62022-12-08 18:03:28 +08006957 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006958 char cmd[MAX_CMD_SIZE];
6959 char buf[MAX_BUF_SIZE]={0};
6960 BOOL enable;
6961
developer06a01d92022-09-07 16:32:39 +08006962 wifi_getApEnable(apIndex, &enable);
6963 if (!enable)
6964 return RETURN_ERR;
6965 wifi_getApWpsEnable(apIndex, &enable);
6966 if (!enable)
6967 return RETURN_ERR;
6968
developerd946fd62022-12-08 18:03:28 +08006969 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6970 return RETURN_ERR;
6971 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08006972 _syscmd(cmd, buf, sizeof(buf));
6973 if((strstr(buf, "OK"))!=NULL)
6974 return RETURN_OK;
6975
6976 return RETURN_ERR;
6977}
6978
6979// This function is called when the WPS push button has been pressed for this AP
6980INT wifi_setApWpsButtonPush(INT apIndex)
6981{
6982 char cmd[MAX_CMD_SIZE];
6983 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08006984 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006985 BOOL enable=FALSE;
6986
developer06a01d92022-09-07 16:32:39 +08006987 wifi_getApEnable(apIndex, &enable);
6988 if (!enable)
6989 return RETURN_ERR;
6990
6991 wifi_getApWpsEnable(apIndex, &enable);
6992 if (!enable)
6993 return RETURN_ERR;
6994
developerd946fd62022-12-08 18:03:28 +08006995 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6996 return RETURN_ERR;
6997
6998 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
developer06a01d92022-09-07 16:32:39 +08006999 _syscmd(cmd, buf, sizeof(buf));
7000
7001 if((strstr(buf, "OK"))!=NULL)
7002 return RETURN_OK;
7003 return RETURN_ERR;
7004}
7005
7006// cancels WPS mode for this AP
7007INT wifi_cancelApWPS(INT apIndex)
7008{
developerd946fd62022-12-08 18:03:28 +08007009 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007010 char cmd[MAX_CMD_SIZE];
7011 char buf[MAX_BUF_SIZE]={0};
7012
developerd946fd62022-12-08 18:03:28 +08007013 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7014 return RETURN_ERR;
7015 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007016 _syscmd(cmd,buf, sizeof(buf));
7017
7018 if((strstr(buf, "OK"))!=NULL)
7019 return RETURN_OK;
7020 return RETURN_ERR;
7021}
7022
7023//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7024//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7025INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7026{
developerd946fd62022-12-08 18:03:28 +08007027 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007028 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007029 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007030 char cmd[256] = {0}, buf[2048] = {0};
7031 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007032 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007033 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007034 wifi_associated_dev_t *dev=NULL;
7035
7036 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7037 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007038 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7039 return RETURN_ERR;
7040 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007041 _syscmd(cmd,buf,sizeof(buf));
7042 *output_array_size = atoi(buf);
7043
7044 if (*output_array_size <= 0)
7045 return RETURN_OK;
7046
7047 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7048 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007049 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007050 _syscmd(cmd,buf,sizeof(buf));
7051 f = fopen("/tmp/connected_devices.txt", "r");
7052 if (f==NULL)
7053 {
7054 *output_array_size=0;
7055 return RETURN_ERR;
7056 }
developer30423732022-12-01 16:17:49 +08007057 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007058 {
7059 param = strtok(line,"=");
7060 value = strtok(NULL,"=");
7061
7062 if( strcmp("flags",param) == 0 )
7063 {
7064 value[strlen(value)-1]='\0';
7065 if(strstr (value,"AUTHORIZED") != NULL )
7066 {
7067 dev[auth_temp].cli_AuthenticationState = 1;
7068 dev[auth_temp].cli_Active = 1;
7069 auth_temp++;
7070 read_flag=1;
7071 }
7072 }
7073 if(read_flag==1)
7074 {
7075 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7076 {
7077 value[strlen(value)-1]='\0';
7078 sscanf(value, "%x:%x:%x:%x:%x:%x",
7079 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7080 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7081 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7082 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7083 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7084 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7085 mac_temp++;
7086 read_flag=0;
7087 }
7088 }
7089 }
7090 *output_array_size = auth_temp;
7091 auth_temp=0;
7092 mac_temp=0;
7093 free(line);
7094 fclose(f);
7095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7096 return RETURN_OK;
7097}
7098
7099#define MACADDRESS_SIZE 6
7100
7101INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7102{
7103 FILE *fp = NULL;
7104 char str[MAX_BUF_SIZE] = {0};
7105 int wificlientindex = 0 ;
7106 int count = 0;
7107 int signalstrength = 0;
7108 int arr[MACADDRESS_SIZE] = {0};
7109 unsigned char mac[MACADDRESS_SIZE] = {0};
7110 UINT wifi_count = 0;
7111 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7112 char pipeCmd[MAX_CMD_SIZE] = {0};
7113
7114 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7115 *output_array_size = 0;
7116 *associated_dev_array = NULL;
7117
7118 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7119 fp = popen(pipeCmd, "r");
7120 if (fp == NULL)
7121 {
7122 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7123 return RETURN_ERR;
7124 }
7125
7126 /* Read the output a line at a time - output it. */
7127 fgets(str, sizeof(str)-1, fp);
7128 wifi_count = (unsigned int) atoi ( str );
7129 *output_array_size = wifi_count;
7130 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7131 pclose(fp);
7132
7133 if(wifi_count == 0)
7134 {
7135 return RETURN_OK;
7136 }
7137 else
7138 {
7139 wifi_associated_dev3_t* temp = NULL;
7140 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7141 if(temp == NULL)
7142 {
7143 printf("Error Statement. Insufficient memory \n");
7144 return RETURN_ERR;
7145 }
7146
7147 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7148 system(pipeCmd);
7149 memset(pipeCmd,0,sizeof(pipeCmd));
7150 if(apIndex == 0)
7151 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7152 else if(apIndex == 1)
7153 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7154 system(pipeCmd);
7155
7156 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7157 if(fp == NULL)
7158 {
7159 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007160 free(temp);
developer06a01d92022-09-07 16:32:39 +08007161 return RETURN_ERR;
7162 }
7163 fclose(fp);
7164
developer30423732022-12-01 16:17:49 +08007165 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007166 fp = popen(pipeCmd, "r");
7167 if(fp)
7168 {
7169 for(count =0 ; count < wifi_count; count++)
7170 {
7171 fgets(str, MAX_BUF_SIZE, fp);
7172 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7173 {
7174 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7175 {
7176 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7177
7178 }
7179 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7180 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]);
7181 }
7182 temp[count].cli_AuthenticationState = 1; //TODO
7183 temp[count].cli_Active = 1; //TODO
7184 }
7185 pclose(fp);
7186 }
7187
developer30423732022-12-01 16:17:49 +08007188 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 +08007189 fp = popen(pipeCmd, "r");
7190 if(fp)
7191 {
7192 pclose(fp);
7193 }
7194 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7195 if(fp)
7196 {
7197 for(count =0 ; count < wifi_count ;count++)
7198 {
7199 fgets(str, MAX_BUF_SIZE, fp);
7200 signalstrength = atoi(str);
7201 temp[count].cli_SignalStrength = signalstrength;
7202 temp[count].cli_RSSI = signalstrength;
7203 temp[count].cli_SNR = signalstrength + 95;
7204 }
7205 pclose(fp);
7206 }
7207
7208
7209 if((apIndex == 0) || (apIndex == 4))
7210 {
7211 for(count =0 ; count < wifi_count ;count++)
7212 {
7213 strcpy(temp[count].cli_OperatingStandard,"g");
7214 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7215 }
7216
7217 //BytesSent
developer30423732022-12-01 16:17:49 +08007218 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 +08007219 fp = popen(pipeCmd, "r");
7220 if(fp)
7221 {
7222 pclose(fp);
7223 }
7224 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7225 if(fp)
7226 {
7227 for (count = 0; count < wifi_count; count++)
7228 {
7229 fgets(str, MAX_BUF_SIZE, fp);
7230 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7231 }
7232 pclose(fp);
7233 }
7234
7235 //BytesReceived
developer30423732022-12-01 16:17:49 +08007236 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 +08007237 fp = popen(pipeCmd, "r");
7238 if (fp)
7239 {
7240 pclose(fp);
7241 }
7242 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7243 if (fp)
7244 {
7245 for (count = 0; count < wifi_count; count++)
7246 {
7247 fgets(str, MAX_BUF_SIZE, fp);
7248 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7249 }
7250 pclose(fp);
7251 }
7252
7253 //PacketsSent
developer30423732022-12-01 16:17:49 +08007254 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 +08007255 fp = popen(pipeCmd, "r");
7256 if (fp)
7257 {
7258 pclose(fp);
7259 }
7260
7261 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7262 if (fp)
7263 {
7264 for (count = 0; count < wifi_count; count++)
7265 {
7266 fgets(str, MAX_BUF_SIZE, fp);
7267 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7268 }
7269 pclose(fp);
7270 }
7271
7272 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007273 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 +08007274 fp = popen(pipeCmd, "r");
7275 if (fp)
7276 {
7277 pclose(fp);
7278 }
7279 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7280 if (fp)
7281 {
7282 for (count = 0; count < wifi_count; count++)
7283 {
7284 fgets(str, MAX_BUF_SIZE, fp);
7285 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7286 }
7287 pclose(fp);
7288 }
7289
7290 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007291 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 +08007292 fp = popen(pipeCmd, "r");
7293 if (fp)
7294 {
7295 pclose(fp);
7296 }
7297 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7298 if (fp)
7299 {
7300 for (count = 0; count < wifi_count; count++)
7301 {
7302 fgets(str, MAX_BUF_SIZE, fp);
7303 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7304 }
7305 pclose(fp);
7306 }
7307
7308 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007309 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 +08007310 fp = popen(pipeCmd, "r");
7311 if (fp)
7312 {
7313 pclose(fp);
7314 }
7315 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7316 if (fp)
7317 {
7318 for (count = 0; count < wifi_count; count++)
7319 {
7320 fgets(str, MAX_BUF_SIZE, fp);
7321 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7322 }
7323 pclose(fp);
7324 }
7325
7326 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007327 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 +08007328 fp = popen(pipeCmd, "r");
7329 if (fp)
7330 {
7331 pclose(fp);
7332 }
7333 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7334 if (fp)
7335 {
7336 for (count = 0; count < wifi_count; count++)
7337 {
7338 fgets(str, MAX_BUF_SIZE, fp);
7339 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7340 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7341 }
7342 pclose(fp);
7343 }
7344
7345 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007346 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 +08007347 fp = popen(pipeCmd, "r");
7348 if (fp)
7349 {
7350 pclose(fp);
7351 }
7352 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7353 if (fp)
7354 {
7355 for (count = 0; count < wifi_count; count++)
7356 {
7357 fgets(str, MAX_BUF_SIZE, fp);
7358 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7359 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7360 }
7361 pclose(fp);
7362 }
7363
7364 }
7365 else if ((apIndex == 1) || (apIndex == 5))
7366 {
7367 for (count = 0; count < wifi_count; count++)
7368 {
7369 strcpy(temp[count].cli_OperatingStandard, "a");
7370 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7371 temp[count].cli_BytesSent = 0;
7372 temp[count].cli_BytesReceived = 0;
7373 temp[count].cli_LastDataUplinkRate = 0;
7374 temp[count].cli_LastDataDownlinkRate = 0;
7375 temp[count].cli_PacketsSent = 0;
7376 temp[count].cli_PacketsReceived = 0;
7377 temp[count].cli_ErrorsSent = 0;
7378 }
7379 }
7380
7381 for (count = 0; count < wifi_count; count++)
7382 {
7383 temp[count].cli_Retransmissions = 0;
7384 temp[count].cli_DataFramesSentAck = 0;
7385 temp[count].cli_DataFramesSentNoAck = 0;
7386 temp[count].cli_MinRSSI = 0;
7387 temp[count].cli_MaxRSSI = 0;
7388 strncpy(temp[count].cli_InterferenceSources, "", 64);
7389 memset(temp[count].cli_IPAddress, 0, 64);
7390 temp[count].cli_RetransCount = 0;
7391 temp[count].cli_FailedRetransCount = 0;
7392 temp[count].cli_RetryCount = 0;
7393 temp[count].cli_MultipleRetryCount = 0;
7394 }
7395 *associated_dev_array = temp;
7396 }
7397 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7398 return RETURN_OK;
7399}
7400
7401int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7402{
7403 FILE *fp = NULL;
7404 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7405 char cmd[MAX_CMD_SIZE];
7406 int count = 0;
7407
7408 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7409 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7410 fp = popen(cmd,"r");
7411 if(fp == NULL)
7412 {
7413 printf("Failed to run command in Function %s\n",__FUNCTION__);
7414 return 0;
7415 }
7416 if(fgets(path, sizeof(path)-1, fp) != NULL)
7417 {
7418 for(count=0;path[count]!='\n';count++)
7419 status[count]=path[count];
7420 status[count]='\0';
7421 }
7422 strcpy(wifi_status,status);
7423 pclose(fp);
7424 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7425 return RETURN_OK;
7426}
7427
7428/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7429struct hostapd_sta_param {
7430 char key[50];
7431 char value[100];
7432}
7433
7434static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7435 int i = 0;
7436
7437 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7438 if (strncmp(params[i].key,key,50) == 0){
7439 return &params[i].value;
7440 }
7441 i++;
7442 }
7443 return NULL;
7444
7445} */
7446
7447static unsigned int count_occurences(const char *buf, const char *word)
7448{
7449 unsigned int n = 0;
7450 char *ptr = strstr(buf, word);
7451
7452 while (ptr++) {
7453 n++;
7454 ptr = strstr(ptr, word);
7455 }
7456
7457 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7458 return n;
7459}
7460
7461static const char *get_line_from_str_buf(const char *buf, char *line)
7462{
7463 int i;
7464 int n = strlen(buf);
7465
7466 for (i = 0; i < n; i++) {
7467 line[i] = buf[i];
7468 if (buf[i] == '\n') {
7469 line[i] = '\0';
7470 return &buf[i + 1];
7471 }
7472 }
7473
7474 return NULL;
7475}
7476
7477INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7478{
7479 unsigned int assoc_cnt = 0;
7480 char interface_name[50] = {0};
7481 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7482 char cmd[MAX_CMD_SIZE] = {'\0'};
7483 char line[256] = {'\0'};
7484 int i = 0;
7485 int ret = 0;
7486 const char *ptr = NULL;
7487 char *key = NULL;
7488 char *val = NULL;
7489 wifi_associated_dev3_t *temp = NULL;
7490 int rssi;
7491
7492 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7493
7494 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7495 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7496 return RETURN_ERR;
7497 }
7498
7499 // Example filtered output of 'iw dev' command:
7500 // Station 0a:69:72:10:d2:fa (on wifi0)
7501 // signal avg:-67 [-71, -71] dBm
7502 // Station 28:c2:1f:25:5f:99 (on wifi0)
7503 // signal avg:-67 [-71, -70] dBm
7504 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7505 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7506 return RETURN_ERR;
7507 }
7508
7509 ret = _syscmd(cmd, buf, sizeof(buf));
7510 if (ret == RETURN_ERR) {
7511 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7512 return RETURN_ERR;
7513 }
7514
7515 *output_array_size = count_occurences(buf, "Station");
7516 if (*output_array_size == 0) return RETURN_OK;
7517
7518 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7519 if (temp == NULL) {
7520 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7521 return RETURN_ERR;
7522 }
7523 *associated_dev_array = temp;
7524
7525 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7526 ptr = get_line_from_str_buf(buf, line);
7527 i = -1;
7528 while (ptr) {
7529 if (strstr(line, "Station")) {
7530 i++;
7531 key = strtok(line, " ");
7532 val = strtok(NULL, " ");
7533 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7534 &temp[i].cli_MACAddress[0],
7535 &temp[i].cli_MACAddress[1],
7536 &temp[i].cli_MACAddress[2],
7537 &temp[i].cli_MACAddress[3],
7538 &temp[i].cli_MACAddress[4],
7539 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7540 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7541 free(*associated_dev_array);
7542 return RETURN_ERR;
7543 }
7544 }
7545 else if (i < 0) {
7546 ptr = get_line_from_str_buf(ptr, line);
7547 continue; // We didn't detect 'station' entry yet
7548 }
7549 else if (strstr(line, "signal avg")) {
7550 key = strtok(line, ":");
7551 val = strtok(NULL, " ");
7552 if (sscanf(val, "%d", &rssi) <= 0 ) {
7553 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7554 free(*associated_dev_array);
7555 return RETURN_ERR;
7556 }
7557 temp[i].cli_RSSI = rssi;
7558 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7559 }
7560 // Here other fields can be parsed if added to filter of 'iw dev' command
7561
7562 ptr = get_line_from_str_buf(ptr, line);
7563 };
7564
7565 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7566
7567 return RETURN_OK;
7568}
7569
7570#if 0
7571//To-do
7572INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7573{
7574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7575
7576 //Using different approach to get required WiFi Parameters from system available commands
7577#if 0
7578 FILE *f;
7579 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7580 char cmd[256], buf[2048];
7581 char *param , *value, *line=NULL;
7582 size_t len = 0;
7583 ssize_t nread;
7584 wifi_associated_dev3_t *dev=NULL;
7585 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007586 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007587 _syscmd(cmd,buf,sizeof(buf));
7588 *output_array_size = atoi(buf);
7589
7590 if (*output_array_size <= 0)
7591 return RETURN_OK;
7592
7593 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7594 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007595 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007596 _syscmd(cmd,buf,sizeof(buf));
7597 f = fopen("/tmp/connected_devices.txt", "r");
7598 if (f==NULL)
7599 {
7600 *output_array_size=0;
7601 return RETURN_ERR;
7602 }
7603 while ((nread = getline(&line, &len, f)) != -1)
7604 {
7605 param = strtok(line,"=");
7606 value = strtok(NULL,"=");
7607
7608 if( strcmp("flags",param) == 0 )
7609 {
7610 value[strlen(value)-1]='\0';
7611 if(strstr (value,"AUTHORIZED") != NULL )
7612 {
7613 dev[auth_temp].cli_AuthenticationState = 1;
7614 dev[auth_temp].cli_Active = 1;
7615 auth_temp++;
7616 read_flag=1;
7617 }
7618 }
7619 if(read_flag==1)
7620 {
7621 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7622 {
7623 value[strlen(value)-1]='\0';
7624 sscanf(value, "%x:%x:%x:%x:%x:%x",
7625 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7626 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7627 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7628 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7629 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7630 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7631
7632 }
7633 else if( strcmp("rx_packets",param) == 0 )
7634 {
7635 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7636 }
7637
7638 else if( strcmp("tx_packets",param) == 0 )
7639 {
7640 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7641 }
7642
7643 else if( strcmp("rx_bytes",param) == 0 )
7644 {
7645 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7646 }
7647
7648 else if( strcmp("tx_bytes",param) == 0 )
7649 {
7650 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7651 mac_temp++;
7652 read_flag=0;
7653 }
7654 }
7655 }
7656
7657 *output_array_size = auth_temp;
7658 auth_temp=0;
7659 mac_temp=0;
7660 free(line);
7661 fclose(f);
7662#endif
7663 char interface_name[MAX_BUF_SIZE] = {0};
7664 char wifi_status[MAX_BUF_SIZE] = {0};
7665 char hostapdconf[MAX_BUF_SIZE] = {0};
7666
7667 wifi_associated_dev3_t *dev_array = NULL;
7668 ULONG wifi_count = 0;
7669
7670 *associated_dev_array = NULL;
7671 *output_array_size = 0;
7672
7673 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7674 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7675 {
7676 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7677
7678 GetInterfaceName(interface_name, hostapdconf);
7679
7680 if(strlen(interface_name) > 1)
7681 {
7682 wifihal_interfacestatus(wifi_status,interface_name);
7683 if(strcmp(wifi_status,"RUNNING") == 0)
7684 {
7685 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7686
7687 *associated_dev_array = dev_array;
7688 *output_array_size = wifi_count;
7689 }
7690 else
7691 {
7692 *associated_dev_array = NULL;
7693 }
7694 }
7695 }
7696
7697 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7698 return RETURN_OK;
7699}
7700#endif
7701
7702/* getIPAddress function */
7703/**
7704* @description Returning IpAddress of the Matched String
7705*
7706* @param
7707* @str Having MacAddress
7708* @ipaddr Having ipaddr
7709* @return The status of the operation
7710* @retval RETURN_OK if successful
7711* @retval RETURN_ERR if any error is detected
7712*
7713*/
7714
7715INT getIPAddress(char *str,char *ipaddr)
7716{
7717 FILE *fp = NULL;
7718 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7719 int LeaseTime = 0,ret = 0;
7720 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7721 {
7722 return RETURN_ERR;
7723 }
7724
7725 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7726 {
7727 /*
7728 Sample:sss
7729 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7730 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7731 */
7732 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08007733 &(LeaseTime),
7734 phyAddr,
7735 ipAddr,
7736 hostName
7737 );
developer06a01d92022-09-07 16:32:39 +08007738 if(ret != 4)
7739 continue;
7740 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08007741 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08007742 }
developerd946fd62022-12-08 18:03:28 +08007743 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08007744 return RETURN_OK;
7745}
7746
7747/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7748/**
7749* @description Returning Inactive wireless connected clients informations
7750*
7751* @param
7752* @filename Holding private_wifi 2g/5g content files
7753* @associated_dev_array Having inactiv wireless clients informations
7754* @output_array_size Returning Inactive wireless counts
7755* @return The status of the operation
7756* @retval RETURN_OK if successful
7757* @retval RETURN_ERR if any error is detected
7758*
7759*/
7760
7761INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7762{
7763 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7764 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7765 FILE *fp = NULL;
7766 int arr[MACADDRESS_SIZE] = {0};
7767 unsigned char mac[MACADDRESS_SIZE] = {0};
7768 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7769 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7770 fp = popen(buf,"r");
7771 if(fp == NULL)
7772 return RETURN_ERR;
7773 else
7774 {
7775 fgets(path,sizeof(path),fp);
7776 maccount = atoi(path);
7777 }
7778 pclose(fp);
7779 *output_array_size = maccount;
7780 wifi_associated_dev3_t* temp = NULL;
7781 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7782 *associated_dev_array = temp;
7783 if(temp == NULL)
7784 {
7785 printf("Error Statement. Insufficient memory \n");
7786 return RETURN_ERR;
7787 }
7788 memset(buf,0,sizeof(buf));
7789 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7790 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08007791 if (fp == NULL) {
7792 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
7793 return RETURN_ERR;
7794 }
developer06a01d92022-09-07 16:32:39 +08007795 for(count = 0; count < maccount ; count++)
7796 {
7797 fgets(path,sizeof(path),fp);
7798 for(i = 0; path[i]!='\n';i++)
7799 str[i]=path[i];
7800 str[i]='\0';
7801 getIPAddress(str,ipaddr);
7802 memset(buf,0,sizeof(buf));
7803 if(strlen(ipaddr) > 0)
7804 {
7805 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7806 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7807 {
7808 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7809 {
7810 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7811 {
7812 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7813
7814 }
7815 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7816 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]);
7817 }
7818 temp[count].cli_AuthenticationState = 0; //TODO
7819 temp[count].cli_Active = 0; //TODO
7820 temp[count].cli_SignalStrength = 0;
7821 }
7822 else //Active wireless clients info
7823 {
7824 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7825 {
7826 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7827 {
7828 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7829
7830 }
7831 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7832 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]);
7833 }
7834 temp[count].cli_Active = 1;
7835 }
7836 }
7837 memset(ipaddr,0,sizeof(ipaddr));
7838 }
7839 pclose(fp);
7840 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7841 return RETURN_OK;
7842}
7843//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7844//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7845//To get Band Steering Capability
7846INT wifi_getBandSteeringCapability(BOOL *support)
7847{
7848 *support = FALSE;
7849 return RETURN_OK;
7850}
7851
7852
7853//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7854//To get Band Steering enable status
7855INT wifi_getBandSteeringEnable(BOOL *enable)
7856{
7857 *enable = FALSE;
7858 return RETURN_OK;
7859}
7860
7861//To turn on/off Band steering
7862INT wifi_setBandSteeringEnable(BOOL enable)
7863{
7864 return RETURN_OK;
7865}
7866
7867//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7868//To get Band Steering AP group
7869INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7870{
7871 if (NULL == output_ApGroup)
7872 return RETURN_ERR;
7873
7874 strcpy(output_ApGroup, "1,2");
7875 return RETURN_OK;
7876}
7877
7878//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7879//to set and read the band steering BandUtilizationThreshold parameters
7880INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7881{
7882 return RETURN_ERR;
7883}
7884
7885INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7886{
7887 return RETURN_ERR;
7888}
7889
7890//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7891//to set and read the band steering RSSIThreshold parameters
7892INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7893{
7894 return RETURN_ERR;
7895}
7896
7897INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7898{
7899 return RETURN_ERR;
7900}
7901
7902
7903//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7904//to set and read the band steering physical modulation rate threshold parameters
7905INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7906{
7907 //If chip is not support, return -1
7908 return RETURN_ERR;
7909}
7910
7911INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7912{
7913 //If chip is not support, return -1
7914 return RETURN_ERR;
7915}
7916
7917//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7918//to set and read the inactivity time (in seconds) for steering under overload condition
7919INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7920{
7921 return RETURN_ERR;
7922}
7923
7924INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7925{
7926 return RETURN_ERR;
7927}
7928
7929//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7930//to set and read the inactivity time (in seconds) for steering under Idle condition
7931INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7932{
7933 return RETURN_ERR;
7934}
7935
7936INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7937{
7938 return RETURN_ERR;
7939}
7940
7941//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7942//pClientMAC[64]
7943//pSourceSSIDIndex[64]
7944//pDestSSIDIndex[64]
7945//pSteeringReason[256]
7946INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7947{
7948 //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
7949 *pSteeringTime=time(NULL);
7950 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7951 return RETURN_OK;
7952}
7953
7954INT wifi_ifConfigDown(INT apIndex)
7955{
7956 INT status = RETURN_OK;
7957 char cmd[64];
7958
7959 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7960 printf("%s: %s\n", __func__, cmd);
7961 system(cmd);
7962
7963 return status;
7964}
7965
7966INT wifi_ifConfigUp(INT apIndex)
7967{
developerd946fd62022-12-08 18:03:28 +08007968 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007969 char cmd[128];
7970 char buf[1024];
7971
developerd946fd62022-12-08 18:03:28 +08007972 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7973 return RETURN_ERR;
7974 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08007975 _syscmd(cmd, buf, sizeof(buf));
7976 return 0;
7977}
7978
7979//>> Deprecated. Replace with wifi_applyRadioSettings
7980INT wifi_pushBridgeInfo(INT apIndex)
7981{
developerd946fd62022-12-08 18:03:28 +08007982 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007983 char ip[32] = {0};
7984 char subnet[32] = {0};
7985 char bridge[32] = {0};
7986 int vlanId = 0;
7987 char cmd[128] = {0};
7988 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08007989
7990 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7991 wifi_getApVlanID(apIndex,&vlanId);
7992
developerd946fd62022-12-08 18:03:28 +08007993 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7994 return RETURN_ERR;
7995 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08007996 _syscmd(cmd,buf, sizeof(buf));
7997
7998 return 0;
7999}
8000
8001INT wifi_pushChannel(INT radioIndex, UINT channel)
8002{
developerd946fd62022-12-08 18:03:28 +08008003 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008004 char cmd[128];
8005 char buf[1024];
8006 int apIndex;
8007
8008 apIndex=(radioIndex==0)?0:1;
developerd946fd62022-12-08 18:03:28 +08008009 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8010 return RETURN_ERR;
8011 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008012 _syscmd(cmd,buf, sizeof(buf));
8013
8014 return 0;
8015}
8016
8017INT wifi_pushChannelMode(INT radioIndex)
8018{
8019 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8020 return RETURN_ERR;
8021}
8022
8023INT wifi_pushDefaultValues(INT radioIndex)
8024{
8025 //Apply Comcast specified default radio settings instantly
8026 //AMPDU=1
8027 //AMPDUFrames=32
8028 //AMPDULim=50000
8029 //txqueuelen=1000
8030
8031 return RETURN_ERR;
8032}
8033
8034INT wifi_pushTxChainMask(INT radioIndex)
8035{
8036 //Apply default TxChainMask instantly
8037 return RETURN_ERR;
8038}
8039
8040INT wifi_pushRxChainMask(INT radioIndex)
8041{
8042 //Apply default RxChainMask instantly
8043 return RETURN_ERR;
8044}
8045
8046INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8047{
8048 INT status;
8049
8050 status = wifi_setSSIDName(apIndex,ssid);
8051 wifi_setApEnable(apIndex,FALSE);
8052 wifi_setApEnable(apIndex,TRUE);
8053
8054 return status;
8055}
8056
8057INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8058{
8059 //Apply default Ssid Advertisement instantly
8060 return RETURN_ERR;
8061}
8062
8063INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8064{
8065 INT status = RETURN_ERR;
8066 *output = 0;
8067 return RETURN_ERR;
8068}
8069
8070INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8071{
8072 return RETURN_OK;
8073}
8074
8075INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8076{
8077 return RETURN_OK;
8078}
8079
8080//To-do
8081INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8082{
developereb199ae2022-09-13 14:04:27 +08008083 char output[16]={'\0'};
8084 char config_file[MAX_BUF_SIZE] = {0};
8085
8086 if (!output_string)
8087 return RETURN_ERR;
8088
8089 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8090 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8091
8092 if (strlen(output) == 0)
8093 snprintf(output_string, 64, "Disabled");
8094 else if (strncmp(output, "0", 1) == 0)
8095 snprintf(output_string, 64, "Disabled");
8096 else if (strncmp(output, "1", 1) == 0)
8097 snprintf(output_string, 64, "Optional");
8098 else if (strncmp(output, "2", 1) == 0)
8099 snprintf(output_string, 64, "Required");
8100 else {
8101 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8102 return RETURN_ERR;
8103 }
8104
8105 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008106 return RETURN_OK;
8107}
8108INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8109{
developereb199ae2022-09-13 14:04:27 +08008110 char str[MAX_BUF_SIZE]={'\0'};
8111 char cmd[MAX_CMD_SIZE]={'\0'};
8112 struct params params;
8113 char config_file[MAX_BUF_SIZE] = {0};
8114
8115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8116 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8117 return RETURN_ERR;
8118
8119 params.name = "ieee80211w";
8120 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8121 params.value = "0";
8122 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8123 params.value = "1";
8124 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8125 params.value = "2";
8126 else{
8127 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8128 return RETURN_ERR;
8129 }
8130 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8131 wifi_hostapdWrite(config_file, &params, 1);
8132 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008133 return RETURN_OK;
8134}
8135INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8136{
8137 char output[16]={'\0'};
8138 char config_file[MAX_BUF_SIZE] = {0};
8139
8140 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8141 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8142 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8143
8144 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8145 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8146
8147 return RETURN_OK;
8148}
8149
8150INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8151{
8152 return RETURN_OK;
8153}
8154
8155INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8156{
8157 return RETURN_OK;
8158}
8159
8160INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8161{
8162 return RETURN_OK;
8163}
8164
8165INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8166{
8167 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8168 char config_file[MAX_BUF_SIZE] = {0};
8169
8170 if (NULL == output)
8171 return RETURN_ERR;
8172 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8173 wifi_hostapdRead(config_file,"hw_mode",output,64);
8174
8175 if(strcmp(output,"b")==0)
8176 sprintf(output, "%s", "1,2,5.5,11");
8177 else if (strcmp(output,"a")==0)
8178 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8179 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8180 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8181
8182 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8183 return RETURN_OK;
8184}
8185
8186INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8187{
8188 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8189 char *temp;
8190 char temp_output[128];
8191 char temp_TransmitRates[128];
8192 char config_file[MAX_BUF_SIZE] = {0};
8193
8194 if (NULL == output)
8195 return RETURN_ERR;
8196
8197 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8198 wifi_hostapdRead(config_file,"supported_rates",output,64);
8199
developer5b398df2022-11-17 20:39:48 +08008200 if (strlen(output) == 0) {
8201 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8202 return RETURN_OK;
8203 }
developer06a01d92022-09-07 16:32:39 +08008204 strcpy(temp_TransmitRates,output);
8205 strcpy(temp_output,"");
8206 temp = strtok(temp_TransmitRates," ");
8207 while(temp!=NULL)
8208 {
8209 temp[strlen(temp)-1]=0;
8210 if((temp[0]=='5') && (temp[1]=='\0'))
8211 {
8212 temp="5.5";
8213 }
8214 strcat(temp_output,temp);
8215 temp = strtok(NULL," ");
8216 if(temp!=NULL)
8217 {
8218 strcat(temp_output,",");
8219 }
8220 }
8221 strcpy(output,temp_output);
8222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8223
8224 return RETURN_OK;
8225}
8226
8227INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8228{
8229 return RETURN_OK;
8230}
8231
8232
8233INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8234{
8235 int i=0;
8236 char *temp;
developeref938762022-10-19 17:21:01 +08008237 char temp1[128] = {0};
8238 char temp_output[128] = {0};
8239 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008240 struct params params={'\0'};
8241 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008242 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008243
8244 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8245 if(NULL == output)
8246 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008247 strcpy(temp_TransmitRates,output);
8248
8249 for(i=0;i<strlen(temp_TransmitRates);i++)
8250 {
developeref938762022-10-19 17:21:01 +08008251 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008252 {
8253 continue;
8254 }
8255 else
8256 {
8257 return RETURN_ERR;
8258 }
8259 }
8260 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008261 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008262 while(temp!=NULL)
8263 {
8264 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008265 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008266 {
developeref938762022-10-19 17:21:01 +08008267 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008268 {
8269 return RETURN_ERR;
8270 }
8271 }
8272
8273 if(strcmp(temp,"5.5")==0)
8274 {
8275 strcpy(temp1,"55");
8276 }
8277 else
8278 {
8279 strcat(temp1,"0");
8280 }
8281 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008282 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008283 if(temp!=NULL)
8284 {
8285 strcat(temp_output," ");
8286 }
8287 }
8288 strcpy(output,temp_output);
8289
developer06a01d92022-09-07 16:32:39 +08008290 params.name = "supported_rates";
8291 params.value = output;
8292
8293 wifi_dbg_printf("\n%s:",__func__);
8294 wifi_dbg_printf("params.value=%s\n",params.value);
8295 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8296 wifi_hostapdWrite(config_file,&params,1);
8297 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8298
8299 return RETURN_OK;
8300}
8301
8302
8303static char *sncopy(char *dst, int dst_sz, const char *src)
8304{
8305 if (src && dst && dst_sz > 0) {
8306 strncpy(dst, src, dst_sz);
8307 dst[dst_sz - 1] = '\0';
8308 }
8309 return dst;
8310}
8311
8312static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8313{
8314 if (0 == strcmp(ht_mode, "HT40") ||
8315 0 == strcmp(ht_mode, "HT80") ||
8316 0 == strcmp(ht_mode, "HT160")) {
8317 switch (channel) {
8318 case 1 ... 7:
8319 case 36:
8320 case 44:
8321 case 52:
8322 case 60:
8323 case 100:
8324 case 108:
8325 case 116:
8326 case 124:
8327 case 132:
8328 case 140:
8329 case 149:
8330 case 157:
8331 return 1;
8332 case 8 ... 13:
8333 case 40:
8334 case 48:
8335 case 56:
8336 case 64:
8337 case 104:
8338 case 112:
8339 case 120:
8340 case 128:
8341 case 136:
8342 case 144:
8343 case 153:
8344 case 161:
8345 return -1;
8346 default:
8347 return -EINVAL;
8348 }
8349 }
8350
8351 return -EINVAL;
8352}
8353
developerb7593de2022-10-18 09:51:57 +08008354static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8355{
8356 int idx = channel%8;
8357 if (0 == strcmp(ht_mode, "HT40") ||
8358 0 == strcmp(ht_mode, "HT80") ||
8359 0 == strcmp(ht_mode, "HT160")) {
8360 switch (idx) {
8361 case 1:
8362 return 1;
8363 case 5:
8364 return -1;
8365 default:
8366 return -EINVAL;
8367 }
8368 }
8369
8370 return -EINVAL;
8371}
developer06a01d92022-09-07 16:32:39 +08008372static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8373{
8374 if (NULL == hw_mode) return;
8375
8376 if (0 == strcmp(hw_mode, "ac"))
8377 sncopy(bw_mode, bw_mode_len, "ht vht");
8378
8379 if (0 == strcmp(hw_mode, "n"))
8380 sncopy(bw_mode, bw_mode_len, "ht");
8381
8382 return;
8383}
8384
8385static int util_chan_to_freq(int chan)
8386{
8387 if (chan == 14)
8388 return 2484;
8389 else if (chan < 14)
8390 return 2407 + chan * 5;
8391 else if (chan >= 182 && chan <= 196)
8392 return 4000 + chan * 5;
8393 else
8394 return 5000 + chan * 5;
8395 return 0;
8396}
8397
developerb7593de2022-10-18 09:51:57 +08008398static int util_6G_chan_to_freq(int chan)
8399{
8400 if (chan)
8401 return 5950 + chan * 5;
8402 else
8403 return 0;
8404
8405}
developer06a01d92022-09-07 16:32:39 +08008406const int *util_unii_5g_chan2list(int chan, int width)
8407{
8408 static const int lists[] = {
8409 // <width>, <chan1>, <chan2>..., 0,
8410 20, 36, 0,
8411 20, 40, 0,
8412 20, 44, 0,
8413 20, 48, 0,
8414 20, 52, 0,
8415 20, 56, 0,
8416 20, 60, 0,
8417 20, 64, 0,
8418 20, 100, 0,
8419 20, 104, 0,
8420 20, 108, 0,
8421 20, 112, 0,
8422 20, 116, 0,
8423 20, 120, 0,
8424 20, 124, 0,
8425 20, 128, 0,
8426 20, 132, 0,
8427 20, 136, 0,
8428 20, 140, 0,
8429 20, 144, 0,
8430 20, 149, 0,
8431 20, 153, 0,
8432 20, 157, 0,
8433 20, 161, 0,
8434 20, 165, 0,
8435 40, 36, 40, 0,
8436 40, 44, 48, 0,
8437 40, 52, 56, 0,
8438 40, 60, 64, 0,
8439 40, 100, 104, 0,
8440 40, 108, 112, 0,
8441 40, 116, 120, 0,
8442 40, 124, 128, 0,
8443 40, 132, 136, 0,
8444 40, 140, 144, 0,
8445 40, 149, 153, 0,
8446 40, 157, 161, 0,
8447 80, 36, 40, 44, 48, 0,
8448 80, 52, 56, 60, 64, 0,
8449 80, 100, 104, 108, 112, 0,
8450 80, 116, 120, 124, 128, 0,
8451 80, 132, 136, 140, 144, 0,
8452 80, 149, 153, 157, 161, 0,
8453 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8454 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8455 -1 // final delimiter
8456 };
8457 const int *start;
8458 const int *p;
8459
8460 for (p = lists; *p != -1; p++) {
8461 if (*p == width) {
8462 for (start = ++p; *p != 0; p++) {
8463 if (*p == chan)
8464 return start;
8465 }
8466 }
8467 // move to the end of channel list of given width
8468 while (*p != 0) {
8469 p++;
8470 }
8471 }
8472
8473 return NULL;
8474}
8475
8476static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8477{
8478 if (NULL == ht_mode)
8479 return 0;
8480
8481 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8482 const int *chans = util_unii_5g_chan2list(channel, width);
8483 int sum = 0;
8484 int cnt = 0;
8485
8486 if (NULL == chans)
8487 return 0;
8488
8489 while (*chans) {
8490 sum += *chans;
8491 cnt++;
8492 chans++;
8493 }
developer30423732022-12-01 16:17:49 +08008494 if (cnt == 0)
8495 return 0;
developer06a01d92022-09-07 16:32:39 +08008496 return sum / cnt;
8497}
8498
developerb7593de2022-10-18 09:51:57 +08008499static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8500{
8501 if (NULL == ht_mode)
8502 return 0;
8503
8504 int width = strtol((ht_mode + 2), NULL, 10);
8505
8506 int idx = 0 ;
8507 int centerchan = 0;
8508 int chan_ofs = 1;
8509
8510 if (width == 40){
8511 idx = ((channel/4) + chan_ofs)%2;
8512 switch (idx) {
8513 case 0:
8514 centerchan = (channel - 2);
8515 break;
8516 case 1:
8517 centerchan = (channel + 2);
8518 break;
8519 default:
8520 return -EINVAL;
8521 }
8522 }else if (width == 80){
8523 idx = ((channel/4) + chan_ofs)%4;
8524 switch (idx) {
8525 case 0:
8526 centerchan = (channel - 6);
8527 break;
8528 case 1:
8529 centerchan = (channel + 6);
8530 break;
8531 case 2:
8532 centerchan = (channel + 2);
8533 break;
8534 case 3:
8535 centerchan = (channel - 2);
8536 break;
8537 default:
8538 return -EINVAL;
8539 }
8540 }else if (width == 160){
8541 switch (channel) {
8542 case 1 ... 29:
8543 centerchan = 15;
8544 break;
8545 case 33 ... 61:
8546 centerchan = 47;
8547 break;
8548 case 65 ... 93:
8549 centerchan = 79;
8550 break;
8551 case 97 ... 125:
8552 centerchan = 111;
8553 break;
8554 case 129 ... 157:
8555 centerchan = 143;
8556 break;
8557 case 161 ... 189:
8558 centerchan = 175;
8559 break;
8560 case 193 ... 221:
8561 centerchan = 207;
8562 break;
8563 default:
8564 return -EINVAL;
8565 }
8566 }
8567 return centerchan;
8568}
developer06a01d92022-09-07 16:32:39 +08008569static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8570{
8571 BOOL onlyG, onlyN, onlyA;
8572 CHAR tmp[64];
8573 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8574 if (ret == RETURN_OK) {
8575 sncopy(hw_mode, hw_mode_size, tmp);
8576 }
8577 return ret;
8578}
8579
8580INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8581{
8582 // Sample commands:
8583 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8584 // hostapd_cli -i wifi0 chan_switch 30 2437
8585 char cmd[MAX_CMD_SIZE] = {0};
8586 char buf[MAX_BUF_SIZE] = {0};
8587 int freq = 0, ret = 0;
8588 char center_freq1_str[32] = ""; // center_freq1=%d
8589 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8590 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8591 char hw_mode[16] = ""; // n|ac
8592 char bw_mode[16] = ""; // ht|ht vht
8593 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08008594 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008595 int sec_chan_offset;
8596 int width;
developer4fb0b922022-09-30 14:29:09 +08008597 char config_file[64] = {0};
8598 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008599 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008600 wifi_band band = band_invalid;
8601 int center_chan = 0;
8602 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008603
developer4fb0b922022-09-30 14:29:09 +08008604 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008605
developerd946fd62022-12-08 18:03:28 +08008606 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8607 return RETURN_ERR;
8608
developer06a01d92022-09-07 16:32:39 +08008609 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8610
developerb7593de2022-10-18 09:51:57 +08008611 band = wifi_index_to_band(radioIndex);
8612
developer5884e982022-10-06 10:52:50 +08008613 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008614
8615 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008616 if (channel){
developerb7593de2022-10-18 09:51:57 +08008617 if (band == band_6){
8618 freq = util_6G_chan_to_freq(channel);
8619 }else{
8620 freq = util_chan_to_freq(channel);
8621 }
developer5884e982022-10-06 10:52:50 +08008622 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008623
developer5884e982022-10-06 10:52:50 +08008624 // Provide bandwith if specified
8625 if (channel_width_MHz > 20) {
8626 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8627 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8628 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008629
developer5884e982022-10-06 10:52:50 +08008630 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8631 }else if (channel_width_MHz == 20){
8632 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8633 }
developer06a01d92022-09-07 16:32:39 +08008634
developerb7593de2022-10-18 09:51:57 +08008635
developer5884e982022-10-06 10:52:50 +08008636 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008637 if (band == band_6){
8638 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8639 if(center_chan){
8640 center_freq1 = util_6G_chan_to_freq(center_chan);
8641 }
8642 }else{
8643 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8644 if(center_chan){
8645 center_freq1 = util_chan_to_freq(center_chan);
8646 }
developer5884e982022-10-06 10:52:50 +08008647 }
developerb7593de2022-10-18 09:51:57 +08008648
8649 if (center_freq1)
8650 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8651
8652 }
8653
8654 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8655 if (band == band_6){
8656 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8657 }else{
8658 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008659 }
developerb7593de2022-10-18 09:51:57 +08008660 if (sec_chan_offset != -EINVAL)
8661 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008662
developer5884e982022-10-06 10:52:50 +08008663 // Only the first AP, other are hanging on the same radio
8664 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08008665 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
8666 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08008667 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8668 wifi_dbg_printf("execute: '%s'\n", cmd);
8669 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008670
developer5884e982022-10-06 10:52:50 +08008671 ret = wifi_setRadioChannel(radioIndex, channel);
8672 if (ret != RETURN_OK) {
8673 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8674 return RETURN_ERR;
8675 }
8676
8677 if (sec_chan_offset == 1) ext_str = "Above";
8678 else if (sec_chan_offset == -1) ext_str = "Below";
8679
8680 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008681
developer5884e982022-10-06 10:52:50 +08008682 } else {
8683 if (channel_width_MHz > 20)
8684 ext_str = "Above";
8685 }
developer4fb0b922022-09-30 14:29:09 +08008686 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8687 _syscmd(cmd, buf, sizeof(buf));
8688 if (strlen(buf) != 0)
8689 stbcEnable = TRUE;
8690
developer06a01d92022-09-07 16:32:39 +08008691 wifi_setRadioExtChannel(radioIndex, ext_str);
8692
developer4fb0b922022-09-30 14:29:09 +08008693 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8694
developer06a01d92022-09-07 16:32:39 +08008695 char mhz_str[16];
8696 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8697 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8698
8699 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8700
8701 return RETURN_OK;
8702}
8703
8704INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8705{
developer615510b2022-09-27 10:14:35 +08008706 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008707 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008708 char cmd[256]={0};
8709 char buf[128]={0};
8710 char file_name[32] = {0};
8711 char filter_SSID[32] = {0};
8712 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08008713 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08008714 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008715 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008716 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008717 size_t len=0;
8718 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008719 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008720 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008721 bool filter_enable = false;
8722 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008723 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008724
developer615510b2022-09-27 10:14:35 +08008725 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008726
developer615510b2022-09-27 10:14:35 +08008727 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8728 f = fopen(file_name, "r");
8729 if (f != NULL) {
8730 fgets(filter_SSID, sizeof(file_name), f);
8731 if (strlen(filter_SSID) != 0)
8732 filter_enable = true;
8733 fclose(f);
8734 }
8735
developerd946fd62022-12-08 18:03:28 +08008736 if (GetInterfaceName(radio_index, interface_name) != RETURN_OK)
8737 return RETURN_ERR;
8738
developer033b37b2022-10-18 11:27:46 +08008739 phyId = radio_index_to_phy(radio_index);
8740
8741 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008742 _syscmd(cmd, buf, sizeof(buf));
8743 channels_num = strtol(buf, NULL, 10);
8744
developerd946fd62022-12-08 18:03:28 +08008745 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8746 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
developer615510b2022-09-27 10:14:35 +08008747 fprintf(stderr, "cmd: %s\n", cmd);
8748 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008749 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8750 return RETURN_ERR;
8751 }
developer5550e242022-09-30 09:59:32 +08008752
8753 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8754 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8755
developer615510b2022-09-27 10:14:35 +08008756 ret = fgets(line, sizeof(line), f);
8757 while (ret != NULL) {
8758 if(strstr(line, "BSS") != NULL) { // new neighbor info
8759 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8760 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8761 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8762
8763 if (!filter_BSS) {
8764 index++;
8765 wifi_neighbor_ap2_t *tmp;
8766 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8767 if (tmp == NULL) { // no more memory to use
8768 index--;
8769 wifi_dbg_printf("%s: realloc failed\n", __func__);
8770 break;
8771 }
8772 scan_array = tmp;
8773 }
8774 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008775
developer615510b2022-09-27 10:14:35 +08008776 filter_BSS = false;
8777 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8778 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8779 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8780 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8781 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008782 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008783 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008784
developer615510b2022-09-27 10:14:35 +08008785 if (freq >= 2412 && freq <= 2484) {
8786 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8787 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8788 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8789 }
8790 else if (freq >= 5160 && freq <= 5805) {
8791 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8792 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8793 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8794 }
developer06a01d92022-09-07 16:32:39 +08008795
developer615510b2022-09-27 10:14:35 +08008796 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008797 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008798 for (int i = 0; i < channels_num; i++) {
8799 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8800 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8801 break;
8802 }
8803 }
developer06a01d92022-09-07 16:32:39 +08008804 }
developer615510b2022-09-27 10:14:35 +08008805 } else if (strstr(line, "beacon interval") != NULL) {
8806 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8807 } else if (strstr(line, "signal") != NULL) {
8808 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8809 } else if (strstr(line,"SSID") != NULL) {
8810 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8811 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8812 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008813 }
developer615510b2022-09-27 10:14:35 +08008814 } else if (strstr(line, "Supported rates") != NULL) {
8815 char SRate[80] = {0}, *tmp = NULL;
8816 memset(buf, 0, sizeof(buf));
8817 strcpy(SRate, line);
8818 tmp = strtok(SRate, ":");
8819 tmp = strtok(NULL, ":");
8820 strcpy(buf, tmp);
8821 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008822
developer615510b2022-09-27 10:14:35 +08008823 tmp = strtok(buf, " \n");
8824 while (tmp != NULL) {
8825 strcat(SRate, tmp);
8826 if (SRate[strlen(SRate) - 1] == '*') {
8827 SRate[strlen(SRate) - 1] = '\0';
8828 }
8829 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008830
developer615510b2022-09-27 10:14:35 +08008831 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008832 }
developer615510b2022-09-27 10:14:35 +08008833 SRate[strlen(SRate) - 1] = '\0';
8834 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8835 } else if (strstr(line, "DTIM") != NULL) {
8836 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8837 } else if (strstr(line, "VHT capabilities") != NULL) {
8838 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8839 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8840 } else if (strstr(line, "HT capabilities") != NULL) {
8841 strcat(scan_array[index].ap_SupportedStandards, ",n");
8842 strcpy(scan_array[index].ap_OperatingStandards, "n");
8843 } else if (strstr(line, "VHT operation") != NULL) {
8844 ret = fgets(line, sizeof(line), f);
8845 sscanf(line," * channel width: %d", &vht_channel_width);
8846 if(vht_channel_width == 1) {
8847 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8848 } else {
8849 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8850 }
8851 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8852 continue;
8853 } else if (strstr(line, "HT operation") != NULL) {
8854 ret = fgets(line, sizeof(line), f);
8855 sscanf(line," * secondary channel offset: %s", &buf);
8856 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008857 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008858 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 +08008859 }
developer615510b2022-09-27 10:14:35 +08008860 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008861 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008862 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8863 } else {
8864 //20Mhz
8865 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 +08008866 }
developer615510b2022-09-27 10:14:35 +08008867 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008868 continue;
developer615510b2022-09-27 10:14:35 +08008869 } else if (strstr(line, "HE capabilities") != NULL) {
8870 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8871 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8872 ret = fgets(line, sizeof(line), f);
8873 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8874 if (strstr(line, "HE40/2.4GHz") != NULL)
8875 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8876 else
8877 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8878 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8879 if (strstr(line, "HE80/5GHz") != NULL) {
8880 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8881 ret = fgets(line, sizeof(line), f);
8882 } else
8883 continue;
8884 if (strstr(line, "HE160/5GHz") != NULL)
8885 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008886 }
developer615510b2022-09-27 10:14:35 +08008887 continue;
8888 } else if (strstr(line, "WPA") != NULL) {
8889 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8890 } else if (strstr(line, "RSN") != NULL) {
8891 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8892 } else if (strstr(line, "Group cipher") != NULL) {
8893 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8894 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8895 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008896 }
developer06a01d92022-09-07 16:32:39 +08008897 }
developer615510b2022-09-27 10:14:35 +08008898 ret = fgets(line, sizeof(line), f);
8899 }
8900
8901 if (!filter_BSS) {
8902 *output_array_size = index + 1;
8903 } else {
8904 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8905 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008906 }
developer06a01d92022-09-07 16:32:39 +08008907 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008908 pclose(f);
developer5550e242022-09-30 09:59:32 +08008909 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008910 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008911 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008912}
developer615510b2022-09-27 10:14:35 +08008913
developer06a01d92022-09-07 16:32:39 +08008914INT wifi_getApAssociatedDeviceStats(
8915 INT apIndex,
8916 mac_address_t *clientMacAddress,
8917 wifi_associated_dev_stats_t *associated_dev_stats,
8918 u64 *handle)
8919{
8920 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8921 char interface_name[50] = {0};
8922 char cmd[1024] = {0};
8923 char mac_str[18] = {0};
8924 char *key = NULL;
8925 char *val = NULL;
8926 FILE *f = NULL;
8927 char *line = NULL;
8928 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08008929
8930 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8931 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8932 return RETURN_ERR;
8933 }
8934
8935 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8936 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8937 if((f = popen(cmd, "r")) == NULL) {
8938 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8939 return RETURN_ERR;
8940 }
8941
developer30423732022-12-01 16:17:49 +08008942 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08008943 key = strtok(line,":");
8944 val = strtok(NULL,":");
8945
8946 if(!strncmp(key,"rx bytes",8))
8947 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8948 if(!strncmp(key,"tx bytes",8))
8949 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8950 if(!strncmp(key,"rx packets",10))
8951 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8952 if(!strncmp(key,"tx packets",10))
8953 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8954 if(!strncmp(key,"tx retries",10))
8955 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8956 if(!strncmp(key,"tx failed",9))
8957 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8958 if(!strncmp(key,"rx drop misc",13))
8959 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8960 if(!strncmp(key,"rx bitrate",10)) {
8961 val = strtok(val, " ");
8962 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8963 }
8964 if(!strncmp(key,"tx bitrate",10)) {
8965 val = strtok(val, " ");
8966 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8967 }
8968 }
8969 free(line);
8970 pclose(f);
8971 return RETURN_OK;
8972}
8973
8974INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8975{
developerd946fd62022-12-08 18:03:28 +08008976 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008977 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8978
8979 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8980 if (NULL == output_string)
8981 return RETURN_ERR;
8982
developerd946fd62022-12-08 18:03:28 +08008983 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8984 return RETURN_ERR;
8985 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer06a01d92022-09-07 16:32:39 +08008986 _syscmd(cmd, buf, sizeof(buf));
8987
8988 //size of SSID name restricted to value less than 32 bytes
8989 snprintf(output_string, 32, "%s", buf);
8990 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8991
8992 return RETURN_OK;
8993}
8994
8995INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8996{
8997 //char cmd[MAX_CMD_SIZE] = {0};
8998 char config_file[MAX_BUF_SIZE] = {0};
8999 char buf[32] = {0};
9000
9001 if (!output_filterMode)
9002 return RETURN_ERR;
9003
9004 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9005 //_syscmd(cmd, buf, sizeof(buf));
9006 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9007 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009008 if(strlen(buf) == 0) {
9009 *output_filterMode = 0;
9010 }
9011 else {
9012 int macaddr_acl_mode = strtol(buf, NULL, 10);
9013 if (macaddr_acl_mode == 1) {
9014 *output_filterMode = 1;
9015 } else if (macaddr_acl_mode == 0) {
9016 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9017 if (strlen(buf) == 0) {
9018 *output_filterMode = 0;
9019 } else {
9020 *output_filterMode = 2;
9021 }
9022 } else {
9023 return RETURN_ERR;
9024 }
9025 }
developer06a01d92022-09-07 16:32:39 +08009026
9027 return RETURN_OK;
9028}
9029
9030INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9031{
9032 FILE *fp = NULL;
9033 char str[MAX_BUF_SIZE] = {0};
9034 int wificlientindex = 0 ;
9035 int count = 0;
9036 int signalstrength = 0;
9037 int arr[MACADDRESS_SIZE] = {0};
9038 unsigned char mac[MACADDRESS_SIZE] = {0};
9039 UINT wifi_count = 0;
9040 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9041 char pipeCmd[MAX_CMD_SIZE] = {0};
9042
9043 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9044 *output_array_size = 0;
9045 *associated_dev_array = NULL;
9046 char interface_name[50] = {0};
9047
9048 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9049 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9050 return RETURN_ERR;
9051 }
9052
9053 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9054 fp = popen(pipeCmd, "r");
9055 if (fp == NULL)
9056 {
9057 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9058 return RETURN_ERR;
9059 }
9060
9061 /* Read the output a line at a time - output it. */
9062 fgets(str, sizeof(str)-1, fp);
9063 wifi_count = (unsigned int) atoi ( str );
9064 *output_array_size = wifi_count;
9065 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9066 pclose(fp);
9067
9068 if(wifi_count == 0)
9069 {
9070 return RETURN_OK;
9071 }
9072 else
9073 {
9074 wifi_associated_dev2_t* temp = NULL;
9075 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9076 *associated_dev_array = temp;
9077 if(temp == NULL)
9078 {
9079 printf("Error Statement. Insufficient memory \n");
9080 return RETURN_ERR;
9081 }
9082
9083 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9084 system(pipeCmd);
9085
9086 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9087 if(fp == NULL)
9088 {
9089 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9090 return RETURN_ERR;
9091 }
9092 fclose(fp);
9093
developer30423732022-12-01 16:17:49 +08009094 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009095 fp = popen(pipeCmd, "r");
9096 if(fp)
9097 {
9098 for(count =0 ; count < wifi_count; count++)
9099 {
9100 fgets(str, MAX_BUF_SIZE, fp);
9101 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9102 {
9103 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9104 {
9105 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9106
9107 }
9108 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9109 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]);
9110 }
9111 temp[count].cli_AuthenticationState = 1; //TODO
9112 temp[count].cli_Active = 1; //TODO
9113 }
9114 pclose(fp);
9115 }
9116
9117 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009118 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 +08009119 fp = popen(pipeCmd, "r");
9120 if(fp)
9121 {
9122 pclose(fp);
9123 }
9124 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9125 if(fp)
9126 {
9127 for(count =0 ; count < wifi_count ;count++)
9128 {
9129 fgets(str, MAX_BUF_SIZE, fp);
9130 signalstrength = atoi(str);
9131 temp[count].cli_RSSI = signalstrength;
9132 }
9133 pclose(fp);
9134 }
9135
9136
9137 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009138 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 +08009139 fp = popen(pipeCmd, "r");
9140 if (fp)
9141 {
9142 pclose(fp);
9143 }
9144 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9145 if (fp)
9146 {
9147 for (count = 0; count < wifi_count; count++)
9148 {
9149 fgets(str, MAX_BUF_SIZE, fp);
9150 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9151 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9152 }
9153 pclose(fp);
9154 }
9155
9156 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009157 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 +08009158 fp = popen(pipeCmd, "r");
9159 if (fp)
9160 {
9161 pclose(fp);
9162 }
9163 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9164 if (fp)
9165 {
9166 for (count = 0; count < wifi_count; count++)
9167 {
9168 fgets(str, MAX_BUF_SIZE, fp);
9169 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9170 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9171 }
9172 pclose(fp);
9173 }
9174 }
9175 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9176 return RETURN_OK;
9177
9178}
9179
9180INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9181{
9182#if 0
9183 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009184 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009185 _syscmd(cmd, buf, sizeof(buf));*/
9186
9187 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9188 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9189 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9190 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9191
9192 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.
9193 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].
9194 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].
9195 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].
9196 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9197 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9198
9199 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9200 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9201 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9202 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.
9203 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.
9204 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.
9205 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.
9206 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.
9207 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.
9208 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.
9209 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9210#endif
9211
9212 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009213 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009214 char pipeCmd[128] = {0};
9215 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009216 wifi_ssidTrafficStats2_t *out = output_struct;
9217
developerce736392022-09-13 15:24:34 +08009218 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009219 if (!output_struct)
9220 return RETURN_ERR;
9221
developerce736392022-09-13 15:24:34 +08009222 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerdbbd6782022-12-16 14:26:20 +08009223 if (GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
9224 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009225 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009226
developer06a01d92022-09-07 16:32:39 +08009227 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009228 if (fp == NULL) {
9229 fprintf(stderr, "%s: popen failed\n", __func__);
9230 return RETURN_ERR;
9231 }
9232 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009233 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009234
developerce736392022-09-13 15:24:34 +08009235 if (strlen(str) == 0) // interface not exist
9236 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009237
developerce736392022-09-13 15:24:34 +08009238 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9239 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009240
developerce736392022-09-13 15:24:34 +08009241 memset(str, 0, sizeof(str));
9242 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009243 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009244 if (fp == NULL) {
9245 fprintf(stderr, "%s: popen failed\n", __func__);
9246 return RETURN_ERR;
9247 }
9248 fgets(str, sizeof(str), fp);
9249
9250 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9251 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009252 pclose(fp);
developerce736392022-09-13 15:24:34 +08009253
9254 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9255 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9256
9257 // Not supported
9258 output_struct->ssid_RetransCount = 0;
9259 output_struct->ssid_FailedRetransCount = 0;
9260 output_struct->ssid_RetryCount = 0;
9261 output_struct->ssid_MultipleRetryCount = 0;
9262 output_struct->ssid_ACKFailureCount = 0;
9263 output_struct->ssid_AggregatedPacketCount = 0;
9264
developer06a01d92022-09-07 16:32:39 +08009265 return RETURN_OK;
9266}
9267
9268//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).
9269INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9270{
9271 char output_val[16]={'\0'};
9272 char config_file[MAX_BUF_SIZE] = {0};
9273
9274 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9275 if (!output)
9276 return RETURN_ERR;
9277 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9278 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9279
9280 if( strcmp(output_val,"1") == 0 )
9281 *output = TRUE;
9282 else
9283 *output = FALSE;
9284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9285
9286 return RETURN_OK;
9287}
9288
9289INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9290{
9291 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9292 char str[MAX_BUF_SIZE]={'\0'};
9293 char string[MAX_BUF_SIZE]={'\0'};
9294 char cmd[MAX_CMD_SIZE]={'\0'};
9295 char *ch;
9296 char config_file[MAX_BUF_SIZE] = {0};
9297 struct params params;
9298
9299 if(enable == TRUE)
9300 strcpy(string,"1");
9301 else
9302 strcpy(string,"0");
9303
9304 params.name = "ap_isolate";
9305 params.value = string;
9306
9307 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9308 wifi_hostapdWrite(config_file,&params,1);
9309 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9310
9311 return RETURN_OK;
9312}
9313
9314INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9315{
9316 if (NULL == output_dBm)
9317 return RETURN_ERR;
9318
9319 *output_dBm = 0;
9320 return RETURN_OK;
9321}
9322
9323INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9324{
9325 return RETURN_OK;
9326}
9327INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9328{
9329 return RETURN_OK;
9330}
9331INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9332{
9333 return RETURN_OK;
9334}
9335INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9336{
9337 return RETURN_OK;
9338}
9339INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9340{
9341 return RETURN_OK;
9342}
9343INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9344{
9345 char config_file[MAX_BUF_SIZE] = {0};
9346 struct params list;
9347
9348 list.name = "bss_transition";
9349 list.value = activate?"1":"0";
9350 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9351 wifi_hostapdWrite(config_file, &list, 1);
9352
9353 return RETURN_OK;
9354}
9355wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9356
9357void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9358{
9359 return;
9360}
9361
9362INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9363{
9364 // TODO Implement me!
9365 return RETURN_OK;
9366}
9367
9368INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9369{
developera3c68b92022-09-13 15:27:29 +08009370 char file_name[128] = {0};
9371 char buf[128] = {0};
9372 FILE *f = NULL;
developer804c64f2022-10-19 13:54:40 +08009373 int max_num_radios = 0;
developera3c68b92022-09-13 15:27:29 +08009374
9375 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9376
developer804c64f2022-10-19 13:54:40 +08009377 wifi_getMaxRadioNumber(&max_num_radios);
developera3c68b92022-09-13 15:27:29 +08009378 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
developer804c64f2022-10-19 13:54:40 +08009379 for (int index = 0; index < max_num_radios; index++) {
developera3c68b92022-09-13 15:27:29 +08009380 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9381 f = fopen(file_name, "w");
9382 if (f == NULL)
9383 return RETURN_ERR;
9384 // For mode == 0 is to disable filter, just don't write to the file.
9385 if (mode)
9386 fprintf(f, "%s", essid);
9387
9388 fclose(f);
9389 }
9390 } else { // special case, need to set AP's SSID as filter for each radio.
9391 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9392 f = fopen(file_name, "w");
9393 if (f == NULL)
9394 return RETURN_ERR;
9395
9396 // For mode == 0 is to disable filter, just don't write to the file.
9397 if (mode)
9398 fprintf(f, "%s", essid);
9399
9400 fclose(f);
9401 }
9402
9403 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009404 return RETURN_OK;
9405}
9406
9407INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9408{
9409 // TODO Implement me!
9410 //Apply wifi_pushRadioChannel() instantly
9411 return RETURN_ERR;
9412}
9413
9414INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9415{
9416 // TODO Implement me!
9417 return RETURN_OK;
9418}
9419
9420#ifdef HAL_NETLINK_IMPL
9421static int tidStats_callback(struct nl_msg *msg, void *arg) {
9422 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9423 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9424 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9425 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9426 int rem , tid_index = 0;
9427
9428 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9429 wifi_associated_dev_tid_entry_t *stats_entry;
9430
9431 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9432 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9433 };
9434 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9435 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9436 };
9437
9438 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9439 genlmsg_attrlen(gnlh, 0), NULL);
9440
9441
9442 if (!tb[NL80211_ATTR_STA_INFO]) {
9443 fprintf(stderr, "station stats missing!\n");
9444 return NL_SKIP;
9445 }
9446
9447 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9448 tb[NL80211_ATTR_STA_INFO],
9449 stats_policy)) {
9450 fprintf(stderr, "failed to parse nested attributes!\n");
9451 return NL_SKIP;
9452 }
9453
9454 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9455 {
9456 stats_entry = &out->tid_array[tid_index];
9457
9458 stats_entry->tid = tid_index;
9459 stats_entry->ac = _tid_ac_index_get[tid_index];
9460
9461 if(sinfo[NL80211_STA_INFO_TID_STATS])
9462 {
9463 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9464 printf("failed to parse nested stats attributes!");
9465 return NL_SKIP;
9466 }
9467 }
9468 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9469 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9470
9471 if(tid_index < (PS_MAX_TID - 1))
9472 tid_index++;
9473 }
9474 //ToDo: sum_time_ms, ewma_time_ms
9475 return NL_SKIP;
9476}
9477#endif
9478
9479INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9480{
9481#ifdef HAL_NETLINK_IMPL
9482 Netlink nl;
9483 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009484 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009485
developerd946fd62022-12-08 18:03:28 +08009486 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9487 return RETURN_ERR;
9488
9489 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009490
9491 nl.id = initSock80211(&nl);
9492
9493 if (nl.id < 0) {
9494 fprintf(stderr, "Error initializing netlink \n");
9495 return -1;
9496 }
9497
9498 struct nl_msg* msg = nlmsg_alloc();
9499
9500 if (!msg) {
9501 fprintf(stderr, "Failed to allocate netlink message.\n");
9502 nlfree(&nl);
9503 return -2;
9504 }
9505
9506 genlmsg_put(msg,
9507 NL_AUTO_PORT,
9508 NL_AUTO_SEQ,
9509 nl.id,
9510 0,
9511 0,
9512 NL80211_CMD_GET_STATION,
9513 0);
9514
9515 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9516 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9517 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9518 nl_send_auto(nl.socket, msg);
9519 nl_recvmsgs(nl.socket, nl.cb);
9520 nlmsg_free(msg);
9521 nlfree(&nl);
9522 return RETURN_OK;
9523#else
9524//iw implementation
9525#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9526#define TOTAL_MAX_LINES 50
9527
9528 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009529 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009530 FILE *fp=NULL;
9531 char pipeCmd[1024]= {'\0'};
9532 int lines,tid_index=0;
9533 char mac_addr[20] = {'\0'};
9534
developerd946fd62022-12-08 18:03:28 +08009535 if (GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9536 return RETURN_ERR;
9537
developer06a01d92022-09-07 16:32:39 +08009538 wifi_associated_dev_tid_entry_t *stats_entry;
9539
developer06a01d92022-09-07 16:32:39 +08009540 strcpy(mac_addr,clientMacAddress);
9541
9542 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9543 fp= popen(pipeCmd,"r");
9544 if(fp == NULL)
9545 {
9546 perror("popen for station dump failed\n");
9547 return RETURN_ERR;
9548 }
9549 pclose(fp);
9550
9551 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9552 fp=popen(pipeCmd,"r");
9553 if(fp == NULL)
9554 {
9555 perror("popen for grep station failed\n");
9556 return RETURN_ERR;
9557 }
9558 else if(fgets(buf,sizeof(buf),fp) != NULL)
9559 lines=atoi(buf);
9560 else
9561 {
9562 pclose(fp);
9563 fprintf(stderr,"No devices are connected \n");
9564 return RETURN_ERR;
9565 }
9566 pclose(fp);
9567
9568 if(lines == 1)
9569 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9570
9571 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9572 {
9573 stats_entry = &tid_stats->tid_array[tid_index];
9574 stats_entry->tid = tid_index;
9575
9576 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);
9577
9578 fp=popen(pipeCmd,"r");
9579 if(fp ==NULL)
9580 {
9581 perror("Failed to read from tid file \n");
9582 return RETURN_ERR;
9583 }
9584 else if(fgets(buf,sizeof(buf),fp) != NULL)
9585 stats_entry->num_msdus = atol(buf);
9586
9587 pclose(fp);
9588 stats_entry->ac = _tid_ac_index_get[tid_index];
9589// TODO:
9590// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9591// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9592 }
9593 return RETURN_OK;
9594#endif
9595}
9596
9597
9598INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9599{
developerd946fd62022-12-08 18:03:28 +08009600 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009601 char cmd[128]={0};
9602 char buf[128]={0};
9603 int freq = 0;
9604
9605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9606
9607 // full mode is used to scan all channels.
9608 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9609 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9610 ieee80211_channel_to_frequency(chan_list[0], &freq);
9611
developerd946fd62022-12-08 18:03:28 +08009612 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9613 return RETURN_ERR;
9614
developer615510b2022-09-27 10:14:35 +08009615 if (freq)
developerd946fd62022-12-08 18:03:28 +08009616 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +08009617 else
developerd946fd62022-12-08 18:03:28 +08009618 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +08009619
9620 _syscmd(cmd, buf, sizeof(buf));
9621 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9622
developer06a01d92022-09-07 16:32:39 +08009623 return RETURN_OK;
9624}
9625
9626
9627INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9628{
9629 // TODO Implement me!
9630 return RETURN_ERR;
9631}
9632
9633INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9634{
9635 // TODO Implement me!
9636 return RETURN_ERR;
9637}
9638
9639INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9640{
9641 // TODO Implement me!
9642 return RETURN_ERR;
9643}
9644
9645INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9646{
9647 // TODO Implement me!
9648 return RETURN_ERR;
9649}
9650
9651INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9652{
9653 // TODO Implement me!
9654 return RETURN_ERR;
9655}
9656
9657INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9658{
9659 // TODO Implement me!
9660 return RETURN_ERR;
9661}
9662
9663INT wifi_steering_eventUnregister(void)
9664{
9665 // TODO Implement me!
9666 return RETURN_ERR;
9667}
9668
9669INT wifi_delApAclDevices(INT apIndex)
9670{
9671#if 0
9672 char cmd[MAX_BUF_SIZE] = {0};
9673 char buf[MAX_BUF_SIZE] = {0};
9674
9675 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +08009676 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +08009677 if(_syscmd(cmd,buf,sizeof(buf)))
9678 return RETURN_ERR;
9679#endif
developere6aafda2022-09-13 14:59:28 +08009680 char cmd[MAX_CMD_SIZE]={0};
9681 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009682
developere6aafda2022-09-13 14:59:28 +08009683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9684 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9685 if(_syscmd(cmd, buf, sizeof(buf)))
9686 return RETURN_ERR;
9687 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009688
9689 return RETURN_OK;
9690}
9691
9692#ifdef HAL_NETLINK_IMPL
9693static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9694 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9695 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9696 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9697 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9698 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9699 char mac_addr[20],dev[20];
9700
9701 nla_parse(tb,
9702 NL80211_ATTR_MAX,
9703 genlmsg_attrdata(gnlh, 0),
9704 genlmsg_attrlen(gnlh, 0),
9705 NULL);
9706
9707 if(!tb[NL80211_ATTR_STA_INFO]) {
9708 fprintf(stderr, "sta stats missing!\n");
9709 return NL_SKIP;
9710 }
9711
9712 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9713 fprintf(stderr, "failed to parse nested attributes!\n");
9714 return NL_SKIP;
9715 }
9716 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9717
9718 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9719
9720 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9721 fprintf(stderr, "failed to parse nested rate attributes!");
9722 return NL_SKIP;
9723 }
9724
9725 if(sinfo[NL80211_STA_INFO_TID_STATS])
9726 {
9727 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9728 printf("failed to parse nested stats attributes!");
9729 return NL_SKIP;
9730 }
9731 }
9732
9733 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9734 {
9735 printf("Type is VHT\n");
9736 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9737 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9738
9739 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9740 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9741 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9742 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9743 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9744 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9745 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9746 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9747 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9748 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9749 }
9750 else
9751 {
9752 printf(" OFDM or CCK \n");
9753 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9754 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9755 }
9756
9757 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9758 if(rinfo[NL80211_RATE_INFO_MCS])
9759 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9760 }
9761 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9762 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9763 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9764 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9765
9766 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9767 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9768
9769 if (sinfo[NL80211_STA_INFO_SIGNAL])
9770 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9771 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9772 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9773 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9774 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9775 //rssi_array need to be filled
9776 return NL_SKIP;
9777}
9778#endif
9779
9780INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9781{
9782#ifdef HAL_NETLINK_IMPL
9783 Netlink nl;
developerd946fd62022-12-08 18:03:28 +08009784 char if_name[32];
9785 if (GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9786 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08009787
9788 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9789
9790 if (*output_array_size <= 0)
9791 return RETURN_OK;
9792
developer06a01d92022-09-07 16:32:39 +08009793 nl.id = initSock80211(&nl);
9794
9795 if (nl.id < 0) {
9796 fprintf(stderr, "Error initializing netlink \n");
9797 return 0;
9798 }
9799
9800 struct nl_msg* msg = nlmsg_alloc();
9801
9802 if (!msg) {
9803 fprintf(stderr, "Failed to allocate netlink message.\n");
9804 nlfree(&nl);
9805 return 0;
9806 }
9807
9808 genlmsg_put(msg,
9809 NL_AUTO_PORT,
9810 NL_AUTO_SEQ,
9811 nl.id,
9812 0,
9813 0,
9814 NL80211_CMD_GET_STATION,
9815 0);
9816
9817 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9818 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9819 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9820 nl_send_auto(nl.socket, msg);
9821 nl_recvmsgs(nl.socket, nl.cb);
9822 nlmsg_free(msg);
9823 nlfree(&nl);
9824 return RETURN_OK;
9825#else
9826 //TODO Implement me
9827 return RETURN_OK;
9828#endif
9829}
9830
9831#ifdef HAL_NETLINK_IMPL
9832static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9833 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9834 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9835 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9836 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9837 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9838 char mac_addr[20],dev[20];
9839
9840 nla_parse(tb,
9841 NL80211_ATTR_MAX,
9842 genlmsg_attrdata(gnlh, 0),
9843 genlmsg_attrlen(gnlh, 0),
9844 NULL);
9845
9846 if(!tb[NL80211_ATTR_STA_INFO]) {
9847 fprintf(stderr, "sta stats missing!\n");
9848 return NL_SKIP;
9849 }
9850
9851 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9852 fprintf(stderr, "failed to parse nested attributes!\n");
9853 return NL_SKIP;
9854 }
9855
9856 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9857
9858 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9859
9860 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9861 fprintf(stderr, "failed to parse nested rate attributes!");
9862 return NL_SKIP;
9863 }
9864
9865 if(sinfo[NL80211_STA_INFO_TID_STATS])
9866 {
9867 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9868 printf("failed to parse nested stats attributes!");
9869 return NL_SKIP;
9870 }
9871 }
9872 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9873 {
9874 printf("Type is VHT\n");
9875 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9876 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9877
9878 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9879 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9880 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9881 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9882 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9883 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9884 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9885 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9886 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9887 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9888 }
9889 else
9890 {
9891 printf(" OFDM or CCK \n");
9892 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9893 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9894 }
9895
9896 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9897 if(rinfo[NL80211_RATE_INFO_MCS])
9898 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9899 }
9900
9901 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9902 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9903 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9904 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9905
9906 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9907 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9908 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9909
9910 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9911 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9912
9913 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9914 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9915
9916 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9917 ((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]);
9918
9919 return NL_SKIP;
9920}
9921#endif
9922
9923INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9924{
9925#ifdef HAL_NETLINK_IMPL
9926 Netlink nl;
9927 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009928 char interface_name[16] = {0};
9929 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9930 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08009931
9932 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9933
9934 if (*output_array_size <= 0)
9935 return RETURN_OK;
9936
developerd946fd62022-12-08 18:03:28 +08009937 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009938
9939 nl.id = initSock80211(&nl);
9940
9941 if(nl.id < 0) {
9942 fprintf(stderr, "Error initializing netlink \n");
9943 return 0;
9944 }
9945
9946 struct nl_msg* msg = nlmsg_alloc();
9947
9948 if(!msg) {
9949 fprintf(stderr, "Failed to allocate netlink message.\n");
9950 nlfree(&nl);
9951 return 0;
9952 }
9953
9954 genlmsg_put(msg,
9955 NL_AUTO_PORT,
9956 NL_AUTO_SEQ,
9957 nl.id,
9958 0,
9959 0,
9960 NL80211_CMD_GET_STATION,
9961 0);
9962
9963 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9964 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9965 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9966 nl_send_auto(nl.socket, msg);
9967 nl_recvmsgs(nl.socket, nl.cb);
9968 nlmsg_free(msg);
9969 nlfree(&nl);
9970 return RETURN_OK;
9971#else
9972 //TODO Implement me
9973 return RETURN_OK;
9974#endif
9975}
9976
9977INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9978{
9979 // TODO Implement me!
9980 char buf[MAX_BUF_SIZE] = {0};
9981 char config_file[MAX_BUF_SIZE] = {0};
9982
9983 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9984 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9985 *activate = (strncmp("1",buf,1) == 0);
9986
9987 return RETURN_OK;
9988}
9989
9990INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9991{
9992 char config_file[MAX_BUF_SIZE] = {0};
9993 struct params list;
9994
9995 list.name = "rrm_neighbor_report";
9996 list.value = activate?"1":"0";
9997 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9998 wifi_hostapdWrite(config_file, &list, 1);
9999
10000 return RETURN_OK;
10001}
10002
10003INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10004{
10005 char buf[32] = {0};
10006 char config_file[MAX_BUF_SIZE] = {0};
10007
10008 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10009 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10010 *activate = (strncmp("1",buf,1) == 0);
10011
10012 return RETURN_OK;
10013}
10014#undef HAL_NETLINK_IMPL
10015#ifdef HAL_NETLINK_IMPL
10016static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10017 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10018 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10019 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10020 char dev[20];
10021 int freq =0 ;
10022 static int i=0;
10023
10024 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10025
10026 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10027 };
10028
10029 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10030
10031 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10032
10033 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10034 fprintf(stderr, "survey data missing!\n");
10035 return NL_SKIP;
10036 }
10037
10038 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10039 {
10040 fprintf(stderr, "failed to parse nested attributes!\n");
10041 return NL_SKIP;
10042 }
10043
10044
10045 if(out[0].array_size == 1 )
10046 {
10047 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10048 {
10049 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10050 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10051 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10052
10053 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10054 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10055 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10056 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10057 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10058 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10059 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10060 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10061 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10062 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10063 if (sinfo[NL80211_SURVEY_INFO_TIME])
10064 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10065 return NL_STOP;
10066 }
10067 }
10068 else
10069 {
10070 if ( i <= out[0].array_size )
10071 {
10072 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10073 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10074 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10075
10076 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10077 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10078 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10079 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10080 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10081 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10082 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10083 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10084 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10085 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10086 if (sinfo[NL80211_SURVEY_INFO_TIME])
10087 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10088 }
10089 }
10090
10091 i++;
10092 return NL_SKIP;
10093}
10094#endif
10095
10096static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10097{
10098 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10099 FILE *fp;
10100
10101 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10102 {
10103 printf("Creating Frequency-Channel Map\n");
10104 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10105 }
10106 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10107 if((fp = popen(command, "r")))
10108 {
10109 fgets(output, sizeof(output), fp);
10110 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010111 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010112 }
10113
10114 return 0;
10115}
10116
10117static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10118{
10119 int freqMHz = -1;
10120 char cmd[MAX_CMD_SIZE] = {'\0'};
developer033b37b2022-10-18 11:27:46 +080010121 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080010122
10123 ieee80211_channel_to_frequency(channel, &freqMHz);
10124 if (freqMHz == -1) {
10125 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10126 return -1;
10127 }
10128
developer033b37b2022-10-18 11:27:46 +080010129 phyId = radio_index_to_phy(radioIndex);
10130 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 +080010131 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10132 radioIndex, freqMHz);
10133 return -1;
10134 }
10135
10136 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10137 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10138 return -1;
10139 }
10140
10141 return 0;
10142}
10143
10144static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10145{
10146 const char *ptr = buf;
10147 char *key = NULL;
10148 char *val = NULL;
10149 char line[256] = { '\0' };
10150
10151 while (ptr = get_line_from_str_buf(ptr, line)) {
10152 if (strstr(line, "Frequency")) continue;
10153
10154 key = strtok(line, ":");
10155 val = strtok(NULL, " ");
10156 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10157
10158 if (!strcmp(key, "noise")) {
10159 sscanf(val, "%d", &stats->ch_noise);
10160 if (stats->ch_noise == 0) {
10161 // Workaround for missing noise information.
10162 // Assume -95 for 2.4G and -103 for 5G
10163 if (radioIndex == 0) stats->ch_noise = -95;
10164 if (radioIndex == 1) stats->ch_noise = -103;
10165 }
10166 }
10167 else if (!strcmp(key, "channel active time")) {
10168 sscanf(val, "%llu", &stats->ch_utilization_total);
10169 }
10170 else if (!strcmp(key, "channel busy time")) {
10171 sscanf(val, "%llu", &stats->ch_utilization_busy);
10172 }
10173 else if (!strcmp(key, "channel receive time")) {
10174 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10175 }
10176 else if (!strcmp(key, "channel transmit time")) {
10177 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10178 }
10179 };
10180
10181 return 0;
10182}
10183
10184INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10185{
10186 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10187#ifdef HAL_NETLINK_IMPL
10188 Netlink nl;
10189 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010190 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010191
10192 local[0].array_size = array_size;
10193
developerd946fd62022-12-08 18:03:28 +080010194 if (GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10195 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010196
10197 nl.id = initSock80211(&nl);
10198
10199 if (nl.id < 0) {
10200 fprintf(stderr, "Error initializing netlink \n");
10201 return -1;
10202 }
10203
10204 struct nl_msg* msg = nlmsg_alloc();
10205
10206 if (!msg) {
10207 fprintf(stderr, "Failed to allocate netlink message.\n");
10208 nlfree(&nl);
10209 return -2;
10210 }
10211
10212 genlmsg_put(msg,
10213 NL_AUTO_PORT,
10214 NL_AUTO_SEQ,
10215 nl.id,
10216 0,
10217 NLM_F_DUMP,
10218 NL80211_CMD_GET_SURVEY,
10219 0);
10220
10221 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10222 nl_send_auto(nl.socket, msg);
10223 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10224 nl_recvmsgs(nl.socket, nl.cb);
10225 nlmsg_free(msg);
10226 nlfree(&nl);
10227 //Copying the Values
10228 for(int i=0;i<array_size;i++)
10229 {
10230 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10231 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10232 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10233 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10234 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10235 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10236 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10237 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10238 }
10239#else
10240 ULONG channel = 0;
10241 int i;
10242 int number_of_channels = array_size;
10243 char buf[512];
10244 INT ret;
10245 wifi_channelStats_t tmp_stats;
10246
10247 if (number_of_channels == 0) {
10248 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10249 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10250 return RETURN_ERR;
10251 }
10252 number_of_channels = 1;
10253 input_output_channelStats_array[0].ch_number = channel;
10254 }
10255
10256 for (i = 0; i < number_of_channels; i++) {
10257
10258 input_output_channelStats_array[i].ch_noise = 0;
10259 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10260 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10261 input_output_channelStats_array[i].ch_utilization_busy = 0;
10262 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10263 input_output_channelStats_array[i].ch_utilization_total = 0;
10264
10265 memset(buf, 0, sizeof(buf));
10266 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10267 return RETURN_ERR;
10268 }
10269 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10270 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10271 return RETURN_ERR;
10272 }
10273
10274 // XXX: fake missing 'self' counter which is not available in iw survey output
10275 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10276 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10277
10278 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10279 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10280 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10281 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10282 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10283
10284 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",
10285 __func__,
10286 input_output_channelStats_array[i].ch_number,
10287 input_output_channelStats_array[i].ch_noise,
10288 input_output_channelStats_array[i].ch_utilization_total,
10289 input_output_channelStats_array[i].ch_utilization_busy,
10290 input_output_channelStats_array[i].ch_utilization_busy_rx,
10291 input_output_channelStats_array[i].ch_utilization_busy_tx,
10292 input_output_channelStats_array[i].ch_utilization_busy_self,
10293 input_output_channelStats_array[i].ch_utilization_busy_ext);
10294 }
10295#endif
10296 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10297 return RETURN_OK;
10298}
10299#define HAL_NETLINK_IMPL
10300
10301/* Hostapd events */
10302
10303#ifndef container_of
10304#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10305#define container_of(ptr, type, member) \
10306 ((type *)((char *)ptr - offset_of(type, member)))
10307#endif /* container_of */
10308
10309struct ctrl {
10310 char sockpath[128];
10311 char sockdir[128];
10312 char bss[IFNAMSIZ];
10313 char reply[4096];
10314 int ssid_index;
10315 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10316 void (*overrun)(struct ctrl *ctrl);
10317 struct wpa_ctrl *wpa;
10318 unsigned int ovfl;
10319 size_t reply_len;
10320 int initialized;
10321 ev_timer retry;
10322 ev_timer watchdog;
10323 ev_stat stat;
10324 ev_io io;
10325};
10326static wifi_newApAssociatedDevice_callback clients_connect_cb;
10327static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10328static struct ctrl wpa_ctrl[MAX_APS];
10329static int initialized;
10330
10331static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10332{
10333 char cbuf[256] = {};
10334 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10335 struct cmsghdr *cmsg;
10336 unsigned int ovfl = ctrl->ovfl;
10337 unsigned int drop;
10338
10339 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10340 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10341 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10342 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10343
10344 drop = ovfl - ctrl->ovfl;
10345 ctrl->ovfl = ovfl;
10346
10347 return drop;
10348}
10349
10350static void ctrl_close(struct ctrl *ctrl)
10351{
10352 if (ctrl->io.cb)
10353 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10354 if (ctrl->retry.cb)
10355 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10356 if (!ctrl->wpa)
10357 return;
10358
10359 wpa_ctrl_detach(ctrl->wpa);
10360 wpa_ctrl_close(ctrl->wpa);
10361 ctrl->wpa = NULL;
10362 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10363}
10364
10365static void ctrl_process(struct ctrl *ctrl)
10366{
10367 const char *str;
10368 int drops;
10369 int level;
10370 int err;
10371
10372 /* Example events:
10373 *
10374 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10375 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10376 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10377 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10378 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10379 */
10380 if (!(str = index(ctrl->reply, '>')))
10381 return;
10382 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10383 return;
10384
10385 str++;
10386
10387 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10388 if (!(str = index(ctrl->reply, ' ')))
10389 return;
10390 wifi_associated_dev_t sta;
10391 memset(&sta, 0, sizeof(sta));
10392
10393 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10394 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10395 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10396
10397 sta.cli_Active=true;
10398
10399 (clients_connect_cb)(ctrl->ssid_index, &sta);
10400 goto handled;
10401 }
10402
10403 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10404 if (!(str = index(ctrl->reply, ' ')))
10405 return;
10406
10407 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10408 goto handled;
10409 }
10410
10411 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10412 printf("CTRL_WPA: handle TERMINATING event\n");
10413 goto retry;
10414 }
10415
10416 if (strncmp("AP-DISABLED", str, 11) == 0) {
10417 printf("CTRL_WPA: handle AP-DISABLED\n");
10418 goto retry;
10419 }
10420
10421 printf("Event not supported!!\n");
10422
10423handled:
10424
10425 if ((drops = ctrl_get_drops(ctrl))) {
10426 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10427 if (ctrl->overrun)
10428 ctrl->overrun(ctrl);
10429 }
10430
10431 return;
10432
10433retry:
10434 printf("WPA_CTRL: closing\n");
10435 ctrl_close(ctrl);
10436 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10437 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10438}
10439
10440static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10441{
10442 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10443 int err;
10444
10445 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10446 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10447 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10448 ctrl->reply[ctrl->reply_len] = 0;
10449 if (err < 0) {
10450 if (errno == EAGAIN || errno == EWOULDBLOCK)
10451 return;
10452 ctrl_close(ctrl);
10453 ev_timer_again(EV_A_ &ctrl->retry);
10454 return;
10455 }
10456
10457 ctrl_process(ctrl);
10458}
10459
10460static int ctrl_open(struct ctrl *ctrl)
10461{
10462 int fd;
10463
10464 if (ctrl->wpa)
10465 return 0;
10466
10467 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10468 if (!ctrl->wpa)
10469 goto err;
10470
10471 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10472 goto err_close;
10473
10474 fd = wpa_ctrl_get_fd(ctrl->wpa);
10475 if (fd < 0)
10476 goto err_detach;
10477
10478 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10479 goto err_detach;
10480
10481 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10482 ev_io_start(EV_DEFAULT_ &ctrl->io);
10483
10484 return 0;
10485
10486err_detach:
10487 wpa_ctrl_detach(ctrl->wpa);
10488err_close:
10489 wpa_ctrl_close(ctrl->wpa);
10490err:
10491 ctrl->wpa = NULL;
10492 return -1;
10493}
10494
10495static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10496{
10497 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10498
10499 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10500 ctrl_open(ctrl);
10501}
10502
10503static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10504{
10505 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10506
10507 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10508 if (ctrl_open(ctrl) == 0) {
10509 printf("WPA_CTRL: retry successful\n");
10510 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10511 }
10512}
10513
10514int ctrl_enable(struct ctrl *ctrl)
10515{
10516 if (ctrl->wpa)
10517 return 0;
10518
10519 if (!ctrl->stat.cb) {
10520 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10521 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10522 }
10523
10524 if (!ctrl->retry.cb) {
10525 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10526 }
10527
10528 return ctrl_open(ctrl);
10529}
10530
10531static void
10532ctrl_msg_cb(char *buf, size_t len)
10533{
10534 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10535
10536 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10537 ctrl_process(ctrl);
10538}
10539
10540static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10541{
10542 int err;
10543
10544 if (!ctrl->wpa)
10545 return -1;
10546 if (*reply_len < 2)
10547 return -1;
10548
10549 (*reply_len)--;
10550 ctrl->reply_len = sizeof(ctrl->reply);
10551 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10552 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10553 if (err < 0)
10554 return err;
10555
10556 if (ctrl->reply_len > *reply_len)
10557 ctrl->reply_len = *reply_len;
10558
10559 *reply_len = ctrl->reply_len;
10560 memcpy(reply, ctrl->reply, *reply_len);
10561 reply[*reply_len - 1] = 0;
10562 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10563 return 0;
10564}
10565
10566static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10567{
10568 const char *pong = "PONG";
10569 const char *ping = "PING";
10570 char reply[1024];
10571 size_t len = sizeof(reply);
10572 int err;
10573 ULONG s, snum;
10574 INT ret;
10575 BOOL status;
10576
10577 printf("WPA_CTRL: watchdog cb\n");
10578
10579 ret = wifi_getSSIDNumberOfEntries(&snum);
10580 if (ret != RETURN_OK) {
10581 printf("%s: failed to get SSID count", __func__);
10582 return;
10583 }
10584
10585 if (snum > MAX_APS) {
10586 printf("more ssid than supported! %lu\n", snum);
10587 return;
10588 }
10589
10590 for (s = 0; s < snum; s++) {
10591 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010592 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010593 continue;
10594 }
10595 if (status == false) continue;
10596
10597 memset(reply, 0, sizeof(reply));
10598 len = sizeof(reply);
10599 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10600 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10601 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10602 continue;
10603
10604 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10605 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010606 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010607 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10608 }
10609}
10610
10611static int init_wpa()
10612{
10613 int ret = 0, i = 0;
10614 ULONG s, snum;
10615
10616 ret = wifi_getSSIDNumberOfEntries(&snum);
10617 if (ret != RETURN_OK) {
10618 printf("%s: failed to get SSID count", __func__);
10619 return RETURN_ERR;
10620 }
10621
10622 if (snum > MAX_APS) {
10623 printf("more ssid than supported! %lu\n", snum);
10624 return RETURN_ERR;
10625 }
10626
10627 for (s = 0; s < snum; s++) {
10628 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10629 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10630 wpa_ctrl[s].ssid_index = s;
10631 ctrl_enable(&wpa_ctrl[s]);
10632 }
10633
10634 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10635 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10636
10637 initialized = 1;
10638 printf("WPA_CTRL: initialized\n");
10639
10640 return RETURN_OK;
10641}
10642
10643void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10644{
10645 clients_connect_cb = callback_proc;
10646 if (!initialized)
10647 init_wpa();
10648}
10649
10650void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10651{
10652 clients_disconnect_cb = callback_proc;
10653 if (!initialized)
10654 init_wpa();
10655}
10656
10657INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10658{
10659 // TODO Implement me!
10660 return RETURN_ERR;
10661}
10662
10663INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10664{
10665 // TODO Implement me!
10666 return RETURN_ERR;
10667}
10668
10669INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10670{
10671 int i;
10672 char cmd[256];
10673 char channel_numbers_buf[256];
10674 char dfs_state_buf[256];
10675 char line[256];
10676 const char *ptr;
10677
10678 memset(cmd, 0, sizeof(cmd));
10679 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10680 memset(line, 0, sizeof(line));
10681 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10682 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10683
10684 if (radioIndex == 0) { // 2.4G - all allowed
10685 if (outputMapSize < 11) {
10686 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10687 return RETURN_ERR;
10688 }
10689
10690 for (i = 0; i < 11; i++) {
10691 outputMap[i].ch_number = i + 1;
10692 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10693 }
10694
10695 return RETURN_OK;
10696 }
10697
10698 if (radioIndex == 1) { // 5G
10699// Example output of iw list:
10700//
10701// Frequencies:
10702// * 5180 MHz [36] (17.0 dBm)
10703// * 5200 MHz [40] (17.0 dBm)
10704// * 5220 MHz [44] (17.0 dBm)
10705// * 5240 MHz [48] (17.0 dBm)
10706// * 5260 MHz [52] (23.0 dBm) (radar detection)
10707// DFS state: usable (for 78930 sec)
10708// DFS CAC time: 60000 ms
10709// * 5280 MHz [56] (23.0 dBm) (radar detection)
10710// DFS state: usable (for 78930 sec)
10711// DFS CAC time: 60000 ms
10712// * 5300 MHz [60] (23.0 dBm) (radar detection)
10713// DFS state: usable (for 78930 sec)
10714// DFS CAC time: 60000 ms
10715// * 5320 MHz [64] (23.0 dBm) (radar detection)
10716// DFS state: usable (for 78930 sec)
10717// DFS CAC time: 60000 ms
10718// * 5500 MHz [100] (disabled)
10719// * 5520 MHz [104] (disabled)
10720// * 5540 MHz [108] (disabled)
10721// * 5560 MHz [112] (disabled)
10722//
10723// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10724 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10725 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10726 return RETURN_ERR;
10727 }
10728
10729 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10730 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10731 return RETURN_ERR;
10732 }
10733
10734 ptr = channel_numbers_buf;
10735 i = 0;
10736 while (ptr = get_line_from_str_buf(ptr, line)) {
10737 if (i >= outputMapSize) {
10738 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10739 return RETURN_ERR;
10740 }
10741 sscanf(line, "%d", &outputMap[i].ch_number);
10742
10743 memset(cmd, 0, sizeof(cmd));
10744 // Below command should fetch string for DFS state (usable, available or unavailable)
10745 // Example line: "DFS state: usable (for 78930 sec)"
10746 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) {
10747 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10748 return RETURN_ERR;
10749 }
10750
10751 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10752 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10753 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10754 return RETURN_ERR;
10755 }
10756
10757 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10758
10759 if (!strcmp(dfs_state_buf, "usable")) {
10760 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10761 } else if (!strcmp(dfs_state_buf, "available")) {
10762 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10763 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10764 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10765 } else {
10766 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10767 }
10768 i++;
10769 }
10770
10771 return RETURN_OK;
10772 }
10773
10774 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10775 return RETURN_ERR;
10776}
10777
10778INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10779{
10780 // TODO Implement me!
10781 return RETURN_ERR;
10782}
10783
10784INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10785{
10786 return RETURN_OK;
10787}
10788
10789INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10790{
10791 // TODO Implement me!
10792 return RETURN_ERR;
10793}
10794
10795INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10796{
10797 // TODO API refrence Implementaion is present on RPI hal
10798 return RETURN_ERR;
10799}
10800
10801INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10802{
developerd946fd62022-12-08 18:03:28 +080010803 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +080010804 char cmd[128]={'\0'};
10805 char buf[128]={'\0'};
10806 char *support;
10807 int maximum_tx = 0, current_tx = 0;
10808
10809 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10810 if(txpwr_pcntg == NULL)
10811 return RETURN_ERR;
10812
developerd946fd62022-12-08 18:03:28 +080010813 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10814 return RETURN_ERR;
10815
developera5005b62022-09-13 15:43:35 +080010816 // Get the maximum tx power of the device
developerd946fd62022-12-08 18:03:28 +080010817 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developera5005b62022-09-13 15:43:35 +080010818 _syscmd(cmd, buf, sizeof(buf));
10819 maximum_tx = strtol(buf, NULL, 10);
10820
10821 // Get the current tx power
10822 memset(cmd, 0, sizeof(cmd));
10823 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080010824 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
developera5005b62022-09-13 15:43:35 +080010825 _syscmd(cmd, buf, sizeof(buf));
10826 current_tx = strtol(buf, NULL, 10);
10827
10828 // Get the power supported list and find the current power percentage in supported list
10829 memset(buf, 0, sizeof(buf));
10830 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10831 support = strtok(buf, ",");
10832 while(true)
10833 {
10834 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 +080010835 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010836 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010837 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010838 }
10839 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10840 if (tmp == current_tx) {
10841 *txpwr_pcntg = strtol(support, NULL, 10);
10842 break;
10843 }
10844 support = strtok(NULL, ",");
10845 }
10846 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010847 return RETURN_OK;
10848}
10849
10850INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10851{
developer58599c22022-09-13 16:40:34 +080010852 // TODO precac feature.
10853 struct params params = {0};
10854 char config_file[128] = {0};
10855
10856 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10857
10858 params.name = "enable_background_radar";
10859 params.value = enable?"1":"0";
10860 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10861 wifi_hostapdWrite(config_file, &params, 1);
10862 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10863
10864 /* TODO precac feature */
10865
10866 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10867 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010868}
10869
10870INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10871{
developer58599c22022-09-13 16:40:34 +080010872 char config_file[128] = {0};
10873 char buf[64] = {0};
10874
10875 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10876 if (NULL == enable || NULL == precac)
10877 return RETURN_ERR;
10878
10879 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10880 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10881 if (strncmp(enable, "1", 1) == 0)
10882 *enable = true;
10883 else
10884 *enable = false;
10885
10886 /* TODO precac feature */
10887
10888 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10889 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010890}
10891
10892INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10893{
developer58599c22022-09-13 16:40:34 +080010894 *supported = TRUE;
10895 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010896}
10897
developer3e6b1692022-09-30 18:04:05 +080010898INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10899{
10900 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10901 struct params params = {0};
10902 char config_file[64] = {0};
10903 char buf[64] = {0};
10904 unsigned int set_mu_type = 0;
10905 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10906
10907 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10908 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10909
10910 if (strlen(buf) > 0)
10911 set_mu_type = strtol(buf, NULL, 10);
10912
10913 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10914 set_mu_type &= ~0x05; // unset bit 0, 2
10915 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10916 set_mu_type |= 0x01;
10917 set_mu_type &= ~0x04;
10918 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10919 set_mu_type &= ~0x01;
10920 set_mu_type |= 0x04;
10921 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10922 set_mu_type |= 0x05; // set bit 0, 2
10923 }
10924
10925 params.name = "hemu_onoff";
10926 sprintf(buf, "%u", set_mu_type);
10927 params.value = buf;
10928 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10929 wifi_hostapdWrite(config_file, &params, 1);
10930 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10931
10932 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10933 return RETURN_OK;
10934}
10935
10936INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10937{
10938 struct params params={0};
10939 char config_file[64] = {0};
10940 char buf[64] = {0};
10941 unsigned int get_mu_type = 0;
10942
10943 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10944
10945 if (mu_type == NULL)
10946 return RETURN_ERR;
10947
10948 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10949 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10950 get_mu_type = strtol(buf, NULL, 10);
10951
10952 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10953 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10954 else if (get_mu_type & 0x04)
10955 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10956 else if (get_mu_type & 0x01)
10957 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10958 else
10959 *mu_type = WIFI_DL_MU_TYPE_NONE;
10960
10961 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10962 return RETURN_OK;
10963}
10964
10965INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10966{
10967 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10968 struct params params={0};
10969 char config_file[64] = {0};
10970 char buf[64] = {0};
10971 unsigned int set_mu_type = 0;
10972 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10973
10974 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10975 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10976
10977 if (strlen(buf) > 0)
10978 set_mu_type = strtol(buf, NULL, 10);
10979
10980 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10981 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10982 set_mu_type &= ~0x0a;
10983 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10984 set_mu_type |= 0x02;
10985 set_mu_type &= ~0x08;
10986 }
10987
10988 params.name = "hemu_onoff";
10989 sprintf(buf, "%u", set_mu_type);
10990 params.value = buf;
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_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11000{
11001 struct params params={0};
11002 char config_file[64] = {0};
11003 char buf[64] = {0};
11004 unsigned int get_mu_type = 0;
11005
11006 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11007
11008 if (mu_type == NULL)
11009 return RETURN_ERR;
11010
11011 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11012 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11013
11014 get_mu_type = strtol(buf, NULL, 10);
11015 if (get_mu_type & 0x02)
11016 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11017 else
11018 *mu_type = WIFI_DL_MU_TYPE_NONE;
11019
11020 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11021 return RETURN_OK;
11022}
11023
11024
developer454b9462022-09-13 15:29:16 +080011025INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11026{
11027 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011028 char buf[256] = {0};
11029 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011030 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011031 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011032 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011033 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011034
11035 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11036
developer254882b2022-09-30 17:12:31 +080011037 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011038 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11039 return RETURN_ERR;
11040 }
developer454b9462022-09-13 15:29:16 +080011041
developer254882b2022-09-30 17:12:31 +080011042 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011043 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011044
developer254882b2022-09-30 17:12:31 +080011045 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11046 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011047 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011048 _syscmd(cmd, buf, sizeof(buf));
11049 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11050 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11051 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011052 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 +080011053 _syscmd(cmd, buf, sizeof(buf));
11054 }
11055 if (band == band_5) {
11056 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11057 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011058 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 +080011059 _syscmd(cmd, buf, sizeof(buf));
11060 }
11061 }
11062 }
11063 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011064
developer254882b2022-09-30 17:12:31 +080011065 if (guard_interval == wifi_guard_interval_400)
11066 strcpy(GI, "0.4");
11067 else if (guard_interval == wifi_guard_interval_800)
11068 strcpy(GI, "0.8");
11069 else if (guard_interval == wifi_guard_interval_1600)
11070 strcpy(GI, "1.6");
11071 else if (guard_interval == wifi_guard_interval_3200)
11072 strcpy(GI, "3.2");
11073 else if (guard_interval == wifi_guard_interval_auto)
11074 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011075 // Record GI for get GI function
11076 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11077 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011078 if (f == NULL)
11079 return RETURN_ERR;
11080 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011081 fclose(f);
11082 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11083 return RETURN_OK;
11084}
11085
11086INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11087{
11088 char buf[32] = {0};
11089 char cmd[64] = {0};
11090
11091 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11092
11093 if (guard_interval == NULL)
11094 return RETURN_ERR;
11095
11096 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11097 _syscmd(cmd, buf, sizeof(buf));
11098
11099 if (strncmp(buf, "0.4", 3) == 0)
11100 *guard_interval = wifi_guard_interval_400;
11101 else if (strncmp(buf, "0.8", 3) == 0)
11102 *guard_interval = wifi_guard_interval_800;
11103 else if (strncmp(buf, "1.6", 3) == 0)
11104 *guard_interval = wifi_guard_interval_1600;
11105 else if (strncmp(buf, "3.2", 3) == 0)
11106 *guard_interval = wifi_guard_interval_3200;
11107 else
11108 *guard_interval = wifi_guard_interval_auto;
11109
11110 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11111 return RETURN_OK;
11112}
11113
developer3cc61d12022-09-13 16:36:05 +080011114INT wifi_setBSSColor(INT radio_index, UCHAR color)
11115{
11116 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11117 struct params params = {0};
11118 char config_file[128] = {0};
11119 char bss_color[4] ={0};
11120
11121 params.name = "he_bss_color";
11122 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11123 params.value = bss_color;
11124 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11125 wifi_hostapdWrite(config_file, &params, 1);
11126 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11127
11128 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11129 return RETURN_OK;
11130}
11131
11132INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11133{
11134 char config_file[128] = {0};
11135 char buf[64] = {0};
11136 char temp_output[128] = {'\0'};
11137
11138 wifi_dbg_printf("\nFunc=%s\n", __func__);
11139 if (NULL == color)
11140 return RETURN_ERR;
11141
11142 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11143 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11144
11145 if(strlen(buf) > 0) {
11146 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11147 } else {
11148 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11149 }
11150
11151 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11152 wifi_dbg_printf("\noutput_string=%s\n", color);
11153
11154 return RETURN_OK;
11155}
11156
developer06a01d92022-09-07 16:32:39 +080011157/* multi-psk support */
11158INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11159{
11160 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011161 char interface_name[16] = {0};
11162
11163 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11164 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011165
developerd946fd62022-12-08 18:03:28 +080011166 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11167 interface_name,
developer06a01d92022-09-07 16:32:39 +080011168 mac[0],
11169 mac[1],
11170 mac[2],
11171 mac[3],
11172 mac[4],
11173 mac[5]
11174 );
11175 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11176 _syscmd(cmd, key->wifi_keyId, 64);
11177
11178
11179 return RETURN_OK;
11180}
11181
11182INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11183{
developerd946fd62022-12-08 18:03:28 +080011184 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011185 FILE *fd = NULL;
11186 char fname[100];
11187 char cmd[128] = {0};
11188 char out[64] = {0};
11189 wifi_key_multi_psk_t * key = NULL;
11190 if(keysNumber < 0)
11191 return RETURN_ERR;
11192
developer431128d2022-12-16 15:30:41 +080011193 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011194 fd = fopen(fname, "w");
11195 if (!fd) {
11196 return RETURN_ERR;
11197 }
11198 key= (wifi_key_multi_psk_t *) keys;
11199 for(int i=0; i<keysNumber; ++i, key++) {
11200 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11201 }
11202 fclose(fd);
11203
11204 //reload file
developerd946fd62022-12-08 18:03:28 +080011205 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11206 return RETURN_ERR;
11207 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011208 _syscmd(cmd, out, 64);
11209 return RETURN_OK;
11210}
11211
11212INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11213{
11214 FILE *fd = NULL;
11215 char fname[100];
11216 char * line = NULL;
11217 char * pos = NULL;
11218 size_t len = 0;
11219 ssize_t read = 0;
11220 INT ret = RETURN_OK;
11221 wifi_key_multi_psk_t *keys_it = NULL;
11222
11223 if (keysNumber < 1) {
11224 return RETURN_ERR;
11225 }
11226
developer431128d2022-12-16 15:30:41 +080011227 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011228 fd = fopen(fname, "r");
11229 if (!fd) {
11230 return RETURN_ERR;
11231 }
11232
11233 if (keys == NULL) {
11234 ret = RETURN_ERR;
11235 goto close;
11236 }
11237
11238 keys_it = keys;
11239 while ((read = getline(&line, &len, fd)) != -1) {
11240 //Strip trailing new line if present
11241 if (read > 0 && line[read-1] == '\n') {
11242 line[read-1] = '\0';
11243 }
11244
11245 if(strcmp(line,"keyid=")) {
11246 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11247 if (!(pos = index(line, ' '))) {
11248 ret = RETURN_ERR;
11249 goto close;
11250 }
11251 pos++;
11252 //Here should be 00:00:00:00:00:00
11253 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11254 printf("Not supported MAC: %s\n", pos);
11255 }
11256 if (!(pos = index(pos, ' '))) {
11257 ret = RETURN_ERR;
11258 goto close;
11259 }
11260 pos++;
11261
11262 //The rest is PSK
11263 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11264 keys_it++;
11265
11266 if(--keysNumber <= 0)
11267 break;
11268 }
11269 }
11270
11271close:
11272 free(line);
11273 fclose(fd);
11274 return ret;
11275}
11276/* end of multi-psk support */
11277
11278INT wifi_setNeighborReports(UINT apIndex,
11279 UINT numNeighborReports,
11280 wifi_NeighborReport_t *neighborReports)
11281{
11282 char cmd[256] = { 0 };
11283 char hex_bssid[13] = { 0 };
11284 char bssid[18] = { 0 };
11285 char nr[256] = { 0 };
11286 char ssid[256];
11287 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011288 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011289 INT ret;
11290
11291 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011292 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
11293 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11294 return RETURN_ERR;
11295 sprintf(cmd, "hostapd_cli show_neighbor -i %s | awk '{print $1 \" \" $2}' | xargs -n2 -r hostapd_cli remove_neighbor -i %s",interface_name,interface_name);
developer06a01d92022-09-07 16:32:39 +080011296 system(cmd);
11297
11298 for(unsigned int i = 0; i < numNeighborReports; i++)
11299 {
11300 memset(ssid, 0, sizeof(ssid));
11301 ret = wifi_getSSIDName(apIndex, ssid);
11302 if (ret != RETURN_OK)
11303 return RETURN_ERR;
11304
11305 memset(hex_ssid, 0, sizeof(hex_ssid));
11306 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11307 sprintf(hex_ssid + k,"%02x", ssid[j]);
11308
11309 snprintf(hex_bssid, sizeof(hex_bssid),
11310 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11311 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11312 snprintf(bssid, sizeof(bssid),
11313 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11314 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11315
11316 snprintf(nr, sizeof(nr),
11317 "%s" // bssid
11318 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11319 "%02hhx" // operclass
11320 "%02hhx" // channel
11321 "%02hhx", // phy_mode
11322 hex_bssid,
11323 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11324 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11325 neighborReports[i].opClass,
11326 neighborReports[i].channel,
11327 neighborReports[i].phyTable);
11328
11329 snprintf(cmd, sizeof(cmd),
11330 "hostapd_cli set_neighbor "
11331 "%s " // bssid
11332 "ssid=%s " // ssid
11333 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011334 "-i %s",
11335 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011336
11337 if (WEXITSTATUS(system(cmd)) != 0)
11338 {
11339 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11340 }
11341 }
11342
11343 return RETURN_OK;
11344}
11345
11346INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11347{
11348 return RETURN_OK;
11349}
11350
11351#ifdef _WIFI_HAL_TEST_
11352int main(int argc,char **argv)
11353{
11354 int index;
11355 INT ret=0;
11356 char buf[1024]="";
11357
11358 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11359 if(argc<3)
11360 {
11361 if(argc==2)
11362 {
11363 if(!strcmp(argv[1], "init"))
11364 return wifi_init();
11365 if(!strcmp(argv[1], "reset"))
11366 return wifi_reset();
11367 if(!strcmp(argv[1], "wifi_getHalVersion"))
11368 {
11369 char buffer[64];
11370 if(wifi_getHalVersion(buffer)==RETURN_OK)
11371 printf("Version: %s\n", buffer);
11372 else
11373 printf("Error in wifi_getHalVersion\n");
11374 return RETURN_OK;
11375 }
11376 }
11377 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11378 exit(-1);
11379 }
11380
11381 index = atoi(argv[2]);
11382 if(strstr(argv[1], "wifi_getApName")!=NULL)
11383 {
11384 wifi_getApName(index,buf);
11385 printf("Ap name is %s \n",buf);
11386 return 0;
11387 }
11388 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11389 {
11390 BOOL b = FALSE;
11391 BOOL *output_bool = &b;
11392 wifi_getRadioAutoChannelEnable(index,output_bool);
11393 printf("Channel enabled = %d \n",b);
11394 return 0;
11395 }
11396 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11397 {
11398 wifi_getApWpaEncryptionMode(index,buf);
11399 printf("encryption enabled = %s\n",buf);
11400 return 0;
11401 }
11402 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11403 {
11404 BOOL b = FALSE;
11405 BOOL *output_bool = &b;
11406 wifi_getApSsidAdvertisementEnable(index,output_bool);
11407 printf("advertisment enabled = %d\n",b);
11408 return 0;
11409 }
11410 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11411 {
11412 if(argc <= 3 )
11413 {
11414 printf("Insufficient arguments \n");
11415 exit(-1);
11416 }
11417
11418 char sta[20] = {'\0'};
11419 ULLONG handle= 0;
11420 strcpy(sta,argv[3]);
11421 mac_address_t st;
11422 mac_addr_aton(st,sta);
11423
11424 wifi_associated_dev_tid_stats_t tid_stats;
11425 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11426 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11427 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);
11428 }
11429
11430 if(strstr(argv[1], "getApEnable")!=NULL) {
11431 BOOL enable;
11432 ret=wifi_getApEnable(index, &enable);
11433 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11434 }
11435 else if(strstr(argv[1], "setApEnable")!=NULL) {
11436 BOOL enable = atoi(argv[3]);
11437 ret=wifi_setApEnable(index, enable);
11438 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11439 }
11440 else if(strstr(argv[1], "getApStatus")!=NULL) {
11441 char status[64];
11442 ret=wifi_getApStatus(index, status);
11443 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11444 }
11445 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11446 {
11447 wifi_getSSIDNameStatus(index,buf);
11448 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11449 return 0;
11450 }
11451 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11452 wifi_ssidTrafficStats2_t stats={0};
11453 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11454 printf("%s %d: returns %d\n", argv[1], index, ret);
11455 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11456 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11457 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11458 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11459 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11460 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11461 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11462 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11463 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11464 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11465 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11466 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11467 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11468 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11469 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11470 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11471 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11472 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11473 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11474 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11475 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11476 }
11477 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11478 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11479 UINT array_size=0;
11480 UINT i=0;
11481 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11482 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11483 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11484 printf(" neighbor %d:\n", i);
11485 printf(" ap_SSID =%s\n", pt->ap_SSID);
11486 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11487 printf(" ap_Mode =%s\n", pt->ap_Mode);
11488 printf(" ap_Channel =%d\n", pt->ap_Channel);
11489 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11490 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11491 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11492 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11493 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11494 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11495 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11496 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11497 printf(" ap_Noise =%d\n", pt->ap_Noise);
11498 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11499 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11500 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11501 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11502 }
11503 if(neighbor_ap_array)
11504 free(neighbor_ap_array); //make sure to free the list
11505 }
11506 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11507 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11508 UINT array_size=0;
11509 UINT i=0;
11510 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11511 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11512 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11513 printf(" associated_dev %d:\n", i);
11514 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11515 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11516 printf(" cli_SNR =%d\n", pt->cli_SNR);
11517 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11518 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11519 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11520 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11521 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11522 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11523 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11524 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11525 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11526 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11527 }
11528 if(associated_dev_array)
11529 free(associated_dev_array); //make sure to free the list
11530 }
11531
11532 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11533 {
11534#define MAX_ARRAY_SIZE 64
11535 int i, array_size;
11536 char *p, *ch_str;
11537 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11538
11539 if(argc != 5)
11540 {
11541 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11542 exit(-1);
11543 }
11544 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11545
11546 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11547 {
11548 strtok_r(ch_str, ",", &p);
11549 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11550 }
11551 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11552 if(!array_size)
11553 array_size=1;//Need to print current channel statistics
11554 for(i=0; i<array_size; i++)
11555 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11556 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11557 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11558 input_output_channelStats_array[i].ch_number,\
11559 input_output_channelStats_array[i].ch_noise,\
11560 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11561 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11562 input_output_channelStats_array[i].ch_utilization_busy,\
11563 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11564 input_output_channelStats_array[i].ch_utilization_total);
11565 }
11566
11567 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11568 {
11569 if(argc <= 3 )
11570 {
11571 printf("Insufficient arguments \n");
11572 exit(-1);
11573 }
11574 char mac_addr[20] = {'\0'};
11575 wifi_device_t output_struct;
11576 int dev_index = atoi(argv[3]);
11577
11578 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11579 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11580 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);
11581 }
11582
11583 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11584 {
11585 if (argc <= 3)
11586 {
11587 printf("Insufficient arguments\n");
11588 exit(-1);
11589 }
11590 char args[256];
11591 wifi_NeighborReport_t *neighborReports;
11592
11593 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11594 if (!neighborReports)
11595 {
11596 printf("Failed to allocate memory");
11597 exit(-1);
11598 }
11599
11600 for (int i = 3; i < argc; ++i)
11601 {
11602 char *val;
11603 int j = 0;
11604 memset(args, 0, sizeof(args));
11605 strncpy(args, argv[i], sizeof(args));
11606 val = strtok(args, ";");
11607 while (val != NULL)
11608 {
11609 if (j == 0)
11610 {
11611 mac_addr_aton(neighborReports[i - 3].bssid, val);
11612 } else if (j == 1)
11613 {
11614 neighborReports[i - 3].info = strtol(val, NULL, 16);
11615 } else if (j == 2)
11616 {
11617 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11618 } else if (j == 3)
11619 {
11620 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11621 } else if (j == 4)
11622 {
11623 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11624 } else {
11625 printf("Insufficient arguments]n\n");
11626 exit(-1);
11627 }
11628 val = strtok(NULL, ";");
11629 j++;
11630 }
11631 }
11632
11633 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11634 if (ret != RETURN_OK)
11635 {
11636 printf("wifi_setNeighborReports ret = %d", ret);
11637 exit(-1);
11638 }
11639 }
11640 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11641 {
11642 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11643 printf("%s.\n", buf);
11644 else
11645 printf("Error returned\n");
11646 }
11647 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11648 {
11649 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11650 printf("%s.\n", buf);
11651 else
11652 printf("Error returned\n");
11653 }
11654 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11655 {
11656 if (argc <= 2)
11657 {
11658 printf("Insufficient arguments\n");
11659 exit(-1);
11660 }
11661 char buf[64]= {'\0'};
11662 wifi_getRadioOperatingChannelBandwidth(index,buf);
11663 printf("Current bandwidth is %s \n",buf);
11664 return 0;
11665 }
11666 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11667 {
11668 if (argc <= 5)
11669 {
11670 printf("Insufficient arguments\n");
11671 exit(-1);
11672 }
11673 UINT channel = atoi(argv[3]);
11674 UINT width = atoi(argv[4]);
11675 UINT beacon = atoi(argv[5]);
11676 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11677 printf("Result = %d", ret);
11678 }
11679
11680 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11681 return 0;
11682}
11683
11684#endif
11685
11686#ifdef WIFI_HAL_VERSION_3
11687
developer1e5aa162022-09-13 16:06:24 +080011688INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11689{
11690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11691 if (bitMap & WIFI_BITRATE_1MBPS)
11692 strcat(BasicRate, "1,");
11693 if (bitMap & WIFI_BITRATE_2MBPS)
11694 strcat(BasicRate, "2,");
11695 if (bitMap & WIFI_BITRATE_5_5MBPS)
11696 strcat(BasicRate, "5.5,");
11697 if (bitMap & WIFI_BITRATE_6MBPS)
11698 strcat(BasicRate, "6,");
11699 if (bitMap & WIFI_BITRATE_9MBPS)
11700 strcat(BasicRate, "9,");
11701 if (bitMap & WIFI_BITRATE_11MBPS)
11702 strcat(BasicRate, "11,");
11703 if (bitMap & WIFI_BITRATE_12MBPS)
11704 strcat(BasicRate, "12,");
11705 if (bitMap & WIFI_BITRATE_18MBPS)
11706 strcat(BasicRate, "18,");
11707 if (bitMap & WIFI_BITRATE_24MBPS)
11708 strcat(BasicRate, "24,");
11709 if (bitMap & WIFI_BITRATE_36MBPS)
11710 strcat(BasicRate, "36,");
11711 if (bitMap & WIFI_BITRATE_48MBPS)
11712 strcat(BasicRate, "48,");
11713 if (bitMap & WIFI_BITRATE_54MBPS)
11714 strcat(BasicRate, "54,");
11715 if (strlen(BasicRate) != 0) // remove last comma
11716 BasicRate[strlen(BasicRate) - 1] = '\0';
11717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11718 return RETURN_OK;
11719}
11720
11721INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11722{
11723 UINT BitMap = 0;
11724 char *rate;
11725
11726 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11727 rate = strtok(BasicRatesList, ",");
11728 while(rate != NULL)
11729 {
11730 if (strcmp(rate, "1") == 0)
11731 BitMap |= WIFI_BITRATE_1MBPS;
11732 else if (strcmp(rate, "2") == 0)
11733 BitMap |= WIFI_BITRATE_2MBPS;
11734 else if (strcmp(rate, "5.5") == 0)
11735 BitMap |= WIFI_BITRATE_5_5MBPS;
11736 else if (strcmp(rate, "6") == 0)
11737 BitMap |= WIFI_BITRATE_6MBPS;
11738 else if (strcmp(rate, "9") == 0)
11739 BitMap |= WIFI_BITRATE_9MBPS;
11740 else if (strcmp(rate, "11") == 0)
11741 BitMap |= WIFI_BITRATE_11MBPS;
11742 else if (strcmp(rate, "12") == 0)
11743 BitMap |= WIFI_BITRATE_12MBPS;
11744 else if (strcmp(rate, "18") == 0)
11745 BitMap |= WIFI_BITRATE_18MBPS;
11746 else if (strcmp(rate, "24") == 0)
11747 BitMap |= WIFI_BITRATE_24MBPS;
11748 else if (strcmp(rate, "36") == 0)
11749 BitMap |= WIFI_BITRATE_36MBPS;
11750 else if (strcmp(rate, "48") == 0)
11751 BitMap |= WIFI_BITRATE_48MBPS;
11752 else if (strcmp(rate, "54") == 0)
11753 BitMap |= WIFI_BITRATE_54MBPS;
11754 rate = strtok(NULL, ",");
11755 }
11756 *basicRateBitMap = BitMap;
11757 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11758 return RETURN_OK;
11759}
11760
11761// 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 +080011762INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11763{
developer1e5aa162022-09-13 16:06:24 +080011764 char buf[128] = {0};
11765 char cmd[128] = {0};
11766 char config_file[64] = {0};
11767 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011768 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011769 wifi_radio_operationParam_t current_param;
11770
11771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11772
11773 multiple_set = TRUE;
11774 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11775 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11776 return RETURN_ERR;
11777 }
11778 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11779 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11780 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11781 return RETURN_ERR;
11782 }
11783 }
developer5884e982022-10-06 10:52:50 +080011784
11785 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11786 bandwidth = 20;
11787 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11788 bandwidth = 40;
11789 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11790 bandwidth = 80;
11791 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11792 bandwidth = 160;
11793 if (operationParam->autoChannelEnabled){
11794 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11795 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11796 return RETURN_ERR;
11797 }
11798 }else{
developer1e5aa162022-09-13 16:06:24 +080011799 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11800 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11801 return RETURN_ERR;
11802 }
11803 }
developer5884e982022-10-06 10:52:50 +080011804
developer1e5aa162022-09-13 16:06:24 +080011805 if (current_param.variant != operationParam->variant) {
11806 // Two different definition bit map, so need to check every bit.
11807 if (operationParam->variant & WIFI_80211_VARIANT_A)
11808 set_mode |= WIFI_MODE_A;
11809 if (operationParam->variant & WIFI_80211_VARIANT_B)
11810 set_mode |= WIFI_MODE_B;
11811 if (operationParam->variant & WIFI_80211_VARIANT_G)
11812 set_mode |= WIFI_MODE_G;
11813 if (operationParam->variant & WIFI_80211_VARIANT_N)
11814 set_mode |= WIFI_MODE_N;
11815 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11816 set_mode |= WIFI_MODE_AC;
11817 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11818 set_mode |= WIFI_MODE_AX;
11819 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11820 memset(buf, 0, sizeof(buf));
11821 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11822 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11823 return RETURN_ERR;
11824 }
11825 }
11826 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11827 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11828 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11829 return RETURN_ERR;
11830 }
11831 }
11832 if (current_param.beaconInterval != operationParam->beaconInterval) {
11833 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11834 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11835 return RETURN_ERR;
11836 }
11837 }
11838 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11839 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11840 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11841 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11842 return RETURN_ERR;
11843 }
11844 }
11845 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11846 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11847 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11848 return RETURN_ERR;
11849 }
11850 }
11851 if (current_param.guardInterval != operationParam->guardInterval) {
11852 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11853 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11854 return RETURN_ERR;
11855 }
11856 }
11857 if (current_param.transmitPower != operationParam->transmitPower) {
11858 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11859 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11860 return RETURN_ERR;
11861 }
11862 }
11863 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11864 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11865 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11866 return RETURN_ERR;
11867 }
11868 }
11869 if (current_param.obssCoex != operationParam->obssCoex) {
11870 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11871 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11872 return RETURN_ERR;
11873 }
11874 }
11875 if (current_param.stbcEnable != operationParam->stbcEnable) {
11876 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11877 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11878 return RETURN_ERR;
11879 }
11880 }
11881 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11882 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11883 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11884 return RETURN_ERR;
11885 }
11886 }
11887
11888 // if enable is true, then restart the radio
11889 wifi_setRadioEnable(index, FALSE);
11890 if (operationParam->enable == TRUE)
11891 wifi_setRadioEnable(index, TRUE);
11892 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11893
developer06a01d92022-09-07 16:32:39 +080011894 return RETURN_OK;
11895}
11896
11897INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11898{
developer1e5aa162022-09-13 16:06:24 +080011899 char band[64] = {0};
11900 char buf[256] = {0};
11901 char config_file[64] = {0};
11902 char cmd[128] = {0};
11903 int ret = RETURN_ERR;
11904 int mode = 0;
11905 ULONG channel = 0;
11906 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011907
11908 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11909 printf("Entering %s index = %d\n", __func__, (int)index);
11910
developer1e5aa162022-09-13 16:06:24 +080011911 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11912 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11913 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011914 {
developer1e5aa162022-09-13 16:06:24 +080011915 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011916 return RETURN_ERR;
11917 }
11918 operationParam->enable = enabled;
11919
11920 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011921 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011922 {
developer1e5aa162022-09-13 16:06:24 +080011923 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011924 return RETURN_ERR;
11925 }
11926
11927 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011928 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011929 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011930 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011931 else if (!strcmp(band, "6GHz"))
11932 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011933 else
11934 {
developer1e5aa162022-09-13 16:06:24 +080011935 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011936 band);
11937 }
11938
developer1e5aa162022-09-13 16:06:24 +080011939 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11940 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11941 operationParam->channel = 0;
11942 operationParam->autoChannelEnabled = TRUE;
11943 } else {
11944 operationParam->channel = strtol(buf, NULL, 10);
11945 operationParam->autoChannelEnabled = FALSE;
11946 }
11947
developer06a01d92022-09-07 16:32:39 +080011948 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011949 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11950 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11951 return RETURN_ERR;
11952 }
developer06a01d92022-09-07 16:32:39 +080011953 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11954 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11955 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011956 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11957 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011958 else
11959 {
developer1e5aa162022-09-13 16:06:24 +080011960 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11961 return false;
developer06a01d92022-09-07 16:32:39 +080011962 }
11963
developer1e5aa162022-09-13 16:06:24 +080011964 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11965 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11966 return RETURN_ERR;
11967 }
11968 // Two different definition bit map, so need to check every bit.
11969 if (mode & WIFI_MODE_A)
11970 operationParam->variant |= WIFI_80211_VARIANT_A;
11971 if (mode & WIFI_MODE_B)
11972 operationParam->variant |= WIFI_80211_VARIANT_B;
11973 if (mode & WIFI_MODE_G)
11974 operationParam->variant |= WIFI_80211_VARIANT_G;
11975 if (mode & WIFI_MODE_N)
11976 operationParam->variant |= WIFI_80211_VARIANT_N;
11977 if (mode & WIFI_MODE_AC)
11978 operationParam->variant |= WIFI_80211_VARIANT_AC;
11979 if (mode & WIFI_MODE_AX)
11980 operationParam->variant |= WIFI_80211_VARIANT_AX;
11981 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11982 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11983 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011984 }
developer1e5aa162022-09-13 16:06:24 +080011985 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11986 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11987 return RETURN_ERR;
11988 }
11989 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11990 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11991 return RETURN_ERR;
11992 }
developer06a01d92022-09-07 16:32:39 +080011993
developer1e5aa162022-09-13 16:06:24 +080011994 memset(buf, 0, sizeof(buf));
11995 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11996 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11997 return RETURN_ERR;
11998 }
11999 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12000
12001 memset(buf, 0, sizeof(buf));
12002 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12003 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12004 return RETURN_ERR;
12005 }
12006 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12007
12008 memset(buf, 0, sizeof(buf));
12009 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12010 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12011
12012 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12013 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12014 return RETURN_ERR;
12015 }
12016 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12017 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12018 return RETURN_ERR;
12019 }
12020
12021 memset(buf, 0, sizeof(buf));
12022 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12023 if (strcmp(buf, "-1") == 0) {
12024 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12025 operationParam->ctsProtection = FALSE;
12026 } else {
12027 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12028 operationParam->ctsProtection = TRUE;
12029 }
12030
12031 memset(buf, 0, sizeof(buf));
12032 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12033 if (strcmp(buf, "0") == 0)
12034 operationParam->obssCoex = FALSE;
12035 else
12036 operationParam->obssCoex = TRUE;
12037
12038 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12039 _syscmd(cmd, buf, sizeof(buf));
12040 if (strlen(buf) != 0)
12041 operationParam->stbcEnable = TRUE;
12042 else
12043 operationParam->stbcEnable = FALSE;
12044
12045 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12046 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12047 return RETURN_ERR;
12048 }
12049
12050 // Below value is hardcoded
12051
12052 operationParam->numSecondaryChannels = 0;
12053 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12054 operationParam->channelSecondary[i] = 0;
12055 }
12056 operationParam->csa_beacon_count = 15;
12057 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012058
12059 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12060 return RETURN_OK;
12061}
12062
12063static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12064{
developerc086fb72022-10-04 10:18:22 +080012065 int max_radio_num = 0;
12066
12067 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012068 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012069 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12070 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012071 }
12072
developerc086fb72022-10-04 10:18:22 +080012073 return (arrayIndex * max_radio_num) + radioIndex;
12074}
developer06a01d92022-09-07 16:32:39 +080012075
developerc086fb72022-10-04 10:18:22 +080012076wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12077 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12078 return WIFI_BITRATE_1MBPS;
12079 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12080 return WIFI_BITRATE_2MBPS;
12081 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12082 return WIFI_BITRATE_5_5MBPS;
12083 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12084 return WIFI_BITRATE_6MBPS;
12085 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12086 return WIFI_BITRATE_9MBPS;
12087 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12088 return WIFI_BITRATE_11MBPS;
12089 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12090 return WIFI_BITRATE_12MBPS;
12091 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12092 return WIFI_BITRATE_18MBPS;
12093 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12094 return WIFI_BITRATE_24MBPS;
12095 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12096 return WIFI_BITRATE_36MBPS;
12097 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12098 return WIFI_BITRATE_48MBPS;
12099 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12100 return WIFI_BITRATE_54MBPS;
12101 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012102}
12103
developer1d57d002022-10-12 18:03:15 +080012104INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12105{
12106 if (beacon == WIFI_BITRATE_1MBPS)
12107 strcpy(beacon_str, "1Mbps");
12108 else if (beacon == WIFI_BITRATE_2MBPS)
12109 strcpy(beacon_str, "2Mbps");
12110 else if (beacon == WIFI_BITRATE_5_5MBPS)
12111 strcpy(beacon_str, "5.5Mbps");
12112 else if (beacon == WIFI_BITRATE_6MBPS)
12113 strcpy(beacon_str, "6Mbps");
12114 else if (beacon == WIFI_BITRATE_9MBPS)
12115 strcpy(beacon_str, "9Mbps");
12116 else if (beacon == WIFI_BITRATE_11MBPS)
12117 strcpy(beacon_str, "11Mbps");
12118 else if (beacon == WIFI_BITRATE_12MBPS)
12119 strcpy(beacon_str, "12Mbps");
12120 else if (beacon == WIFI_BITRATE_18MBPS)
12121 strcpy(beacon_str, "18Mbps");
12122 else if (beacon == WIFI_BITRATE_24MBPS)
12123 strcpy(beacon_str, "24Mbps");
12124 else if (beacon == WIFI_BITRATE_36MBPS)
12125 strcpy(beacon_str, "36Mbps");
12126 else if (beacon == WIFI_BITRATE_48MBPS)
12127 strcpy(beacon_str, "48Mbps");
12128 else if (beacon == WIFI_BITRATE_54MBPS)
12129 strcpy(beacon_str, "54Mbps");
12130 return RETURN_OK;
12131}
12132
developer06a01d92022-09-07 16:32:39 +080012133INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12134{
developerc086fb72022-10-04 10:18:22 +080012135 INT mode = 0;
12136 INT ret = -1;
12137 INT output = 0;
12138 int i = 0;
12139 int vap_index = 0;
12140 BOOL enabled = FALSE;
12141 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012142 wifi_vap_security_t security = {0};
developerc086fb72022-10-04 10:18:22 +080012143 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080012144
12145 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12146 printf("Entering %s index = %d\n", __func__, (int)index);
12147
developer06a01d92022-09-07 16:32:39 +080012148 for (i = 0; i < 5; i++)
12149 {
developerc086fb72022-10-04 10:18:22 +080012150 map->vap_array[i].radio_index = index;
12151
developer06a01d92022-09-07 16:32:39 +080012152 vap_index = array_index_to_vap_index(index, i);
12153 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012154 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012155
developerc086fb72022-10-04 10:18:22 +080012156 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012157
12158 map->vap_array[i].vap_index = vap_index;
12159
12160 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012161 ret = wifi_getApName(vap_index, buf);
12162 if (ret != RETURN_OK) {
12163 printf("%s: wifi_getApName return error\n", __func__);
12164 return RETURN_ERR;
12165 }
12166 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12167
12168 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012169 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012170 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012171 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012172 return RETURN_ERR;
12173 }
12174 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 +080012175
12176 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012177 if (ret != RETURN_OK) {
12178 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012179 return RETURN_ERR;
12180 }
12181 map->vap_array[i].u.bss_info.enabled = enabled;
12182
developerc086fb72022-10-04 10:18:22 +080012183 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12184 if (ret != RETURN_OK) {
12185 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12186 return RETURN_ERR;
12187 }
developer06a01d92022-09-07 16:32:39 +080012188 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012189
12190 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12191 if (ret != RETURN_OK) {
12192 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12193 return RETURN_ERR;
12194 }
12195 map->vap_array[i].u.bss_info.isolation = enabled;
12196
12197 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12198 if (ret != RETURN_OK) {
12199 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12200 return RETURN_ERR;
12201 }
12202 map->vap_array[i].u.bss_info.bssMaxSta = output;
12203
12204 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12205 if (ret != RETURN_OK) {
12206 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12207 return RETURN_ERR;
12208 }
12209 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012210
developerc086fb72022-10-04 10:18:22 +080012211 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12212 if (ret != RETURN_OK) {
12213 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12214 return RETURN_ERR;
12215 }
12216 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012217
developerc086fb72022-10-04 10:18:22 +080012218 ret = wifi_getApSecurity(vap_index, &security);
12219 if (ret != RETURN_OK) {
12220 printf("%s: wifi_getApSecurity return error\n", __func__);
12221 return RETURN_ERR;
12222 }
12223 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012224
developerc086fb72022-10-04 10:18:22 +080012225 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12226 if (ret != RETURN_OK) {
12227 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12228 return RETURN_ERR;
12229 }
12230 if (mode == 0)
12231 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12232 else
12233 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12234 if (mode == 1)
12235 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12236 else if (mode == 2)
12237 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012238
developerc086fb72022-10-04 10:18:22 +080012239 ret = wifi_getApWmmEnable(vap_index, &enabled);
12240 if (ret != RETURN_OK) {
12241 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12242 return RETURN_ERR;
12243 }
12244 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012245
developerc086fb72022-10-04 10:18:22 +080012246 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12247 if (ret != RETURN_OK) {
12248 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012249 return RETURN_ERR;
12250 }
developerc086fb72022-10-04 10:18:22 +080012251 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012252
12253 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012254 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012255 if (ret != RETURN_OK) {
12256 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12257 return RETURN_ERR;
12258 }
12259 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012260
developerc086fb72022-10-04 10:18:22 +080012261 memset(buf, 0, sizeof(buf));
12262 ret = wifi_getBaseBSSID(vap_index, buf);
12263 if (ret != RETURN_OK) {
12264 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12265 return RETURN_ERR;
12266 }
12267 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12268 &map->vap_array[i].u.bss_info.bssid[0],
12269 &map->vap_array[i].u.bss_info.bssid[1],
12270 &map->vap_array[i].u.bss_info.bssid[2],
12271 &map->vap_array[i].u.bss_info.bssid[3],
12272 &map->vap_array[i].u.bss_info.bssid[4],
12273 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012274 // 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]);
12275
12276 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12277 if (ret != RETURN_OK) {
12278 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12279 return RETURN_ERR;
12280 }
12281 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012282
developerc086fb72022-10-04 10:18:22 +080012283 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012284 }
12285 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12286 return RETURN_OK;
12287}
12288
developer431128d2022-12-16 15:30:41 +080012289void checkVapStatus(int apIndex, bool *enable)
12290{
12291 char if_name[16] = {0};
12292 char cmd[128] = {0};
12293 char buf[128] = {0};
12294
12295 *enable = FALSE;
12296 if (GetInterfaceName(apIndex, if_name) != RETURN_OK)
12297 return;
12298
12299 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12300 _syscmd(cmd, buf, sizeof(buf));
12301 if (strlen(buf) > 0)
12302 *enable = TRUE;
12303 return;
12304}
12305
developerd946fd62022-12-08 18:03:28 +080012306static int prepareInterface(UINT apIndex, char *new_interface)
12307{
12308 char cur_interface[16] = {0};
12309 char config_file[128] = {0};
12310 char cmd[128] = {0};
12311 char buf[16] = {0};
12312 int max_radio_num = 0;
12313 int radioIndex = -1;
12314 int phyIndex = -1;
12315
12316 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12317 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12318
12319 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12320 wifi_getMaxRadioNumber(&max_radio_num);
12321 radioIndex = apIndex % max_radio_num;
12322 phyIndex = radio_index_to_phy(radioIndex);
12323 // disable and del old interface, then add new interface
12324 wifi_setApEnable(apIndex, FALSE);
developer431128d2022-12-16 15:30:41 +080012325 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
developerd946fd62022-12-08 18:03:28 +080012326 _syscmd(cmd, buf, sizeof(buf));
12327 }
developer431128d2022-12-16 15:30:41 +080012328 // update the vap status file
12329 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12330 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012331 return RETURN_OK;
12332}
12333
developer06a01d92022-09-07 16:32:39 +080012334INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12335{
developerd946fd62022-12-08 18:03:28 +080012336 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012337 unsigned int i;
12338 wifi_vap_info_t *vap_info = NULL;
12339 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012340 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012341 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012342 char buf[256] = {0};
12343 char cmd[128] = {0};
12344 char config_file[64] = {0};
12345 char bssid[32] = {0};
12346 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012347 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012348
12349 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12350 printf("Entering %s index = %d\n", __func__, (int)index);
12351 for (i = 0; i < map->num_vaps; i++)
12352 {
developer1d57d002022-10-12 18:03:15 +080012353 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012354 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012355
12356 // Check vap status file to enable multiple ap if the system boot.
12357 checkVapStatus(vap_info->vap_index, &enable);
12358 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012359 continue;
developer06a01d92022-09-07 16:32:39 +080012360
developer1d57d002022-10-12 18:03:15 +080012361 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12362
developer431128d2022-12-16 15:30:41 +080012363 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12364 enable = FALSE;
12365
12366 // multi-ap first up need to copy current radio config
12367 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012368 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12369 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012370 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12371 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12372 } else {
12373 // Check whether the interface name is valid or this ap change it.
12374 int apIndex = -1;
12375 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12376 if (apIndex != -1 && apIndex != vap_info->vap_index)
12377 continue;
12378 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012379 }
developer06a01d92022-09-07 16:32:39 +080012380
developer1d57d002022-10-12 18:03:15 +080012381 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012382 params[0].name = "interface";
12383 params[0].value = vap_info->vap_name;
12384 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12385 params[1].name = "bssid";
12386 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012387 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012388 params[2].name = "wpa_psk_file";
12389 params[2].value = psk_file;
12390
12391 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12392 wifi_hostapdWrite(config_file, params, 3);
12393
12394 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12395 _syscmd(cmd, buf, sizeof(buf));
12396
12397 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12398 if (ret != RETURN_OK) {
12399 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12400 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012401 }
developer1d57d002022-10-12 18:03:15 +080012402
12403 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12404 if (ret != RETURN_OK) {
12405 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12406 return RETURN_ERR;
12407 }
12408
12409 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12410 if (ret != RETURN_OK) {
12411 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12412 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012413 }
12414
developer1d57d002022-10-12 18:03:15 +080012415 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12416 if (ret != RETURN_OK) {
12417 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12418 return RETURN_ERR;
12419 }
developer06a01d92022-09-07 16:32:39 +080012420
developer1d57d002022-10-12 18:03:15 +080012421 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12422 if (ret != RETURN_OK) {
12423 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12424 return RETURN_ERR;
12425 }
developer06a01d92022-09-07 16:32:39 +080012426
developer1d57d002022-10-12 18:03:15 +080012427 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12428 if (ret != RETURN_OK) {
12429 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12430 return RETURN_ERR;
12431 }
12432
developer804c64f2022-10-19 13:54:40 +080012433 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012434 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012435 }else {
12436 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012437 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012438 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12439 _syscmd(cmd, buf, sizeof(buf));
12440 }else{
developer1d57d002022-10-12 18:03:15 +080012441 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012442 }
developer1d57d002022-10-12 18:03:15 +080012443 }
12444
12445 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12446 if (ret != RETURN_OK) {
12447 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12448 return RETURN_ERR;
12449 }
12450
12451 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12452 if (ret != RETURN_OK) {
12453 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12454 return RETURN_ERR;
12455 }
12456
12457 memset(buf, 0, sizeof(buf));
12458 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12459 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12460 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12461 if (ret != RETURN_OK) {
12462 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12463 return RETURN_ERR;
12464 }
12465
12466 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12467 if (ret != RETURN_OK) {
12468 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12469 return RETURN_ERR;
12470 }
12471
12472 wifi_setApEnable(vap_info->vap_index, TRUE);
12473 multiple_set = FALSE;
12474
12475 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12476 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12477 if (ret != RETURN_OK) {
12478 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12479 return RETURN_ERR;
12480 }
12481
12482 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12483 if (ret != RETURN_OK) {
12484 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12485 return RETURN_ERR;
12486 }
developer06a01d92022-09-07 16:32:39 +080012487
developer1d57d002022-10-12 18:03:15 +080012488 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012489 }
12490 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12491 return RETURN_OK;
12492}
12493
12494int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12495{
12496 char *token, *next;
12497 const char s[2] = ",";
12498 int count =0;
12499
12500 /* get the first token */
12501 token = strtok_r(pchannels, s, &next);
12502
12503 /* walk through other tokens */
12504 while( token != NULL && count < MAX_CHANNELS) {
12505 chlistptr->channels_list[count++] = atoi(token);
12506 token = strtok_r(NULL, s, &next);
12507 }
12508
12509 return count;
12510}
12511
12512static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12513{
12514 INT status;
12515 wifi_channels_list_t *chlistp;
12516 CHAR output_string[64];
12517 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080012518 wifi_band band;
developer033b37b2022-10-18 11:27:46 +080012519 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080012520
12521 if(rcap == NULL)
12522 {
12523 return RETURN_ERR;
12524 }
12525
12526 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012527 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012528
developer1e5aa162022-09-13 16:06:24 +080012529 if (band == band_2_4)
12530 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12531 else if (band == band_5)
12532 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12533 else if (band == band_6)
12534 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012535
12536 chlistp = &(rcap->channel_list[0]);
12537 memset(pchannels, 0, sizeof(pchannels));
12538
12539 /* possible number of radio channels */
12540 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12541 {
12542 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12543 }
12544 /* Number of channels and list*/
12545 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12546
12547 /* autoChannelSupported */
12548 /* always ON with wifi_getRadioAutoChannelSupported */
12549 rcap->autoChannelSupported = TRUE;
12550
12551 /* DCSSupported */
12552 /* always ON with wifi_getRadioDCSSupported */
12553 rcap->DCSSupported = TRUE;
12554
12555 /* zeroDFSSupported - TBD */
12556 rcap->zeroDFSSupported = FALSE;
12557
12558 /* Supported Country List*/
12559 memset(output_string, 0, sizeof(output_string));
12560 status = wifi_getRadioCountryCode(radioIndex, output_string);
12561 if( status != 0 ) {
12562 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12563 return RETURN_ERR;
12564 } else {
12565 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12566 }
12567 if(!strcmp(output_string,"US")){
12568 rcap->countrySupported[0] = wifi_countrycode_US;
12569 rcap->countrySupported[1] = wifi_countrycode_CA;
12570 } else if (!strcmp(output_string,"CA")) {
12571 rcap->countrySupported[0] = wifi_countrycode_CA;
12572 rcap->countrySupported[1] = wifi_countrycode_US;
12573 } else {
12574 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12575 }
12576
12577 rcap->numcountrySupported = 2;
12578
12579 /* csi */
12580 rcap->csi.maxDevices = 8;
12581 rcap->csi.soudingFrameSupported = TRUE;
12582
developer033b37b2022-10-18 11:27:46 +080012583 phyId = radio_index_to_phy(radioIndex);
12584 snprintf(rcap->ifaceName, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +080012585
12586 /* channelWidth - all supported bandwidths */
12587 int i=0;
12588 rcap->channelWidth[i] = 0;
12589 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12590 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12591 WIFI_CHANNELBANDWIDTH_40MHZ);
12592
12593 }
developer1e5aa162022-09-13 16:06:24 +080012594 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012595 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12596 WIFI_CHANNELBANDWIDTH_40MHZ |
12597 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12598 }
12599
12600
12601 /* mode - all supported variants */
12602 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12603 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012604 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 +080012605 }
12606 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012607 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12608 }
12609 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12610 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012611 }
12612 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12613 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12614
12615 /* supportedBitRate - all supported bitrates */
12616 rcap->supportedBitRate[i] = 0;
12617 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12618 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12619 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12620 }
developer1e5aa162022-09-13 16:06:24 +080012621 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012622 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12623 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12624 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12625 }
12626
12627
12628 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12629 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12630 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12631 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12632 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12633 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12634 rcap->cipherSupported = 0;
12635 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12636 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12637
12638 return RETURN_OK;
12639}
12640
12641INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12642{
developer30423732022-12-01 16:17:49 +080012643 INT status = 0, radioIndex = 0;
12644 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080012645 int iter = 0;
developer30423732022-12-01 16:17:49 +080012646 unsigned int j = 0;
12647 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080012648
12649 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12650
12651 memset(cap, 0, sizeof(wifi_hal_capability_t));
12652
12653 /* version */
12654 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12655 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12656
12657 /* number of radios platform property */
12658 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12659 _syscmd(cmd, output, sizeof(output));
developer804c64f2022-10-19 13:54:40 +080012660 cap->wifi_prop.numRadios = atoi(output) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS: atoi(output) ;
developer06a01d92022-09-07 16:32:39 +080012661
12662 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12663 {
12664 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12665 if (status != 0) {
12666 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12667 return RETURN_ERR;
12668 }
12669
12670 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12671 {
developer804c64f2022-10-19 13:54:40 +080012672 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012673 {
12674 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12675 return RETURN_ERR;
12676 }
12677 iface_info = &cap->wifi_prop.interface_map[iter];
12678 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12679 iface_info->rdk_radio_index = radioIndex;
12680 memset(output, 0, sizeof(output));
12681 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12682 {
12683 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12684 }
12685 // TODO: bridge name
12686 // TODO: vlan id
12687 // TODO: primary
12688 iface_info->index = array_index_to_vap_index(radioIndex, j);
12689 memset(output, 0, sizeof(output));
developer30423732022-12-01 16:17:49 +080012690 if (iface_info->index >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012691 {
12692 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12693 }
12694 iter++;
12695 }
12696 }
12697
12698 cap->BandSteeringSupported = FALSE;
12699 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12700 return RETURN_OK;
12701}
12702
developer9df4e652022-10-11 11:27:38 +080012703INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12704{
12705 struct params h_config={0};
12706 char config_file[64] = {0};
12707
12708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12709
12710 h_config.name = "okc";
12711 h_config.value = okc_enable?"1":"0";
12712
12713 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12714 wifi_hostapdWrite(config_file, &h_config, 1);
12715 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12716
12717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12718 return RETURN_OK;
12719}
12720
12721INT wifi_setSAEMFP(int ap_index, BOOL enable)
12722{
12723 struct params h_config={0};
12724 char config_file[64] = {0};
12725 char buf[128] = {0};
12726
12727 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12728
12729 h_config.name = "sae_require_mfp";
12730 h_config.value = enable?"1":"0";
12731
12732 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12733 wifi_hostapdWrite(config_file, &h_config, 1);
12734 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12735
12736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12737 return RETURN_OK;
12738}
12739
12740INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12741{
12742 struct params h_config={0};
12743 char config_file[64] = {0};
12744 char buf[128] = {0};
12745
12746 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12747
12748 h_config.name = "sae_pwe";
12749 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12750 h_config.value = buf;
12751
12752 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12753 wifi_hostapdWrite(config_file, &h_config, 1);
12754 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12755
12756 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12757 return RETURN_OK;
12758}
12759
12760INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12761{
12762 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12763 struct params h_config={0};
12764 char config_file[64] = {0};
12765
12766 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12767
12768 h_config.name = "wpa_disable_eapol_key_retries";
12769 h_config.value = disable_EAPOL_retries?"1":"0";
12770
12771 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12772 wifi_hostapdWrite(config_file, &h_config, 1);
12773 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12774
12775 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12776 return RETURN_OK;
12777}
12778
developer06a01d92022-09-07 16:32:39 +080012779INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12780{
developer587c1b62022-09-27 15:58:59 +080012781 char buf[128] = {0};
12782 char config_file[128] = {0};
12783 char password[64] = {0};
12784 char mfp[32] = {0};
12785 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012786 BOOL okc_enable = FALSE;
12787 BOOL sae_MFP = FALSE;
12788 BOOL disable_EAPOL_retries = TRUE;
12789 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012790 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012791 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012792
12793 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12794
12795 multiple_set = TRUE;
12796 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12797 if (security->mode == wifi_security_mode_none) {
12798 strcpy(wpa_mode, "None");
12799 } else if (security->mode == wifi_security_mode_wpa_personal)
12800 strcpy(wpa_mode, "WPA-Personal");
12801 else if (security->mode == wifi_security_mode_wpa2_personal)
12802 strcpy(wpa_mode, "WPA2-Personal");
12803 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12804 strcpy(wpa_mode, "WPA-WPA2-Personal");
12805 else if (security->mode == wifi_security_mode_wpa_enterprise)
12806 strcpy(wpa_mode, "WPA-Enterprise");
12807 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12808 strcpy(wpa_mode, "WPA2-Enterprise");
12809 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12810 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012811 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012812 strcpy(wpa_mode, "WPA3-Personal");
developer9df4e652022-10-11 11:27:38 +080012813 okc_enable = TRUE;
12814 sae_MFP = TRUE;
12815 sae_pwe = 2;
12816 disable_EAPOL_retries = FALSE;
12817 } else if (security->mode == wifi_security_mode_wpa3_transition) {
developer4a359672022-10-13 15:30:46 +080012818 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012819 okc_enable = TRUE;
12820 sae_MFP = TRUE;
12821 sae_pwe = 2;
12822 disable_EAPOL_retries = FALSE;
12823 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012824 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012825 sae_MFP = TRUE;
12826 sae_pwe = 2;
12827 disable_EAPOL_retries = FALSE;
12828 }
12829
12830 band = wifi_index_to_band(ap_index);
12831 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12832 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12833 return RETURN_ERR;
12834 }
developer587c1b62022-09-27 15:58:59 +080012835
12836 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012837 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012838 wifi_setSAEMFP(ap_index, sae_MFP);
12839 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012840 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012841
developer9df4e652022-10-11 11:27:38 +080012842 if (security->mode != wifi_security_mode_none) {
12843 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12844 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12845 password[63] = '\0';
12846 wifi_setApSecurityKeyPassphrase(ap_index, password);
12847 }
12848 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12849 params.name = "sae_password";
12850 params.value = security->u.key.key;
12851 wifi_hostapdWrite(config_file, &params, 1);
12852 }
12853 }
developer587c1b62022-09-27 15:58:59 +080012854
12855 if (security->mode != wifi_security_mode_none) {
12856 memset(&params, 0, sizeof(params));
12857 params.name = "wpa_pairwise";
12858 if (security->encr == wifi_encryption_tkip)
12859 params.value = "TKIP";
12860 else if (security->encr == wifi_encryption_aes)
12861 params.value = "CCMP";
12862 else if (security->encr == wifi_encryption_aes_tkip)
12863 params.value = "TKIP CCMP";
12864 wifi_hostapdWrite(config_file, &params, 1);
12865 }
12866
12867 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012868 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012869 else if (security->mfp == wifi_mfp_cfg_optional)
12870 strcpy(mfp, "Optional");
12871 else if (security->mfp == wifi_mfp_cfg_required)
12872 strcpy(mfp, "Required");
12873 wifi_setApSecurityMFPConfig(ap_index, mfp);
12874
12875 memset(&params, 0, sizeof(params));
12876 params.name = "transition_disable";
12877 if (security->wpa3_transition_disable == TRUE)
12878 params.value = "0x01";
12879 else
12880 params.value = "0x00";
12881 wifi_hostapdWrite(config_file, &params, 1);
12882
12883 memset(&params, 0, sizeof(params));
12884 params.name = "wpa_group_rekey";
12885 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12886 params.value = buf;
12887 wifi_hostapdWrite(config_file, &params, 1);
12888
12889 memset(&params, 0, sizeof(params));
12890 params.name = "wpa_strict_rekey";
12891 params.value = security->strict_rekey?"1":"0";
12892 wifi_hostapdWrite(config_file, &params, 1);
12893
12894 memset(&params, 0, sizeof(params));
12895 params.name = "wpa_pairwise_update_count";
12896 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12897 params.value = buf;
12898 wifi_hostapdWrite(config_file, &params, 1);
12899
12900 memset(&params, 0, sizeof(params));
12901 params.name = "disable_pmksa_caching";
12902 params.value = security->disable_pmksa_caching?"1":"0";
12903 wifi_hostapdWrite(config_file, &params, 1);
12904
12905 wifi_setApEnable(ap_index, FALSE);
12906 wifi_setApEnable(ap_index, TRUE);
12907
12908 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12909
developer06a01d92022-09-07 16:32:39 +080012910 return RETURN_OK;
12911}
12912
12913INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12914{
developer9df4e652022-10-11 11:27:38 +080012915 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012916 char config_file[128] = {0};
12917 int disable = 0;
12918 // struct params params = {0};
12919
12920 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12921 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12922 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12923 security->mode = wifi_security_mode_none;
12924 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012925 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012926 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012927 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012928 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012929 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012930 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012931 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012932 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012933 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012934 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012935 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012936 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012937 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012938 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012939 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080012940 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012941 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012942 security->mode = wifi_security_mode_wpa3_enterprise;
12943 }
12944
12945 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12946 if (security->mode == wifi_security_mode_none)
12947 security->encr = wifi_encryption_none;
12948 else {
12949 if (strcmp(buf, "TKIP") == 0)
12950 security->encr = wifi_encryption_tkip;
12951 else if (strcmp(buf, "CCMP") == 0)
12952 security->encr = wifi_encryption_aes;
12953 else
12954 security->encr = wifi_encryption_aes_tkip;
12955 }
12956
developer9df4e652022-10-11 11:27:38 +080012957 if (security->mode != wifi_encryption_none) {
12958 memset(buf, 0, sizeof(buf));
12959 // wpa3 can use one or both configs as password, so we check sae_password first.
12960 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12961 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12962 security->u.key.type = wifi_security_key_type_sae;
12963 } else {
12964 security->u.key.type = wifi_security_key_type_psk;
12965 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12966 }
12967 strncpy(security->u.key.key, buf, sizeof(buf));
12968 security->u.key.key[255] = '\0';
12969 }
12970
developer587c1b62022-09-27 15:58:59 +080012971 memset(buf, 0, sizeof(buf));
12972 wifi_getApSecurityMFPConfig(ap_index, buf);
12973 if (strcmp(buf, "Disabled") == 0)
12974 security->mfp = wifi_mfp_cfg_disabled;
12975 else if (strcmp(buf, "Optional") == 0)
12976 security->mfp = wifi_mfp_cfg_optional;
12977 else if (strcmp(buf, "Required") == 0)
12978 security->mfp = wifi_mfp_cfg_required;
12979
12980 memset(buf, 0, sizeof(buf));
12981 security->wpa3_transition_disable = FALSE;
12982 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12983 disable = strtol(buf, NULL, 16);
12984 if (disable != 0)
12985 security->wpa3_transition_disable = TRUE;
12986
12987 memset(buf, 0, sizeof(buf));
12988 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12989 if (strlen(buf) == 0)
12990 security->rekey_interval = 86400;
12991 else
12992 security->rekey_interval = strtol(buf, NULL, 10);
12993
12994 memset(buf, 0, sizeof(buf));
12995 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12996 if (strlen(buf) == 0)
12997 security->strict_rekey = 1;
12998 else
12999 security->strict_rekey = strtol(buf, NULL, 10);
13000
13001 memset(buf, 0, sizeof(buf));
13002 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13003 if (strlen(buf) == 0)
13004 security->eapol_key_retries = 4;
13005 else
13006 security->eapol_key_retries = strtol(buf, NULL, 10);
13007
13008 memset(buf, 0, sizeof(buf));
13009 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13010 if (strlen(buf) == 0)
13011 security->disable_pmksa_caching = FALSE;
13012 else
13013 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13014
13015 /* TODO
13016 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13017 */
13018 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13019 security->eap_identity_req_timeout = 0;
13020 security->eap_identity_req_retries = 0;
13021 security->eap_req_timeout = 0;
13022 security->eap_req_retries = 0;
13023 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013024 return RETURN_OK;
13025}
13026
13027#endif /* WIFI_HAL_VERSION_3 */
13028
13029#ifdef WIFI_HAL_VERSION_3_PHASE2
13030INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13031{
developerd946fd62022-12-08 18:03:28 +080013032 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013033 char cmd[128] = {0};
13034 char buf[128] = {0};
13035 char *mac_addr = NULL;
13036 BOOL status = FALSE;
13037 size_t len = 0;
13038
13039 if(ap_index > MAX_APS)
13040 return RETURN_ERR;
13041
13042 *output_numDevices = 0;
13043 wifi_getApEnable(ap_index, &status);
13044 if (status == FALSE)
13045 return RETURN_OK;
13046
developerd946fd62022-12-08 18:03:28 +080013047 if (GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13048 return RETURN_ERR;
13049 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013050 _syscmd(cmd, buf, sizeof(buf));
13051
13052 mac_addr = strtok(buf, "\n");
13053 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13054 *output_numDevices = i + 1;
13055 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13056 addr_ptr = output_deviceMacAddressArray[i];
13057 mac_addr_aton(addr_ptr, mac_addr);
13058 mac_addr = strtok(NULL, "\n");
13059 }
13060
13061 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013062}
13063#else
13064INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13065{
developerd946fd62022-12-08 18:03:28 +080013066 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013067 char cmd[128];
13068 BOOL status = false;
13069
13070 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13071 return RETURN_ERR;
13072
13073 output_buf[0] = '\0';
13074
13075 wifi_getApEnable(ap_index,&status);
13076 if (!status)
13077 return RETURN_OK;
13078
developerd946fd62022-12-08 18:03:28 +080013079 if (GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13080 return RETURN_ERR;
13081 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013082 _syscmd(cmd, output_buf, output_buf_size);
13083
13084 return RETURN_OK;
13085}
13086#endif
developer2f513ab2022-09-13 14:26:06 +080013087
13088INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13089{
13090 char output[16]={'\0'};
13091 char config_file[MAX_BUF_SIZE] = {0};
13092
13093 if (!enable)
13094 return RETURN_ERR;
13095
13096 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13097 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13098
13099 if (strlen(output) == 0)
13100 *enable = FALSE;
13101 else if (strncmp(output, "1", 1) == 0)
13102 *enable = TRUE;
13103 else
13104 *enable = FALSE;
13105
13106 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13107 return RETURN_OK;
13108}
developer2d9c30f2022-09-13 15:06:14 +080013109
13110INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13111{
developer804c64f2022-10-19 13:54:40 +080013112 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013113 return RETURN_ERR;
13114 *output_enable=TRUE;
13115 return RETURN_OK;
13116}
developerfd7d2892022-09-13 16:44:53 +080013117
13118INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13119{
13120 char cmd[128] = {0};
13121 char buf[128] = {0};
13122 char line[128] = {0};
13123 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013124 FILE *f = NULL;
13125 int index = 0;
13126 int exp = 0;
13127 int mantissa = 0;
13128 int duration = 0;
13129 int radio_index = 0;
13130 int max_radio_num = 0;
13131 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013132 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13134
13135 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013136
developerfd7d2892022-09-13 16:44:53 +080013137 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013138
13139 phyId = radio_index_to_phy(radio_index);
13140 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013141 _syscmd(cmd, buf, sizeof(buf));
13142 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13143 if (*numSessionReturned > maxNumberSessions)
13144 *numSessionReturned = maxNumberSessions;
13145 else if (*numSessionReturned < 1) {
13146 *numSessionReturned = 0;
13147 return RETURN_OK;
13148 }
13149
developer033b37b2022-10-18 11:27:46 +080013150 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 +080013151 if ((f = popen(cmd, "r")) == NULL) {
13152 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13153 return RETURN_ERR;
13154 }
13155
13156 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013157 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013158 char *tmp = NULL;
13159 strcpy(buf, line);
13160 tmp = strtok(buf, " ");
13161 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13162 tmp = strtok(NULL, " ");
13163 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13164 tmp = strtok(NULL, " ");
13165 if (strstr(tmp, "t")) {
13166 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13167 }
13168 if (strstr(tmp, "a")) {
13169 twtSessions[index].twtParameters.operation.announced = TRUE;
13170 }
13171 tmp = strtok(NULL, " ");
13172 exp = strtol(tmp, NULL, 10);
13173 tmp = strtok(NULL, " ");
13174 mantissa = strtol(tmp, NULL, 10);
13175 tmp = strtok(NULL, " ");
13176 duration = strtol(tmp, NULL, 10);
13177
13178 // only implicit supported
13179 twtSessions[index].twtParameters.operation.implicit = TRUE;
13180 // only individual agreement supported
13181 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13182
13183 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13184 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013185 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013186 // Overflow handling
13187 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13188 } else {
13189 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13190 }
13191 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13192 index++;
13193 }
13194
13195 pclose(f);
13196 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13197 return RETURN_OK;
13198}