blob: 6c462ddbf401a639f8c5d811fd371c3b902f294c [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)
developer67b8ee92022-12-20 10:48:43 +08004957 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
developerd946fd62022-12-08 18:03:28 +08004958 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));
developer67b8ee92022-12-20 10:48:43 +08004974
developerd946fd62022-12-08 18:03:28 +08004975 apIndex_str = strtok(buf, "\n");
4976 while (apIndex_str != NULL) {
4977 apIndex = strtoul(apIndex_str, NULL, 10);
developerd946fd62022-12-08 18:03:28 +08004978 if (enable == TRUE) {
4979 *output_int = apIndex;
4980 return RETURN_OK;
4981 }
4982 apIndex_str = strtok(NULL, "\n");
developer06a01d92022-09-07 16:32:39 +08004983 }
developer67b8ee92022-12-20 10:48:43 +08004984
4985 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
4986 apIndex_str = strstr(inputSsidString, AP_PREFIX);
4987 if (apIndex_str) {
4988 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
4989 return RETURN_OK;
4990 }
developerd946fd62022-12-08 18:03:28 +08004991 *output_int = -1;
4992 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004993}
4994
4995INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4996{
4997 return wifi_getIndexFromName(inputSsidString, output_int);
4998}
4999
5000// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5001INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5002{
5003 char buf[MAX_BUF_SIZE] = {0};
5004 char cmd[MAX_CMD_SIZE] = {0};
5005 char config_file[MAX_BUF_SIZE] = {0};
5006
5007 if(NULL == output_string)
5008 return RETURN_ERR;
5009
5010 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5011 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5012 if((strcmp(buf,"3")==0))
5013 snprintf(output_string, 32, "WPAand11i");
5014 else if((strcmp(buf,"2")==0))
5015 snprintf(output_string, 32, "11i");
5016 else if((strcmp(buf,"1")==0))
5017 snprintf(output_string, 32, "WPA");
5018 else
5019 snprintf(output_string, 32, "None");
5020
5021 return RETURN_OK;
5022}
5023
5024// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5025INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5026{
5027 char config_file[MAX_BUF_SIZE] = {0};
5028 struct params list;
5029
5030 if (NULL == beaconTypeString)
5031 return RETURN_ERR;
5032 list.name = "wpa";
5033 list.value = "0";
5034
5035 if((strcmp(beaconTypeString,"WPAand11i")==0))
5036 list.value="3";
5037 else if((strcmp(beaconTypeString,"11i")==0))
5038 list.value="2";
5039 else if((strcmp(beaconTypeString,"WPA")==0))
5040 list.value="1";
5041
5042 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5043 wifi_hostapdWrite(config_file, &list, 1);
5044 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5045 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5046 return RETURN_OK;
5047}
5048
5049// sets the beacon interval on the hardware for this AP
5050INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5051{
developer5f222492022-09-13 15:21:52 +08005052 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5053 struct params params={'\0'};
5054 char buf[MAX_BUF_SIZE] = {'\0'};
5055 char config_file[MAX_BUF_SIZE] = {'\0'};
5056
5057 params.name = "beacon_int";
5058 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5059 params.value = buf;
5060
5061 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5062 wifi_hostapdWrite(config_file, &params, 1);
5063
5064 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5065 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5066 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005067}
5068
5069INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5070{
developer5b398df2022-11-17 20:39:48 +08005071 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5072 return RETURN_ERR;
5073 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005074}
5075
5076// Get the packet size threshold supported.
5077INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5078{
5079 //save config and apply instantly
5080 if (NULL == output_bool)
5081 return RETURN_ERR;
developer514406b2022-12-05 17:20:21 +08005082 *output_bool = TRUE;
developer06a01d92022-09-07 16:32:39 +08005083 return RETURN_OK;
5084}
5085
5086// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5087INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5088{
developerd946fd62022-12-08 18:03:28 +08005089 char interface_name[16] = {0};
developer514406b2022-12-05 17:20:21 +08005090 char buf[16] = {0};
5091 char config_file[128] = {0};
5092 struct params param = {0};
5093
5094 if (threshold > 65535) {
5095 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5096 return RETURN_ERR;
5097 }
developer06a01d92022-09-07 16:32:39 +08005098
developerd946fd62022-12-08 18:03:28 +08005099 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5100 return RETURN_ERR;
5101 snprintf(config_file, sizeof(config_file), "%s.conf", interface_name);
developer514406b2022-12-05 17:20:21 +08005102 snprintf(buf, sizeof(buf), "%u", threshold);
5103 param.name = "rts_threshold";
5104 param.value = buf;
5105 wifi_hostapdWrite(config_file, &param, 1);
5106 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5107 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005108
5109 return RETURN_OK;
5110}
5111
5112// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5113INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5114{
5115 if (NULL == output_string)
5116 return RETURN_ERR;
5117 snprintf(output_string, 32, "TKIPandAESEncryption");
5118 return RETURN_OK;
5119
5120}
5121
5122// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5123INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5124{
5125 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08005126 char *param_name = NULL;
5127 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005128
5129 if(NULL == output_string)
5130 return RETURN_ERR;
5131
5132 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5133 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5134
5135 if(strcmp(buf,"0")==0)
5136 {
5137 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5138 snprintf(output_string, 32, "None");
5139 return RETURN_OK;
5140 }
5141 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5142 param_name = "rsn_pairwise";
5143 else if((strcmp(buf,"1")==0))
5144 param_name = "wpa_pairwise";
5145 else
5146 return RETURN_ERR;
5147 memset(output_string,'\0',32);
developer06a01d92022-09-07 16:32:39 +08005148 wifi_hostapdRead(config_file,param_name,output_string,32);
developer78a15382022-11-02 10:57:40 +08005149 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5150 param_name = "wpa_pairwise";
5151 memset(output_string, '\0', 32);
5152 wifi_hostapdRead(config_file, param_name, output_string, 32);
5153 }
developer06a01d92022-09-07 16:32:39 +08005154 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5155
5156 if(strcmp(output_string,"TKIP") == 0)
5157 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5158 else if(strcmp(output_string,"CCMP") == 0)
5159 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5160 else if(strcmp(output_string,"TKIP CCMP") == 0)
5161 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5162
5163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5164 return RETURN_OK;
5165}
5166
5167// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5168INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5169{
5170 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5171 struct params params={'\0'};
5172 char output_string[32];
5173 char config_file[MAX_BUF_SIZE] = {0};
5174
5175 memset(output_string,'\0',32);
5176 wifi_getApWpaEncryptionMode(apIndex,output_string);
5177
5178 if(strcmp(encMode, "TKIPEncryption") == 0)
5179 params.value = "TKIP";
5180 else if(strcmp(encMode,"AESEncryption") == 0)
5181 params.value = "CCMP";
5182 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5183 params.value = "TKIP CCMP";
5184
5185 if((strcmp(output_string,"WPAand11i")==0))
5186 {
5187 params.name = "wpa_pairwise";
5188 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5189 wifi_hostapdWrite(config_file, &params, 1);
5190 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5191
developer30423732022-12-01 16:17:49 +08005192 params.name = "rsn_pairwise";
developer06a01d92022-09-07 16:32:39 +08005193 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5194 wifi_hostapdWrite(config_file, &params, 1);
5195 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5196
5197 return RETURN_OK;
5198 }
5199 else if((strcmp(output_string,"11i")==0))
5200 {
5201 params.name = "rsn_pairwise";
5202 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5203 wifi_hostapdWrite(config_file, &params, 1);
5204 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5205 return RETURN_OK;
5206 }
5207 else if((strcmp(output_string,"WPA")==0))
5208 {
5209 params.name = "wpa_pairwise";
5210 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5211 wifi_hostapdWrite(config_file, &params, 1);
5212 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5213 return RETURN_OK;
5214 }
5215
5216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5217 return RETURN_OK;
5218}
5219
5220// deletes internal security varable settings for this ap
5221INT wifi_removeApSecVaribles(INT apIndex)
5222{
5223 //TODO: remove the entry in hostapd config file
developerd946fd62022-12-08 18:03:28 +08005224 //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 +08005225 //_syscmd(cmd, buf, sizeof(buf));
5226
developerd946fd62022-12-08 18:03:28 +08005227 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
developer06a01d92022-09-07 16:32:39 +08005228 //_syscmd(cmd, buf, sizeof(buf));
5229 return RETURN_ERR;
5230}
5231
5232// changes the hardware settings to disable encryption on this ap
5233INT wifi_disableApEncryption(INT apIndex)
5234{
5235 //Apply instantly
5236 return RETURN_ERR;
5237}
5238
5239// set the authorization mode on this ap
5240// mode mapping as: 1: open, 2: shared, 4:auto
5241INT wifi_setApAuthMode(INT apIndex, INT mode)
5242{
developeraf95c502022-09-13 16:18:22 +08005243 struct params params={0};
5244 char config_file[64] = {0};
5245 int ret;
5246
5247 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5248
5249 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5250 params.name = "auth_algs";
5251
5252 if (mode & 1 && mode & 2)
5253 params.value = "3";
5254 else if (mode & 2)
5255 params.value = "2";
5256 else if (mode & 1)
5257 params.value = "1";
5258 else
5259 params.value = "0";
5260
5261 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5262 wifi_hostapdWrite(config_file, &params, 1);
5263 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5264 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5265
5266 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005267}
5268
5269// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5270INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5271{
5272 //save to wifi config, and wait for wifi restart to apply
5273 struct params params={'\0'};
5274 char config_file[MAX_BUF_SIZE] = {0};
5275 int ret;
5276
5277 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5278 if(authMode == NULL)
5279 return RETURN_ERR;
5280
5281 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5282 params.name = "wpa_key_mgmt";
5283
5284 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5285 params.value = "WPA-PSK";
5286 else if(strcmp(authMode,"EAPAuthentication") == 0)
5287 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005288 else if (strcmp(authMode, "SAEAuthentication") == 0)
5289 params.value = "SAE";
5290 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5291 params.value = "WPA-EAP-SUITE-B-192";
developer9df4e652022-10-11 11:27:38 +08005292 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5293 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer06a01d92022-09-07 16:32:39 +08005294 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5295 return RETURN_OK; //This is taken careof in beaconType
5296
5297 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5298 ret=wifi_hostapdWrite(config_file,&params,1);
5299 if(!ret)
5300 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5301 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5302
5303 return ret;
5304}
5305
5306// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5307INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5308{
5309 //save to wifi config, and wait for wifi restart to apply
5310 char BeaconType[50] = {0};
5311 char config_file[MAX_BUF_SIZE] = {0};
5312
5313 *authMode = 0;
5314 wifi_getApBeaconType(apIndex,BeaconType);
5315 printf("%s____%s \n",__FUNCTION__,BeaconType);
5316
5317 if(strcmp(BeaconType,"None") == 0)
5318 strcpy(authMode,"None");
5319 else
5320 {
5321 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5322 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5323 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5324 if(strcmp(authMode,"WPA-PSK") == 0)
5325 strcpy(authMode,"SharedAuthentication");
5326 else if(strcmp(authMode,"WPA-EAP") == 0)
5327 strcpy(authMode,"EAPAuthentication");
5328 }
5329
5330 return RETURN_OK;
5331}
5332
5333// Outputs the number of stations associated per AP
5334INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5335{
developerd946fd62022-12-08 18:03:28 +08005336 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005337 char cmd[128]={0};
5338 char buf[128]={0};
5339 BOOL status = false;
5340
5341 if(apIndex > MAX_APS)
5342 return RETURN_ERR;
5343
5344 wifi_getApEnable(apIndex,&status);
5345 if (!status)
5346 return RETURN_OK;
5347
developerd946fd62022-12-08 18:03:28 +08005348 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
5349 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5350 return RETURN_ERR;
5351 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08005352 _syscmd(cmd, buf, sizeof(buf));
5353 sscanf(buf,"%lu", output_ulong);
5354
5355 return RETURN_OK;
5356}
5357
5358// manually removes any active wi-fi association with the device specified on this ap
5359INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5360{
developerd946fd62022-12-08 18:03:28 +08005361 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005362 char buf[126]={'\0'};
5363
developerd946fd62022-12-08 18:03:28 +08005364 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5365 return RETURN_ERR;
5366 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
developer06a01d92022-09-07 16:32:39 +08005367 system(buf);
5368
5369 return RETURN_OK;
5370}
5371
5372// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5373INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5374{
5375 if(NULL == output_int)
5376 return RETURN_ERR;
developer5b398df2022-11-17 20:39:48 +08005377 int max_radio_num = 0;
5378 wifi_getMaxRadioNumber(&max_radio_num);
5379 *output_int = apIndex%max_radio_num;
developer06a01d92022-09-07 16:32:39 +08005380 return RETURN_OK;
5381}
5382
5383// sets the radio index for the specific ap
5384INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5385{
5386 //set to config only and wait for wifi reset to apply settings
5387 return RETURN_ERR;
5388}
5389
5390// Get the ACL MAC list per AP
5391INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5392{
developerd946fd62022-12-08 18:03:28 +08005393 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005394 char cmd[MAX_CMD_SIZE]={'\0'};
5395 int ret = 0;
5396
developerd946fd62022-12-08 18:03:28 +08005397 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5398 return RETURN_ERR;
5399 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
developer06a01d92022-09-07 16:32:39 +08005400 ret = _syscmd(cmd,macArray,buf_size);
5401 if (ret != 0)
5402 return RETURN_ERR;
5403
5404 return RETURN_OK;
5405}
5406
developere6aafda2022-09-13 14:59:28 +08005407INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5408{
developerd946fd62022-12-08 18:03:28 +08005409 char interface_name[16] = {0};
developere6aafda2022-09-13 14:59:28 +08005410 char cmd[MAX_CMD_SIZE]={'\0'};
5411 int ret = 0;
5412
developerd946fd62022-12-08 18:03:28 +08005413 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5414 return RETURN_ERR;
5415 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
developere6aafda2022-09-13 14:59:28 +08005416 ret = _syscmd(cmd,macArray,buf_size);
5417 if (ret != 0)
5418 return RETURN_ERR;
5419
5420 return RETURN_OK;
5421}
5422
5423
developer06a01d92022-09-07 16:32:39 +08005424// Get the list of stations associated per AP
5425INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5426{
developerd946fd62022-12-08 18:03:28 +08005427 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005428 char cmd[128];
5429
5430 if(apIndex > 3) //Currently supporting apIndex upto 3
5431 return RETURN_ERR;
developerd946fd62022-12-08 18:03:28 +08005432 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5433 return RETURN_ERR;
5434 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5435 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
developer06a01d92022-09-07 16:32:39 +08005436 _syscmd(cmd, macArray, buf_size);
5437
5438 return RETURN_OK;
5439}
5440
5441// adds the mac address to the filter list
5442//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5443INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5444{
5445 char cmd[MAX_CMD_SIZE]={'\0'};
5446 char buf[MAX_BUF_SIZE]={'\0'};
5447
5448#if 0
developerd946fd62022-12-08 18:03:28 +08005449 sprintf(cmd, "hostapd_cli -i %s accept_acl ADD_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005450 if(_syscmd(cmd,buf,sizeof(buf)))
5451 return RETURN_ERR;
5452#endif
5453 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5454 if(_syscmd(cmd,buf,sizeof(buf)))
5455 return RETURN_ERR;
5456
5457 return RETURN_OK;
5458}
5459
5460// deletes the mac address from the filter list
5461//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5462INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5463{
5464 char cmd[MAX_CMD_SIZE]={'\0'};
5465 char buf[MAX_BUF_SIZE]={'\0'};
5466
5467#if 0
developerd946fd62022-12-08 18:03:28 +08005468 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
developer06a01d92022-09-07 16:32:39 +08005469 if(_syscmd(cmd,buf,sizeof(buf)))
5470 return RETURN_ERR;
5471
5472#endif
5473 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5474 if(_syscmd(cmd,buf,sizeof(buf)))
5475 return RETURN_ERR;
5476
5477 return RETURN_OK;
5478}
5479
5480// outputs the number of devices in the filter list
5481INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5482{
developere6aafda2022-09-13 14:59:28 +08005483 char cmd[MAX_BUF_SIZE]={0};
5484 char buf[MAX_CMD_SIZE]={0};
5485
5486 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5487 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005488 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005489
5490 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5491 _syscmd(cmd, buf, sizeof(buf));
5492
5493 *output_uint = atoi(buf);
5494
5495 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5496 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005497}
5498
5499INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5500{
5501 char cmd[128]={'\0'};
5502 char buf[128]={'\0'};
5503
5504 if(strcmp(action,"DENY")==0)
5505 {
5506 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5507 system(buf);
5508 return RETURN_OK;
5509 }
5510
5511 if(strcmp(action,"ALLOW")==0)
5512 {
5513 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5514 system(buf);
5515 return RETURN_OK;
5516 }
5517
5518 return RETURN_ERR;
5519
5520}
5521
5522// enable kick for devices on acl black list
5523INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5524{
5525 char aclArray[512] = {0}, *acl = NULL;
5526 char assocArray[512] = {0}, *asso = NULL;
5527
developere6aafda2022-09-13 14:59:28 +08005528 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005529 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5530
5531 // if there are no devices connected there is nothing to do
5532 if (strlen(assocArray) < 17)
5533 return RETURN_OK;
5534
5535 if (enable == TRUE)
5536 {
5537 //kick off the MAC which is in ACL array (deny list)
5538 acl = strtok(aclArray, "\r\n");
5539 while (acl != NULL) {
5540 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5541 wifi_kickApAssociatedDevice(apIndex, acl);
5542
5543 acl = strtok(NULL, "\r\n");
5544 }
developere6aafda2022-09-13 14:59:28 +08005545 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005546 }
5547 else
5548 {
developere6aafda2022-09-13 14:59:28 +08005549 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005550 }
5551
5552#if 0
5553 //TODO: need to revisit below implementation
5554 char aclArray[512]={0}, *acl=NULL;
5555 char assocArray[512]={0}, *asso=NULL;
5556 char buf[256]={'\0'};
5557 char action[10]={'\0'};
5558 FILE *fr=NULL;
5559 char interface[10]={'\0'};
5560 char config_file[MAX_BUF_SIZE] = {0};
5561
5562 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5563 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5564 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5565 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5566
5567 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5568 system(buf);
5569 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5570 system(buf);
5571 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5572 system(buf);
5573 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5574 system(buf);
5575 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5576 system(buf);
5577
5578 if ( enable == TRUE )
5579 {
5580 int device_count=0;
5581 strcpy(action,"DENY");
5582 //kick off the MAC which is in ACL array (deny list)
5583 acl = strtok (aclArray,",");
5584 while (acl != NULL) {
5585 if(strlen(acl)>=17)
5586 {
5587 apply_rules(apIndex, acl,action,interface);
5588 device_count++;
5589 //Register mac to be blocked ,in syscfg.db persistent storage
5590 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5591 system(buf);
5592 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5593 system(buf);
5594 system("syscfg commit");
5595
5596 wifi_kickApAssociatedDevice(apIndex, acl);
5597 }
5598 acl = strtok (NULL, ",");
5599 }
5600 }
5601 else
5602 {
5603 int device_count=0;
5604 char cmdmac[20]={'\0'};
5605 strcpy(action,"ALLOW");
5606 //kick off the MAC which is not in ACL array (allow list)
5607 acl = strtok (aclArray,",");
5608 while (acl != NULL) {
5609 if(strlen(acl)>=17)
5610 {
5611 apply_rules(apIndex, acl,action,interface);
5612 device_count++;
5613 //Register mac to be Allowed ,in syscfg.db persistent storage
5614 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5615 system(buf);
5616 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5617 system(buf);
5618 sprintf(cmdmac,"%s",acl);
5619 }
5620 acl = strtok (NULL, ",");
5621 }
5622 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5623 system(buf);
5624
5625 //Disconnect the mac which is not in ACL
5626 asso = strtok (assocArray,",");
5627 while (asso != NULL) {
5628 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5629 wifi_kickApAssociatedDevice(apIndex, asso);
5630 asso = strtok (NULL, ",");
5631 }
5632 }
5633#endif
5634 return RETURN_OK;
5635}
5636
5637INT wifi_setPreferPrivateConnection(BOOL enable)
5638{
developer06a01d92022-09-07 16:32:39 +08005639 return RETURN_OK;
5640}
5641
5642// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5643INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5644{
developerd946fd62022-12-08 18:03:28 +08005645 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005646 int items = 1;
5647 struct params list[2];
5648 char buf[MAX_BUF_SIZE] = {0};
5649 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005650 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005651
5652 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005653
developer10adcc12022-09-13 14:39:17 +08005654 if (filterMode == 0) {
5655 sprintf(buf, "%d", 0);
5656 list[0].value = buf;
5657
5658 char cmd[128], rtn[128];
developerd946fd62022-12-08 18:03:28 +08005659 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5660 return RETURN_ERR;
5661 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR", interface_name);
developer10adcc12022-09-13 14:39:17 +08005662 _syscmd(cmd, rtn, sizeof(rtn));
5663 memset(cmd,0,sizeof(cmd));
5664 // Delete deny_mac_file in hostapd configuration
5665 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5666 _syscmd(cmd, rtn, sizeof(rtn));
5667 }
5668 else if (filterMode == 1) {
5669 sprintf(buf, "%d", filterMode);
5670 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005671 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5672 list[1].name = "accept_mac_file";
5673 list[1].value = acl_file;
5674 items = 2;
developer10adcc12022-09-13 14:39:17 +08005675 } else if (filterMode == 2) {
5676 //TODO: deny_mac_file
5677 sprintf(buf, "%d", 0);
5678 list[0].value = buf;
5679 list[1].name = "deny_mac_file";
5680 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5681 list[1].value = deny_file;
5682 items = 2;
5683 } else {
5684 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005685 }
developer10adcc12022-09-13 14:39:17 +08005686
developer06a01d92022-09-07 16:32:39 +08005687 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5688 wifi_hostapdWrite(config_file, list, items);
5689
5690 return RETURN_OK;
5691
5692#if 0
5693 if(apIndex==0 || apIndex==1)
5694 {
5695 //set the filtermode
5696 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5697 system(buf);
5698 system("syscfg commit");
5699
5700 if(filterMode==0)
5701 {
5702 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5703 system(buf);
5704 return RETURN_OK;
5705 }
5706 }
5707 return RETURN_OK;
5708#endif
5709}
5710
5711// 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.
5712INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5713{
5714 return RETURN_ERR;
5715}
5716
5717// gets the vlan ID for this ap from an internal enviornment variable
5718INT wifi_getApVlanID(INT apIndex, INT *output_int)
5719{
developer30423732022-12-01 16:17:49 +08005720 if(apIndex==0)
developer06a01d92022-09-07 16:32:39 +08005721 {
5722 *output_int=100;
5723 return RETURN_OK;
5724 }
5725
5726 return RETURN_ERR;
5727}
5728
5729// sets the vlan ID for this ap to an internal enviornment variable
5730INT wifi_setApVlanID(INT apIndex, INT vlanId)
5731{
5732 //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)
5733 return RETURN_ERR;
5734}
5735
5736// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5737INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5738{
5739 snprintf(bridgeName, 32, "brlan0");
5740 snprintf(IP, 32, "10.0.0.1");
5741 snprintf(subnet, 32, "255.255.255.0");
5742
5743 return RETURN_OK;
5744}
5745
5746//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5747INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5748{
5749 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5750 return RETURN_ERR;
5751}
5752
5753// reset the vlan configuration for this ap
5754INT wifi_resetApVlanCfg(INT apIndex)
5755{
developerf5fef612022-09-20 19:38:26 +08005756 char original_config_file[64] = {0};
5757 char current_config_file[64] = {0};
5758 char buf[64] = {0};
5759 char cmd[64] = {0};
5760 char vlan_file[64] = {0};
5761 char vlan_tagged_interface[16] = {0};
5762 char vlan_bridge[16] = {0};
5763 char vlan_naming[16] = {0};
5764 struct params list[4] = {0};
5765 wifi_band band;
5766
5767 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5768
5769 band = wifi_index_to_band(apIndex);
5770 if (band == band_2_4)
5771 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08005772 else if (band == band_5)
developerf5fef612022-09-20 19:38:26 +08005773 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08005774 else if (band == band_6)
developerf5fef612022-09-20 19:38:26 +08005775 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5776
5777 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5778
5779 if (strlen(vlan_file) == 0)
5780 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005781
developerf5fef612022-09-20 19:38:26 +08005782 // The file should exist or this vap would not work.
5783 if (access(vlan_file, F_OK) != 0) {
5784 sprintf(cmd, "touch %s", vlan_file);
5785 _syscmd(cmd, buf, sizeof(buf));
5786 }
5787 list[0].name = "vlan_file";
5788 list[0].value = vlan_file;
5789
5790 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5791 list[1].name = "vlan_tagged_interface";
5792 list[1].value = vlan_tagged_interface;
5793
5794 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5795 list[2].name = "vlan_bridge";
5796 list[2].value = vlan_bridge;
5797
5798 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5799 list[3].name = "vlan_naming";
5800 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005801
developerf5fef612022-09-20 19:38:26 +08005802 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5803 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005804 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005805 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005806
developerf5fef612022-09-20 19:38:26 +08005807 // restart this ap
5808 wifi_setApEnable(apIndex, FALSE);
5809 wifi_setApEnable(apIndex, TRUE);
5810
5811 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5812
5813 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005814}
5815
5816// 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.
5817INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5818{
5819 return RETURN_ERR;
5820}
5821
5822// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5823INT wifi_startHostApd()
5824{
5825 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5826 system("systemctl start hostapd.service");
5827 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5828 return RETURN_OK;
5829 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5830}
5831
5832// stops hostapd
5833INT wifi_stopHostApd()
5834{
5835 char cmd[128] = {0};
5836 char buf[128] = {0};
5837
5838 sprintf(cmd,"systemctl stop hostapd");
5839 _syscmd(cmd, buf, sizeof(buf));
5840
5841 return RETURN_OK;
5842}
5843
5844// restart hostapd dummy function
5845INT wifi_restartHostApd()
5846{
5847 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5848 system("systemctl restart hostapd-global");
5849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5850
5851 return RETURN_OK;
5852}
5853
5854static int align_hostapd_config(int index)
5855{
5856 ULONG lval;
5857 wifi_getRadioChannel(index%2, &lval);
5858 wifi_setRadioChannel(index%2, lval);
developer30423732022-12-01 16:17:49 +08005859 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005860}
5861
5862// sets the AP enable status variable for the specified ap.
5863INT wifi_setApEnable(INT apIndex, BOOL enable)
5864{
developerd946fd62022-12-08 18:03:28 +08005865 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005866 char config_file[MAX_BUF_SIZE] = {0};
5867 char cmd[MAX_CMD_SIZE] = {0};
5868 char buf[MAX_BUF_SIZE] = {0};
5869 BOOL status;
developer033b37b2022-10-18 11:27:46 +08005870 int max_radio_num = 0;
5871 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08005872
5873 wifi_getApEnable(apIndex,&status);
developer033b37b2022-10-18 11:27:46 +08005874
5875 wifi_getMaxRadioNumber(&max_radio_num);
developer06a01d92022-09-07 16:32:39 +08005876 if (enable == status)
5877 return RETURN_OK;
5878
developerd946fd62022-12-08 18:03:28 +08005879 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5880 return RETURN_ERR;
5881
developer06a01d92022-09-07 16:32:39 +08005882 if (enable == TRUE) {
developer033b37b2022-10-18 11:27:46 +08005883 int radioIndex = apIndex % max_radio_num;
5884 phyId = radio_index_to_phy(radioIndex);
developer06a01d92022-09-07 16:32:39 +08005885 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5886 //Hostapd will bring up this interface
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));
developer033b37b2022-10-18 11:27:46 +08005889 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
developer06a01d92022-09-07 16:32:39 +08005890 _syscmd(cmd, buf, sizeof(buf));
5891 }
5892 else {
developerd946fd62022-12-08 18:03:28 +08005893 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08005894 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +08005895 sprintf(cmd, "ip link set %s down", interface_name);
developer06a01d92022-09-07 16:32:39 +08005896 _syscmd(cmd, buf, sizeof(buf));
5897 }
developer431128d2022-12-16 15:30:41 +08005898 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
developerd946fd62022-12-08 18:03:28 +08005899 interface_name, interface_name, enable, VAP_STATUS_FILE);
developer06a01d92022-09-07 16:32:39 +08005900 _syscmd(cmd, buf, sizeof(buf));
5901 //Wait for wifi up/down to apply
5902 return RETURN_OK;
5903}
5904
5905// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5906INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5907{
developerd946fd62022-12-08 18:03:28 +08005908 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08005909 char cmd[MAX_CMD_SIZE] = {'\0'};
5910 char buf[MAX_BUF_SIZE] = {'\0'};
5911
5912 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5913 return RETURN_ERR;
5914
5915 *output_bool = 0;
5916
5917 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5918 {
developerd946fd62022-12-08 18:03:28 +08005919 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
5920 *output_bool = FALSE;
5921 return RETURN_OK;
5922 }
5923 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
developer06a01d92022-09-07 16:32:39 +08005924 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5925 }
5926
5927 return RETURN_OK;
5928}
5929
5930// Outputs the AP "Enabled" "Disabled" status from driver
5931INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5932{
5933 char cmd[128] = {0};
5934 char buf[128] = {0};
5935 BOOL output_bool;
5936
5937 if ( NULL == output_string)
5938 return RETURN_ERR;
5939 wifi_getApEnable(apIndex,&output_bool);
5940
5941 if(output_bool == 1)
5942 snprintf(output_string, 32, "Up");
5943 else
5944 snprintf(output_string, 32, "Disable");
5945
5946 return RETURN_OK;
5947}
5948
5949//Indicates whether or not beacons include the SSID name.
5950// outputs a 1 if SSID on the AP is enabled, else outputs 0
5951INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5952{
5953 //get the running status
5954 char config_file[MAX_BUF_SIZE] = {0};
5955 char buf[16] = {0};
5956
5957 if (!output)
5958 return RETURN_ERR;
5959
5960 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5961 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08005962 // default is enable
5963 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
5964 *output = TRUE;
developer06a01d92022-09-07 16:32:39 +08005965
5966 return RETURN_OK;
5967}
5968
5969// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5970INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5971{
5972 //store the config, apply instantly
5973 char config_file[MAX_BUF_SIZE] = {0};
5974 struct params list;
5975
5976 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5977 list.name = "ignore_broadcast_ssid";
5978 list.value = enable?"0":"1";
5979
5980 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5981 wifi_hostapdWrite(config_file, &list, 1);
5982 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5983 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005984 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005985 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5986
5987 return RETURN_OK;
5988}
5989
5990//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5991INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5992{
5993 //get the running status
5994 if(!output_uint)
5995 return RETURN_ERR;
5996 *output_uint=16;
5997 return RETURN_OK;
5998}
5999
6000INT wifi_setApRetryLimit(INT apIndex, UINT number)
6001{
6002 //apply instantly
6003 return RETURN_ERR;
6004}
6005
6006//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6007INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6008{
6009 if(!output)
6010 return RETURN_ERR;
6011 *output=TRUE;
6012 return RETURN_OK;
6013}
6014
6015//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6016INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6017{
6018 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08006019 char cmd[128] = {0};
6020 char buf[128] = {0};
6021 int max_radio_num = 0, radioIndex = 0;
developer033b37b2022-10-18 11:27:46 +08006022 int phyId = 0;
developer3ab38042022-09-13 14:17:03 +08006023
developer0b246d12022-09-30 15:24:20 +08006024 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006025
developer0b246d12022-09-30 15:24:20 +08006026 wifi_getMaxRadioNumber(&max_radio_num);
6027 radioIndex = apIndex % max_radio_num;
developer033b37b2022-10-18 11:27:46 +08006028 phyId = radio_index_to_phy(radioIndex);
6029 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
developer0b246d12022-09-30 15:24:20 +08006030 _syscmd(cmd,buf, sizeof(buf));
6031
6032 if (strlen(buf) > 0)
6033 *output = true;
6034
6035 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08006036
developer06a01d92022-09-07 16:32:39 +08006037 return RETURN_OK;
6038}
6039
6040//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6041INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6042{
6043 //get the running status from driver
6044 if(!output)
6045 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08006046
6047 char config_file[MAX_BUF_SIZE] = {0};
6048 char buf[16] = {0};
6049
6050 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6051 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +08006052 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
developer3ab38042022-09-13 14:17:03 +08006053 *output = TRUE;
6054 else
6055 *output = FALSE;
6056
developer06a01d92022-09-07 16:32:39 +08006057 return RETURN_OK;
6058}
6059
6060// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6061INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6062{
6063 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006064 char config_file[MAX_BUF_SIZE] = {0};
6065 struct params list;
6066
6067 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6068 list.name = "wmm_enabled";
6069 list.value = enable?"1":"0";
6070
6071 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6072 wifi_hostapdWrite(config_file, &list, 1);
6073 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6074 wifi_reloadAp(apIndex);
6075 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6076
6077 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006078}
6079
6080//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.
6081INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6082{
6083 //get the running status from driver
6084 if(!output)
6085 return RETURN_ERR;
developer97c720c2022-11-04 17:08:12 +08006086
6087 char config_file[128] = {0};
6088 char buf[16] = {0};
6089
6090 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6091 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6092 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6093 *output = TRUE;
6094 else
6095 *output = FALSE;
6096
developer06a01d92022-09-07 16:32:39 +08006097 return RETURN_OK;
6098}
6099
6100// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6101INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6102{
6103 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08006104 char config_file[MAX_BUF_SIZE] = {0};
6105 struct params list;
6106
6107 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6108 list.name = "uapsd_advertisement_enabled";
6109 list.value = enable?"1":"0";
6110
6111 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6112 wifi_hostapdWrite(config_file, &list, 1);
6113 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6114 wifi_reloadAp(apIndex);
6115 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6116
6117 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006118}
6119
developer6daeb3f2022-09-30 13:36:39 +08006120// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08006121INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6122{
developerd946fd62022-12-08 18:03:28 +08006123 char interface_name[16] = {0};
developer6daeb3f2022-09-30 13:36:39 +08006124 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6125 char cmd[128] = {0};
6126 char buf[128] = {0};
6127 char ack_filepath[128] = {0};
6128 uint16_t bitmap = 0;
6129 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6130 FILE *f = NULL;
6131
6132 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6133
6134 // Get current setting
6135 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6136 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6137 _syscmd(cmd, buf, sizeof(buf));
6138 if (strlen(buf) > 0)
6139 bitmap = strtoul(buf, NULL, 10);
6140
6141 bitmap = strtoul(buf, NULL, 10);
6142
6143 if (ackPolicy == TRUE) { // True, unset this class
6144 bitmap &= ~class_map[class];
6145 } else { // False, set this class
6146 bitmap |= class_map[class];
6147 }
6148
6149 f = fopen(ack_filepath, "w");
6150 if (f == NULL) {
6151 fprintf(stderr, "%s: fopen failed\n", __func__);
6152 return RETURN_ERR;
6153 }
6154 fprintf(f, "%hu", bitmap);
6155 fclose(f);
6156
developerd946fd62022-12-08 18:03:28 +08006157 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6158 return RETURN_ERR;
6159 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
developer6daeb3f2022-09-30 13:36:39 +08006160 _syscmd(cmd, buf, sizeof(buf));
6161
6162 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6163 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006164}
6165
6166//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.
6167INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6168{
6169 //get the running status from driver
6170 if(!output_uint)
6171 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006172
6173 char output[16]={'\0'};
6174 char config_file[MAX_BUF_SIZE] = {0};
6175
6176 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6177 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6178 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6179 else {
6180 int device_num = atoi(output);
6181 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6182 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6183 return RETURN_ERR;
6184 }
6185 else {
6186 *output_uint = device_num;
6187 }
6188 }
6189
developer06a01d92022-09-07 16:32:39 +08006190 return RETURN_OK;
6191}
6192
6193INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6194{
6195 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08006196 char str[MAX_BUF_SIZE]={'\0'};
6197 char cmd[MAX_CMD_SIZE]={'\0'};
6198 struct params params;
6199 char config_file[MAX_BUF_SIZE] = {0};
6200
6201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer30423732022-12-01 16:17:49 +08006202 if (number > MAX_ASSOCIATED_STA_NUM) {
developer0947e1a2022-09-13 14:15:25 +08006203 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6204 return RETURN_ERR;
6205 }
6206 sprintf(str, "%d", number);
6207 params.name = "max_num_sta";
6208 params.value = str;
6209
6210 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6211 int ret = wifi_hostapdWrite(config_file, &params, 1);
6212 if (ret) {
6213 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6214 ,__func__, ret);
6215 }
6216
6217 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6218 if (ret) {
6219 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6220 ,__func__, ret);
6221 }
6222 wifi_reloadAp(apIndex);
6223 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6224
6225 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006226}
6227
6228//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.
6229INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6230{
6231 //get the current threshold
6232 if(!output_uint)
6233 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006234 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6235 if (*output_uint == 0)
6236 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006237 return RETURN_OK;
6238}
6239
6240INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6241{
6242 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006243 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6244 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006245 return RETURN_ERR;
6246}
6247
6248//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.
6249INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6250{
6251 if(!output_uint)
6252 return RETURN_ERR;
6253 *output_uint = 3;
6254 return RETURN_OK;
6255}
6256
6257//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6258INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6259{
6260 if(!output_uint)
6261 return RETURN_ERR;
6262 *output_uint = 3;
6263 return RETURN_OK;
6264}
6265
6266//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.
6267INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6268{
6269 if(!output_in_seconds)
6270 return RETURN_ERR;
6271 *output_in_seconds = 0;
6272 return RETURN_OK;
6273}
6274
6275//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
6276INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6277{
6278 if(!output || apIndex>=MAX_APS)
6279 return RETURN_ERR;
6280 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006281 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006282 return RETURN_OK;
6283}
6284
6285//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6286INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6287{
developer587c1b62022-09-27 15:58:59 +08006288 char config_file[128] = {0};
6289 char wpa[16] = {0};
6290 char key_mgmt[64] = {0};
6291 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006292 if (!output)
6293 return RETURN_ERR;
6294
6295 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006296 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006297
developer587c1b62022-09-27 15:58:59 +08006298 strcpy(output, "None");//Copying "None" to output string for default case
6299 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
developer4a359672022-10-13 15:30:46 +08006300 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
developer517a9792022-10-05 19:37:42 +08006301 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006302 snprintf(output, 32, "WPA-Personal");
developer517a9792022-10-05 19:37:42 +08006303 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006304 snprintf(output, 32, "WPA2-Personal");
developer517a9792022-10-05 19:37:42 +08006305 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006306 snprintf(output, 32, "WPA-WPA2-Personal");
6307
6308 } else if (strstr(key_mgmt, "WPA-EAP")) {
developer517a9792022-10-05 19:37:42 +08006309 if (!strcmp(wpa, "1"))
developer587c1b62022-09-27 15:58:59 +08006310 snprintf(output, 32, "WPA-Enterprise");
developer517a9792022-10-05 19:37:42 +08006311 else if (!strcmp(wpa, "2"))
developer587c1b62022-09-27 15:58:59 +08006312 snprintf(output, 32, "WPA2-Enterprise");
developer517a9792022-10-05 19:37:42 +08006313 else if (!strcmp(wpa, "3"))
developer587c1b62022-09-27 15:58:59 +08006314 snprintf(output, 32, "WPA-WPA2-Enterprise");
6315 } else if (strstr(key_mgmt, "SAE")) {
developer4a359672022-10-13 15:30:46 +08006316 if (strstr(key_mgmt, "WPA-PSK") == NULL)
developer587c1b62022-09-27 15:58:59 +08006317 snprintf(output, 32, "WPA3-Personal");
6318 else
developer4a359672022-10-13 15:30:46 +08006319 snprintf(output, 32, "WPA3-Personal-Transition");
developer587c1b62022-09-27 15:58:59 +08006320 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6321 snprintf(output, 32, "WPA3-Enterprise");
6322 }
developer06a01d92022-09-07 16:32:39 +08006323
6324 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6325 return RETURN_OK;
6326#if 0
6327 //TODO: need to revisit below implementation
6328 char securityType[32], authMode[32];
6329 int enterpriseMode=0;
6330
6331 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6332 if(!output)
6333 return RETURN_ERR;
6334
6335 wifi_getApBeaconType(apIndex, securityType);
6336 strcpy(output,"None");//By default, copying "None" to output string
6337 if (strncmp(securityType,"None", strlen("None")) == 0)
6338 return RETURN_OK;
6339
6340 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6341 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6342
6343 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6344 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6345 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6346 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6347 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6348 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6349 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6350
6351 return RETURN_OK;
6352#endif
6353}
6354
6355INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6356{
6357 char securityType[32];
6358 char authMode[32];
6359
6360 //store settings and wait for wifi up to apply
6361 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6362 if(!encMode)
6363 return RETURN_ERR;
6364
developer06a01d92022-09-07 16:32:39 +08006365 if (strcmp(encMode, "None")==0)
6366 {
6367 strcpy(securityType,"None");
6368 strcpy(authMode,"None");
6369 }
6370 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6371 {
6372 strcpy(securityType,"WPAand11i");
6373 strcpy(authMode,"PSKAuthentication");
6374 }
6375 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6376 {
6377 strcpy(securityType,"WPAand11i");
6378 strcpy(authMode,"EAPAuthentication");
6379 }
6380 else if (strcmp(encMode, "WPA-Personal")==0)
6381 {
6382 strcpy(securityType,"WPA");
6383 strcpy(authMode,"PSKAuthentication");
6384 }
6385 else if (strcmp(encMode, "WPA-Enterprise")==0)
6386 {
6387 strcpy(securityType,"WPA");
6388 strcpy(authMode,"EAPAuthentication");
6389 }
6390 else if (strcmp(encMode, "WPA2-Personal")==0)
6391 {
6392 strcpy(securityType,"11i");
6393 strcpy(authMode,"PSKAuthentication");
6394 }
6395 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6396 {
6397 strcpy(securityType,"11i");
6398 strcpy(authMode,"EAPAuthentication");
6399 }
developer587c1b62022-09-27 15:58:59 +08006400 else if (strcmp(encMode, "WPA3-Personal") == 0)
6401 {
6402 strcpy(securityType,"11i");
6403 strcpy(authMode,"SAEAuthentication");
6404 }
developer4a359672022-10-13 15:30:46 +08006405 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
developer9df4e652022-10-11 11:27:38 +08006406 {
6407 strcpy(securityType, "11i");
6408 strcpy(authMode, "PSK-SAEAuthentication");
6409 }
developer587c1b62022-09-27 15:58:59 +08006410 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6411 {
6412 strcpy(securityType,"11i");
6413 strcpy(authMode,"EAP_192-bit_Authentication");
6414 }
developer06a01d92022-09-07 16:32:39 +08006415 else
6416 {
6417 strcpy(securityType,"None");
6418 strcpy(authMode,"None");
6419 }
6420 wifi_setApBeaconType(apIndex, securityType);
6421 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6422 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6423
6424 return RETURN_OK;
6425}
6426
6427
6428//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6429// output_string must be pre-allocated as 64 character string by caller
6430// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6431INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6432{
developer30423732022-12-01 16:17:49 +08006433 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006434 char config_file[MAX_BUF_SIZE] = {0};
6435
6436 if(output_string==NULL)
6437 return RETURN_ERR;
6438
6439 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6440 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6441
6442 if(strcmp(buf,"0")==0)
6443 {
6444 printf("wpa_mode is %s ......... \n",buf);
6445 return RETURN_ERR;
6446 }
6447
6448 wifi_dbg_printf("\nFunc=%s\n",__func__);
6449 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6450 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6451 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6452
6453 return RETURN_OK;
6454}
6455
6456// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6457// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6458INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6459{
6460 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6461 struct params params={'\0'};
6462 int ret;
6463 char config_file[MAX_BUF_SIZE] = {0};
6464
6465 if(NULL == preSharedKey)
6466 return RETURN_ERR;
6467
6468 params.name = "wpa_passphrase";
6469
6470 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6471 {
6472 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6473 return RETURN_ERR;
6474 }
6475 params.value = preSharedKey;
6476 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6477 ret = wifi_hostapdWrite(config_file, &params, 1);
6478 if(!ret)
6479 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6480 return ret;
6481 //TODO: call hostapd_cli for dynamic_config_control
6482}
6483
6484//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6485// outputs the passphrase, maximum 63 characters
6486INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6487{
6488 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6489
6490 wifi_dbg_printf("\nFunc=%s\n",__func__);
6491 if (NULL == output_string)
6492 return RETURN_ERR;
6493
6494 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6495 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6496 if(strcmp(buf,"0")==0)
6497 {
6498 printf("wpa_mode is %s ......... \n",buf);
6499 return RETURN_ERR;
6500 }
6501
6502 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6503 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6504
6505 return RETURN_OK;
6506}
6507
6508// sets the passphrase enviornment variable, max 63 characters
6509INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6510{
6511 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6512 struct params params={'\0'};
6513 char config_file[MAX_BUF_SIZE] = {0};
6514 int ret;
6515
6516 if(NULL == passPhrase)
6517 return RETURN_ERR;
6518
6519 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6520 {
6521 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6522 return RETURN_ERR;
6523 }
6524 params.name = "wpa_passphrase";
6525 params.value = passPhrase;
6526 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6527 ret=wifi_hostapdWrite(config_file,&params,1);
6528 if(!ret)
6529 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6530
6531 return ret;
6532}
6533
6534//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.
6535INT wifi_setApSecurityReset(INT apIndex)
6536{
developer8d583982022-09-20 11:28:22 +08006537 char original_config_file[64] = {0};
6538 char current_config_file[64] = {0};
6539 char buf[64] = {0};
6540 char cmd[64] = {0};
6541 char wpa[4] = {0};
6542 char wpa_psk[64] = {0};
6543 char wpa_passphrase[64] = {0};
6544 char wpa_psk_file[128] = {0};
6545 char wpa_key_mgmt[64] = {0};
6546 char wpa_pairwise[32] = {0};
6547 wifi_band band;
6548 struct params list[6];
6549
6550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6551
6552 band = wifi_index_to_band(apIndex);
6553 if (band == band_2_4)
6554 sprintf(original_config_file, "/etc/hostapd-2G.conf");
developer30423732022-12-01 16:17:49 +08006555 else if (band == band_5)
developer8d583982022-09-20 11:28:22 +08006556 sprintf(original_config_file, "/etc/hostapd-5G.conf");
developer30423732022-12-01 16:17:49 +08006557 else if (band == band_6)
developer8d583982022-09-20 11:28:22 +08006558 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6559 else
6560 return RETURN_ERR;
6561
6562 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6563 list[0].name = "wpa";
6564 list[0].value = wpa;
6565
6566 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6567 list[1].name = "wpa_psk";
6568 list[1].value = wpa_psk;
6569
6570 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6571 list[2].name = "wpa_passphrase";
6572 list[2].value = wpa_passphrase;
6573
6574 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6575
6576 if (strlen(wpa_psk_file) == 0)
6577 strcpy(wpa_psk_file, PSK_FILE);
6578
6579 if (access(wpa_psk_file, F_OK) != 0) {
6580 sprintf(cmd, "touch %s", wpa_psk_file);
6581 _syscmd(cmd, buf, sizeof(buf));
6582 }
6583 list[3].name = "wpa_psk_file";
6584 list[3].value = wpa_psk_file;
6585
6586 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6587 list[4].name = "wpa_key_mgmt";
6588 list[4].value = wpa_key_mgmt;
6589
6590 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6591 list[5].name = "wpa_pairwise";
6592 list[5].value = wpa_pairwise;
6593
6594 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6595 wifi_hostapdWrite(current_config_file, list, 6);
6596
6597 wifi_setApEnable(apIndex, FALSE);
6598 wifi_setApEnable(apIndex, TRUE);
6599
6600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6601 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006602}
6603
6604//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).
6605INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6606{
developer8f2ddd52022-09-13 15:39:24 +08006607 char config_file[64] = {0};
6608 char buf[64] = {0};
6609 char cmd[256] = {0};
6610
6611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6612
developer06a01d92022-09-07 16:32:39 +08006613 if(!IP_output || !Port_output || !RadiusSecret_output)
6614 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006615
developer8f2ddd52022-09-13 15:39:24 +08006616 // Read the first matched config
6617 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6618 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6619 _syscmd(cmd, buf, sizeof(buf));
6620 strncpy(IP_output, buf, 64);
6621
6622 memset(buf, 0, sizeof(buf));
6623 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6624 _syscmd(cmd, buf, sizeof(buf));
6625 *Port_output = atoi(buf);
6626
6627 memset(buf, 0, sizeof(buf));
6628 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6629 _syscmd(cmd, buf, sizeof(buf));
6630 strncpy(RadiusSecret_output, buf, 64);
6631
6632 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006633 return RETURN_OK;
6634}
6635
6636INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6637{
developer8f2ddd52022-09-13 15:39:24 +08006638 char config_file[64] = {0};
6639 char port_str[8] = {0};
6640 char cmd[256] = {0};
6641 char buf[128] = {0};
6642
6643 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6644
6645 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6646
6647 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6648 _syscmd(cmd, buf, sizeof(buf));
6649 memset(cmd, 0, sizeof(cmd));
6650
6651 snprintf(port_str, sizeof(port_str), "%d", port);
6652 if (strlen(buf) == 0)
6653 // Append
6654 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6655 "auth_server_addr=%s\\n"
6656 "auth_server_port=%s\\n"
6657 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6658 else {
6659 // Delete the three lines setting after the "# radius 1" comment
6660 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6661 _syscmd(cmd, buf, sizeof(buf));
6662 memset(cmd, 0, sizeof(cmd));
6663 // Use "# radius 1" comment to find the location to insert the radius setting
6664 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6665 "# radius 1\\n"
6666 "auth_server_addr=%s\\n"
6667 "auth_server_port=%s\\n"
6668 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6669 }
6670 if(_syscmd(cmd, buf, sizeof(buf))) {
6671 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6672 return RETURN_ERR;
6673 }
6674
6675 wifi_reloadAp(apIndex);
6676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6677 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006678}
6679
6680INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6681{
developer8f2ddd52022-09-13 15:39:24 +08006682 char config_file[64] = {0};
6683 char buf[64] = {0};
6684 char cmd[256] = {0};
6685
6686 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6687
developer06a01d92022-09-07 16:32:39 +08006688 if(!IP_output || !Port_output || !RadiusSecret_output)
6689 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006690
6691 // Read the second matched config
6692 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6693 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6694 _syscmd(cmd, buf, sizeof(buf));
6695 strncpy(IP_output, buf, 64);
6696
6697 memset(buf, 0, sizeof(buf));
6698 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6699 _syscmd(cmd, buf, sizeof(buf));
6700 *Port_output = atoi(buf);
6701
6702 memset(buf, 0, sizeof(buf));
6703 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6704 _syscmd(cmd, buf, sizeof(buf));
6705 strncpy(RadiusSecret_output, buf, 64);
6706
6707 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006708 return RETURN_OK;
6709}
6710
6711INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6712{
developer8f2ddd52022-09-13 15:39:24 +08006713 char config_file[64] = {0};
6714 char port_str[8] = {0};
6715 char cmd[256] = {0};
6716 char buf[128] = {0};
6717
6718 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6719
6720 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6721
6722 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6723 _syscmd(cmd, buf, sizeof(buf));
6724 memset(cmd, 0, sizeof(cmd));
6725
6726 snprintf(port_str, sizeof(port_str), "%d", port);
6727 if (strlen(buf) == 0)
6728 // Append
6729 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6730 "auth_server_addr=%s\\n"
6731 "auth_server_port=%s\\n"
6732 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6733 else {
6734 // Delete the three lines setting after the "# radius 2" comment
6735 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6736 _syscmd(cmd, buf, sizeof(buf));
6737 memset(cmd, 0, sizeof(cmd));
6738 // Use "# radius 2" comment to find the location to insert the radius setting
6739 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6740 "# radius 2\\n"
6741 "auth_server_addr=%s\\n"
6742 "auth_server_port=%s\\n"
6743 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6744 }
6745 if(_syscmd(cmd, buf, sizeof(buf))) {
6746 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6747 return RETURN_ERR;
6748 }
6749
6750 wifi_reloadAp(apIndex);
6751 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6752 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006753}
6754
6755//RadiusSettings
6756INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6757{
6758 if(!output)
6759 return RETURN_ERR;
6760
6761 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6762 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6763 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6764 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6765 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6766 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.
6767 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6768 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6769 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6770 //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.
6771
6772 return RETURN_OK;
6773}
6774
6775INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6776{
6777 //store the paramters, and apply instantly
6778 return RETURN_ERR;
6779}
6780
6781//Device.WiFi.AccessPoint.{i}.WPS.Enable
6782//Enables or disables WPS functionality for this access point.
6783// outputs the WPS enable state of this ap in output_bool
6784INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6785{
developerd946fd62022-12-08 18:03:28 +08006786 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006787 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer5b398df2022-11-17 20:39:48 +08006788 if(!output_bool)
developer06a01d92022-09-07 16:32:39 +08006789 return RETURN_ERR;
developerd946fd62022-12-08 18:03:28 +08006790 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6791 return RETURN_ERR;
6792 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08006793 _syscmd(cmd, buf, sizeof(buf));
6794 if(strstr(buf, "configured"))
6795 *output_bool=TRUE;
6796 else
6797 *output_bool=FALSE;
6798
6799 return RETURN_OK;
6800}
6801
6802//Device.WiFi.AccessPoint.{i}.WPS.Enable
6803// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6804INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6805{
6806 char config_file[MAX_BUF_SIZE] = {0};
6807 struct params params;
6808
developer06a01d92022-09-07 16:32:39 +08006809 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6810 //store the paramters, and wait for wifi up to apply
6811 params.name = "wps_state";
6812 params.value = enable ? "2":"0";
6813
6814 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6815 wifi_hostapdWrite(config_file, &params, 1);
6816 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6817 wifi_reloadAp(apIndex);
6818
6819 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6820 return RETURN_OK;
6821}
6822
6823//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
6824INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6825{
6826 if(!output)
6827 return RETURN_ERR;
6828 snprintf(output, 128, "PushButton,PIN");
6829 return RETURN_OK;
6830}
6831
6832//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6833//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.
6834// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6835INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6836{
6837 if(!output)
6838 return RETURN_ERR;
6839 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6840
6841 return RETURN_OK;
6842}
6843
6844//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6845// 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
6846INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6847{
6848 //apply instantly. No setting need to be stored.
6849 char methods[MAX_BUF_SIZE], *token, *next_token;
6850 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6851 struct params params;
6852
developer5b398df2022-11-17 20:39:48 +08006853 if(!methodString)
developer06a01d92022-09-07 16:32:39 +08006854 return RETURN_ERR;
6855 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6856 //store the paramters, and wait for wifi up to apply
6857
6858 snprintf(methods, sizeof(methods), "%s", methodString);
6859 for(token=methods; *token; token=next_token)
6860 {
6861 strtok_r(token, ",", &next_token);
6862 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6863 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6864 else if(*token=='E')
6865 {
6866 if(!strcmp(methods, "Ethernet"))
6867 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6868 else if(!strcmp(methods, "ExternalNFCToken"))
6869 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6870 else
6871 printf("%s: Unknown WpsConfigMethod\n", __func__);
6872 }
6873 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6874 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6875 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6876 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6877 else if(*token=='P' )
6878 {
6879 if(!strcmp(token, "PushButton"))
6880 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6881 else if(!strcmp(token, "PIN"))
6882 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6883 else
6884 printf("%s: Unknown WpsConfigMethod\n", __func__);
6885 }
6886 else
6887 printf("%s: Unknown WpsConfigMethod\n", __func__);
6888 }
6889 params.name = "config_methods";
6890 params.value = config_methods;
6891 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6892 wifi_hostapdWrite(config_file, &params, 1);
6893 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6894 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6895
6896 return RETURN_OK;
6897}
6898
6899// outputs the pin value, ulong_pin must be allocated by the caller
6900INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6901{
6902 char buf[MAX_BUF_SIZE] = {0};
6903 char cmd[MAX_CMD_SIZE] = {0};
6904
developer5b398df2022-11-17 20:39:48 +08006905 if(!output_ulong)
developer06a01d92022-09-07 16:32:39 +08006906 return RETURN_ERR;
6907 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6908 _syscmd(cmd, buf, sizeof(buf));
6909 if(strlen(buf) > 0)
6910 *output_ulong=strtoul(buf, NULL, 10);
6911
6912 return RETURN_OK;
6913}
6914
6915// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6916INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6917{
6918 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6919 char ap_pin[16] = {0};
6920 char buf[MAX_BUF_SIZE] = {0};
6921 char config_file[MAX_BUF_SIZE] = {0};
6922 ULONG prev_pin = 0;
6923 struct params params;
6924
developer06a01d92022-09-07 16:32:39 +08006925 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6926 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6927 params.name = "ap_pin";
6928 params.value = ap_pin;
6929 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6930 wifi_hostapdWrite(config_file, &params, 1);
6931 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6932 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6933
6934 return RETURN_OK;
6935}
6936
6937// Output string is either Not configured or Configured, max 32 characters
6938INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6939{
developerd946fd62022-12-08 18:03:28 +08006940 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006941 char cmd[MAX_CMD_SIZE];
6942 char buf[MAX_BUF_SIZE]={0};
6943
developer5b398df2022-11-17 20:39:48 +08006944 if(!output_string)
developer06a01d92022-09-07 16:32:39 +08006945 return RETURN_ERR;
6946 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6947 snprintf(output_string, 32, "Not configured");
developerd946fd62022-12-08 18:03:28 +08006948 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6949 return RETURN_ERR;
6950 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
developer06a01d92022-09-07 16:32:39 +08006951 _syscmd(cmd, buf, sizeof(buf));
6952
developer348e3d92022-09-13 14:48:41 +08006953 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006954 snprintf(output_string, 32, "Configured");
6955 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6956
6957 return RETURN_OK;
6958}
6959
6960// sets the WPS pin for this AP
6961INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6962{
developerd946fd62022-12-08 18:03:28 +08006963 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006964 char cmd[MAX_CMD_SIZE];
6965 char buf[MAX_BUF_SIZE]={0};
6966 BOOL enable;
6967
developer06a01d92022-09-07 16:32:39 +08006968 wifi_getApEnable(apIndex, &enable);
6969 if (!enable)
6970 return RETURN_ERR;
6971 wifi_getApWpsEnable(apIndex, &enable);
6972 if (!enable)
6973 return RETURN_ERR;
6974
developerd946fd62022-12-08 18:03:28 +08006975 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6976 return RETURN_ERR;
6977 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
developer06a01d92022-09-07 16:32:39 +08006978 _syscmd(cmd, buf, sizeof(buf));
6979 if((strstr(buf, "OK"))!=NULL)
6980 return RETURN_OK;
6981
6982 return RETURN_ERR;
6983}
6984
6985// This function is called when the WPS push button has been pressed for this AP
6986INT wifi_setApWpsButtonPush(INT apIndex)
6987{
6988 char cmd[MAX_CMD_SIZE];
6989 char buf[MAX_BUF_SIZE]={0};
developerd946fd62022-12-08 18:03:28 +08006990 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006991 BOOL enable=FALSE;
6992
developer06a01d92022-09-07 16:32:39 +08006993 wifi_getApEnable(apIndex, &enable);
6994 if (!enable)
6995 return RETURN_ERR;
6996
6997 wifi_getApWpsEnable(apIndex, &enable);
6998 if (!enable)
6999 return RETURN_ERR;
7000
developerd946fd62022-12-08 18:03:28 +08007001 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7002 return RETURN_ERR;
7003
7004 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 +08007005 _syscmd(cmd, buf, sizeof(buf));
7006
7007 if((strstr(buf, "OK"))!=NULL)
7008 return RETURN_OK;
7009 return RETURN_ERR;
7010}
7011
7012// cancels WPS mode for this AP
7013INT wifi_cancelApWPS(INT apIndex)
7014{
developerd946fd62022-12-08 18:03:28 +08007015 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007016 char cmd[MAX_CMD_SIZE];
7017 char buf[MAX_BUF_SIZE]={0};
7018
developerd946fd62022-12-08 18:03:28 +08007019 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7020 return RETURN_ERR;
7021 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
developer06a01d92022-09-07 16:32:39 +08007022 _syscmd(cmd,buf, sizeof(buf));
7023
7024 if((strstr(buf, "OK"))!=NULL)
7025 return RETURN_OK;
7026 return RETURN_ERR;
7027}
7028
7029//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7030//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7031INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7032{
developerd946fd62022-12-08 18:03:28 +08007033 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007034 FILE *f = NULL;
developer06a01d92022-09-07 16:32:39 +08007035 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
developer30423732022-12-01 16:17:49 +08007036 char cmd[256] = {0}, buf[2048] = {0};
7037 char *param = NULL, *value = NULL, *line=NULL;
developer06a01d92022-09-07 16:32:39 +08007038 size_t len = 0;
developer30423732022-12-01 16:17:49 +08007039 ssize_t nread = 0;
developer06a01d92022-09-07 16:32:39 +08007040 wifi_associated_dev_t *dev=NULL;
7041
7042 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7043 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007044 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7045 return RETURN_ERR;
7046 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007047 _syscmd(cmd,buf,sizeof(buf));
7048 *output_array_size = atoi(buf);
7049
7050 if (*output_array_size <= 0)
7051 return RETURN_OK;
7052
7053 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7054 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007055 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
developer06a01d92022-09-07 16:32:39 +08007056 _syscmd(cmd,buf,sizeof(buf));
7057 f = fopen("/tmp/connected_devices.txt", "r");
7058 if (f==NULL)
7059 {
7060 *output_array_size=0;
7061 return RETURN_ERR;
7062 }
developer30423732022-12-01 16:17:49 +08007063 while ((getline(&line, &len, f)) != -1)
developer06a01d92022-09-07 16:32:39 +08007064 {
7065 param = strtok(line,"=");
7066 value = strtok(NULL,"=");
7067
7068 if( strcmp("flags",param) == 0 )
7069 {
7070 value[strlen(value)-1]='\0';
7071 if(strstr (value,"AUTHORIZED") != NULL )
7072 {
7073 dev[auth_temp].cli_AuthenticationState = 1;
7074 dev[auth_temp].cli_Active = 1;
7075 auth_temp++;
7076 read_flag=1;
7077 }
7078 }
7079 if(read_flag==1)
7080 {
7081 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7082 {
7083 value[strlen(value)-1]='\0';
7084 sscanf(value, "%x:%x:%x:%x:%x:%x",
7085 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7086 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7087 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7088 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7089 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7090 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7091 mac_temp++;
7092 read_flag=0;
7093 }
7094 }
7095 }
7096 *output_array_size = auth_temp;
7097 auth_temp=0;
7098 mac_temp=0;
7099 free(line);
7100 fclose(f);
7101 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7102 return RETURN_OK;
7103}
7104
7105#define MACADDRESS_SIZE 6
7106
7107INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7108{
7109 FILE *fp = NULL;
7110 char str[MAX_BUF_SIZE] = {0};
7111 int wificlientindex = 0 ;
7112 int count = 0;
7113 int signalstrength = 0;
7114 int arr[MACADDRESS_SIZE] = {0};
7115 unsigned char mac[MACADDRESS_SIZE] = {0};
7116 UINT wifi_count = 0;
7117 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7118 char pipeCmd[MAX_CMD_SIZE] = {0};
7119
7120 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7121 *output_array_size = 0;
7122 *associated_dev_array = NULL;
7123
7124 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7125 fp = popen(pipeCmd, "r");
7126 if (fp == NULL)
7127 {
7128 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7129 return RETURN_ERR;
7130 }
7131
7132 /* Read the output a line at a time - output it. */
7133 fgets(str, sizeof(str)-1, fp);
7134 wifi_count = (unsigned int) atoi ( str );
7135 *output_array_size = wifi_count;
7136 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7137 pclose(fp);
7138
7139 if(wifi_count == 0)
7140 {
7141 return RETURN_OK;
7142 }
7143 else
7144 {
7145 wifi_associated_dev3_t* temp = NULL;
7146 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7147 if(temp == NULL)
7148 {
7149 printf("Error Statement. Insufficient memory \n");
7150 return RETURN_ERR;
7151 }
7152
7153 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7154 system(pipeCmd);
7155 memset(pipeCmd,0,sizeof(pipeCmd));
7156 if(apIndex == 0)
7157 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7158 else if(apIndex == 1)
7159 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7160 system(pipeCmd);
7161
7162 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7163 if(fp == NULL)
7164 {
7165 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
developerd946fd62022-12-08 18:03:28 +08007166 free(temp);
developer06a01d92022-09-07 16:32:39 +08007167 return RETURN_ERR;
7168 }
7169 fclose(fp);
7170
developer30423732022-12-01 16:17:49 +08007171 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08007172 fp = popen(pipeCmd, "r");
7173 if(fp)
7174 {
7175 for(count =0 ; count < wifi_count; count++)
7176 {
7177 fgets(str, MAX_BUF_SIZE, fp);
7178 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7179 {
7180 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7181 {
7182 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7183
7184 }
7185 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7186 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]);
7187 }
7188 temp[count].cli_AuthenticationState = 1; //TODO
7189 temp[count].cli_Active = 1; //TODO
7190 }
7191 pclose(fp);
7192 }
7193
developer30423732022-12-01 16:17:49 +08007194 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 +08007195 fp = popen(pipeCmd, "r");
7196 if(fp)
7197 {
7198 pclose(fp);
7199 }
7200 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7201 if(fp)
7202 {
7203 for(count =0 ; count < wifi_count ;count++)
7204 {
7205 fgets(str, MAX_BUF_SIZE, fp);
7206 signalstrength = atoi(str);
7207 temp[count].cli_SignalStrength = signalstrength;
7208 temp[count].cli_RSSI = signalstrength;
7209 temp[count].cli_SNR = signalstrength + 95;
7210 }
7211 pclose(fp);
7212 }
7213
7214
7215 if((apIndex == 0) || (apIndex == 4))
7216 {
7217 for(count =0 ; count < wifi_count ;count++)
7218 {
7219 strcpy(temp[count].cli_OperatingStandard,"g");
7220 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7221 }
7222
7223 //BytesSent
developer30423732022-12-01 16:17:49 +08007224 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 +08007225 fp = popen(pipeCmd, "r");
7226 if(fp)
7227 {
7228 pclose(fp);
7229 }
7230 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7231 if(fp)
7232 {
7233 for (count = 0; count < wifi_count; count++)
7234 {
7235 fgets(str, MAX_BUF_SIZE, fp);
7236 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7237 }
7238 pclose(fp);
7239 }
7240
7241 //BytesReceived
developer30423732022-12-01 16:17:49 +08007242 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 +08007243 fp = popen(pipeCmd, "r");
7244 if (fp)
7245 {
7246 pclose(fp);
7247 }
7248 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7249 if (fp)
7250 {
7251 for (count = 0; count < wifi_count; count++)
7252 {
7253 fgets(str, MAX_BUF_SIZE, fp);
7254 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7255 }
7256 pclose(fp);
7257 }
7258
7259 //PacketsSent
developer30423732022-12-01 16:17:49 +08007260 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 +08007261 fp = popen(pipeCmd, "r");
7262 if (fp)
7263 {
7264 pclose(fp);
7265 }
7266
7267 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7268 if (fp)
7269 {
7270 for (count = 0; count < wifi_count; count++)
7271 {
7272 fgets(str, MAX_BUF_SIZE, fp);
7273 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7274 }
7275 pclose(fp);
7276 }
7277
7278 //PacketsReceived
developer30423732022-12-01 16:17:49 +08007279 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 +08007280 fp = popen(pipeCmd, "r");
7281 if (fp)
7282 {
7283 pclose(fp);
7284 }
7285 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7286 if (fp)
7287 {
7288 for (count = 0; count < wifi_count; count++)
7289 {
7290 fgets(str, MAX_BUF_SIZE, fp);
7291 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7292 }
7293 pclose(fp);
7294 }
7295
7296 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007297 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 +08007298 fp = popen(pipeCmd, "r");
7299 if (fp)
7300 {
7301 pclose(fp);
7302 }
7303 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7304 if (fp)
7305 {
7306 for (count = 0; count < wifi_count; count++)
7307 {
7308 fgets(str, MAX_BUF_SIZE, fp);
7309 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7310 }
7311 pclose(fp);
7312 }
7313
7314 //ErrorsSent
developer30423732022-12-01 16:17:49 +08007315 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 +08007316 fp = popen(pipeCmd, "r");
7317 if (fp)
7318 {
7319 pclose(fp);
7320 }
7321 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7322 if (fp)
7323 {
7324 for (count = 0; count < wifi_count; count++)
7325 {
7326 fgets(str, MAX_BUF_SIZE, fp);
7327 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7328 }
7329 pclose(fp);
7330 }
7331
7332 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08007333 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 +08007334 fp = popen(pipeCmd, "r");
7335 if (fp)
7336 {
7337 pclose(fp);
7338 }
7339 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7340 if (fp)
7341 {
7342 for (count = 0; count < wifi_count; count++)
7343 {
7344 fgets(str, MAX_BUF_SIZE, fp);
7345 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7346 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7347 }
7348 pclose(fp);
7349 }
7350
7351 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08007352 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 +08007353 fp = popen(pipeCmd, "r");
7354 if (fp)
7355 {
7356 pclose(fp);
7357 }
7358 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7359 if (fp)
7360 {
7361 for (count = 0; count < wifi_count; count++)
7362 {
7363 fgets(str, MAX_BUF_SIZE, fp);
7364 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7365 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7366 }
7367 pclose(fp);
7368 }
7369
7370 }
7371 else if ((apIndex == 1) || (apIndex == 5))
7372 {
7373 for (count = 0; count < wifi_count; count++)
7374 {
7375 strcpy(temp[count].cli_OperatingStandard, "a");
7376 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7377 temp[count].cli_BytesSent = 0;
7378 temp[count].cli_BytesReceived = 0;
7379 temp[count].cli_LastDataUplinkRate = 0;
7380 temp[count].cli_LastDataDownlinkRate = 0;
7381 temp[count].cli_PacketsSent = 0;
7382 temp[count].cli_PacketsReceived = 0;
7383 temp[count].cli_ErrorsSent = 0;
7384 }
7385 }
7386
7387 for (count = 0; count < wifi_count; count++)
7388 {
7389 temp[count].cli_Retransmissions = 0;
7390 temp[count].cli_DataFramesSentAck = 0;
7391 temp[count].cli_DataFramesSentNoAck = 0;
7392 temp[count].cli_MinRSSI = 0;
7393 temp[count].cli_MaxRSSI = 0;
7394 strncpy(temp[count].cli_InterferenceSources, "", 64);
7395 memset(temp[count].cli_IPAddress, 0, 64);
7396 temp[count].cli_RetransCount = 0;
7397 temp[count].cli_FailedRetransCount = 0;
7398 temp[count].cli_RetryCount = 0;
7399 temp[count].cli_MultipleRetryCount = 0;
7400 }
7401 *associated_dev_array = temp;
7402 }
7403 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7404 return RETURN_OK;
7405}
7406
7407int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7408{
7409 FILE *fp = NULL;
7410 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7411 char cmd[MAX_CMD_SIZE];
7412 int count = 0;
7413
7414 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7415 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7416 fp = popen(cmd,"r");
7417 if(fp == NULL)
7418 {
7419 printf("Failed to run command in Function %s\n",__FUNCTION__);
7420 return 0;
7421 }
7422 if(fgets(path, sizeof(path)-1, fp) != NULL)
7423 {
7424 for(count=0;path[count]!='\n';count++)
7425 status[count]=path[count];
7426 status[count]='\0';
7427 }
7428 strcpy(wifi_status,status);
7429 pclose(fp);
7430 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7431 return RETURN_OK;
7432}
7433
7434/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7435struct hostapd_sta_param {
7436 char key[50];
7437 char value[100];
7438}
7439
7440static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7441 int i = 0;
7442
7443 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7444 if (strncmp(params[i].key,key,50) == 0){
7445 return &params[i].value;
7446 }
7447 i++;
7448 }
7449 return NULL;
7450
7451} */
7452
7453static unsigned int count_occurences(const char *buf, const char *word)
7454{
7455 unsigned int n = 0;
7456 char *ptr = strstr(buf, word);
7457
7458 while (ptr++) {
7459 n++;
7460 ptr = strstr(ptr, word);
7461 }
7462
7463 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7464 return n;
7465}
7466
7467static const char *get_line_from_str_buf(const char *buf, char *line)
7468{
7469 int i;
7470 int n = strlen(buf);
7471
7472 for (i = 0; i < n; i++) {
7473 line[i] = buf[i];
7474 if (buf[i] == '\n') {
7475 line[i] = '\0';
7476 return &buf[i + 1];
7477 }
7478 }
7479
7480 return NULL;
7481}
7482
7483INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7484{
7485 unsigned int assoc_cnt = 0;
7486 char interface_name[50] = {0};
7487 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7488 char cmd[MAX_CMD_SIZE] = {'\0'};
7489 char line[256] = {'\0'};
7490 int i = 0;
7491 int ret = 0;
7492 const char *ptr = NULL;
7493 char *key = NULL;
7494 char *val = NULL;
7495 wifi_associated_dev3_t *temp = NULL;
7496 int rssi;
7497
7498 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7499
7500 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7501 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7502 return RETURN_ERR;
7503 }
7504
7505 // Example filtered output of 'iw dev' command:
7506 // Station 0a:69:72:10:d2:fa (on wifi0)
7507 // signal avg:-67 [-71, -71] dBm
7508 // Station 28:c2:1f:25:5f:99 (on wifi0)
7509 // signal avg:-67 [-71, -70] dBm
7510 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7511 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7512 return RETURN_ERR;
7513 }
7514
7515 ret = _syscmd(cmd, buf, sizeof(buf));
7516 if (ret == RETURN_ERR) {
7517 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7518 return RETURN_ERR;
7519 }
7520
7521 *output_array_size = count_occurences(buf, "Station");
7522 if (*output_array_size == 0) return RETURN_OK;
7523
7524 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7525 if (temp == NULL) {
7526 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7527 return RETURN_ERR;
7528 }
7529 *associated_dev_array = temp;
7530
7531 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7532 ptr = get_line_from_str_buf(buf, line);
7533 i = -1;
7534 while (ptr) {
7535 if (strstr(line, "Station")) {
7536 i++;
7537 key = strtok(line, " ");
7538 val = strtok(NULL, " ");
7539 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7540 &temp[i].cli_MACAddress[0],
7541 &temp[i].cli_MACAddress[1],
7542 &temp[i].cli_MACAddress[2],
7543 &temp[i].cli_MACAddress[3],
7544 &temp[i].cli_MACAddress[4],
7545 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7546 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7547 free(*associated_dev_array);
7548 return RETURN_ERR;
7549 }
7550 }
7551 else if (i < 0) {
7552 ptr = get_line_from_str_buf(ptr, line);
7553 continue; // We didn't detect 'station' entry yet
7554 }
7555 else if (strstr(line, "signal avg")) {
7556 key = strtok(line, ":");
7557 val = strtok(NULL, " ");
7558 if (sscanf(val, "%d", &rssi) <= 0 ) {
7559 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7560 free(*associated_dev_array);
7561 return RETURN_ERR;
7562 }
7563 temp[i].cli_RSSI = rssi;
7564 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7565 }
7566 // Here other fields can be parsed if added to filter of 'iw dev' command
7567
7568 ptr = get_line_from_str_buf(ptr, line);
7569 };
7570
7571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7572
7573 return RETURN_OK;
7574}
7575
7576#if 0
7577//To-do
7578INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7579{
7580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7581
7582 //Using different approach to get required WiFi Parameters from system available commands
7583#if 0
7584 FILE *f;
7585 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7586 char cmd[256], buf[2048];
7587 char *param , *value, *line=NULL;
7588 size_t len = 0;
7589 ssize_t nread;
7590 wifi_associated_dev3_t *dev=NULL;
7591 *associated_dev_array = NULL;
developerd946fd62022-12-08 18:03:28 +08007592 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
developer06a01d92022-09-07 16:32:39 +08007593 _syscmd(cmd,buf,sizeof(buf));
7594 *output_array_size = atoi(buf);
7595
7596 if (*output_array_size <= 0)
7597 return RETURN_OK;
7598
7599 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7600 *associated_dev_array = dev;
developerd946fd62022-12-08 18:03:28 +08007601 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
developer06a01d92022-09-07 16:32:39 +08007602 _syscmd(cmd,buf,sizeof(buf));
7603 f = fopen("/tmp/connected_devices.txt", "r");
7604 if (f==NULL)
7605 {
7606 *output_array_size=0;
7607 return RETURN_ERR;
7608 }
7609 while ((nread = getline(&line, &len, f)) != -1)
7610 {
7611 param = strtok(line,"=");
7612 value = strtok(NULL,"=");
7613
7614 if( strcmp("flags",param) == 0 )
7615 {
7616 value[strlen(value)-1]='\0';
7617 if(strstr (value,"AUTHORIZED") != NULL )
7618 {
7619 dev[auth_temp].cli_AuthenticationState = 1;
7620 dev[auth_temp].cli_Active = 1;
7621 auth_temp++;
7622 read_flag=1;
7623 }
7624 }
7625 if(read_flag==1)
7626 {
7627 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7628 {
7629 value[strlen(value)-1]='\0';
7630 sscanf(value, "%x:%x:%x:%x:%x:%x",
7631 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7632 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7633 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7634 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7635 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7636 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7637
7638 }
7639 else if( strcmp("rx_packets",param) == 0 )
7640 {
7641 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7642 }
7643
7644 else if( strcmp("tx_packets",param) == 0 )
7645 {
7646 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7647 }
7648
7649 else if( strcmp("rx_bytes",param) == 0 )
7650 {
7651 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7652 }
7653
7654 else if( strcmp("tx_bytes",param) == 0 )
7655 {
7656 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7657 mac_temp++;
7658 read_flag=0;
7659 }
7660 }
7661 }
7662
7663 *output_array_size = auth_temp;
7664 auth_temp=0;
7665 mac_temp=0;
7666 free(line);
7667 fclose(f);
7668#endif
7669 char interface_name[MAX_BUF_SIZE] = {0};
7670 char wifi_status[MAX_BUF_SIZE] = {0};
7671 char hostapdconf[MAX_BUF_SIZE] = {0};
7672
7673 wifi_associated_dev3_t *dev_array = NULL;
7674 ULONG wifi_count = 0;
7675
7676 *associated_dev_array = NULL;
7677 *output_array_size = 0;
7678
7679 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7680 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7681 {
7682 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7683
7684 GetInterfaceName(interface_name, hostapdconf);
7685
7686 if(strlen(interface_name) > 1)
7687 {
7688 wifihal_interfacestatus(wifi_status,interface_name);
7689 if(strcmp(wifi_status,"RUNNING") == 0)
7690 {
7691 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7692
7693 *associated_dev_array = dev_array;
7694 *output_array_size = wifi_count;
7695 }
7696 else
7697 {
7698 *associated_dev_array = NULL;
7699 }
7700 }
7701 }
7702
7703 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7704 return RETURN_OK;
7705}
7706#endif
7707
7708/* getIPAddress function */
7709/**
7710* @description Returning IpAddress of the Matched String
7711*
7712* @param
7713* @str Having MacAddress
7714* @ipaddr Having ipaddr
7715* @return The status of the operation
7716* @retval RETURN_OK if successful
7717* @retval RETURN_ERR if any error is detected
7718*
7719*/
7720
7721INT getIPAddress(char *str,char *ipaddr)
7722{
7723 FILE *fp = NULL;
7724 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7725 int LeaseTime = 0,ret = 0;
7726 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7727 {
7728 return RETURN_ERR;
7729 }
7730
7731 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7732 {
7733 /*
7734 Sample:sss
7735 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7736 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7737 */
7738 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
developerd946fd62022-12-08 18:03:28 +08007739 &(LeaseTime),
7740 phyAddr,
7741 ipAddr,
7742 hostName
7743 );
developer06a01d92022-09-07 16:32:39 +08007744 if(ret != 4)
7745 continue;
7746 if(strcmp(str,phyAddr) == 0)
developerd946fd62022-12-08 18:03:28 +08007747 strcpy(ipaddr,ipAddr);
developer06a01d92022-09-07 16:32:39 +08007748 }
developerd946fd62022-12-08 18:03:28 +08007749 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08007750 return RETURN_OK;
7751}
7752
7753/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7754/**
7755* @description Returning Inactive wireless connected clients informations
7756*
7757* @param
7758* @filename Holding private_wifi 2g/5g content files
7759* @associated_dev_array Having inactiv wireless clients informations
7760* @output_array_size Returning Inactive wireless counts
7761* @return The status of the operation
7762* @retval RETURN_OK if successful
7763* @retval RETURN_ERR if any error is detected
7764*
7765*/
7766
7767INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7768{
7769 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7770 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7771 FILE *fp = NULL;
7772 int arr[MACADDRESS_SIZE] = {0};
7773 unsigned char mac[MACADDRESS_SIZE] = {0};
7774 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7775 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7776 fp = popen(buf,"r");
7777 if(fp == NULL)
7778 return RETURN_ERR;
7779 else
7780 {
7781 fgets(path,sizeof(path),fp);
7782 maccount = atoi(path);
7783 }
7784 pclose(fp);
7785 *output_array_size = maccount;
7786 wifi_associated_dev3_t* temp = NULL;
7787 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7788 *associated_dev_array = temp;
7789 if(temp == NULL)
7790 {
7791 printf("Error Statement. Insufficient memory \n");
7792 return RETURN_ERR;
7793 }
7794 memset(buf,0,sizeof(buf));
7795 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7796 fp = popen(buf,"r");
developer30423732022-12-01 16:17:49 +08007797 if (fp == NULL) {
7798 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
7799 return RETURN_ERR;
7800 }
developer06a01d92022-09-07 16:32:39 +08007801 for(count = 0; count < maccount ; count++)
7802 {
7803 fgets(path,sizeof(path),fp);
7804 for(i = 0; path[i]!='\n';i++)
7805 str[i]=path[i];
7806 str[i]='\0';
7807 getIPAddress(str,ipaddr);
7808 memset(buf,0,sizeof(buf));
7809 if(strlen(ipaddr) > 0)
7810 {
7811 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7812 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7813 {
7814 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7815 {
7816 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7817 {
7818 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7819
7820 }
7821 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7822 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]);
7823 }
7824 temp[count].cli_AuthenticationState = 0; //TODO
7825 temp[count].cli_Active = 0; //TODO
7826 temp[count].cli_SignalStrength = 0;
7827 }
7828 else //Active wireless clients info
7829 {
7830 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7831 {
7832 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7833 {
7834 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7835
7836 }
7837 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7838 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]);
7839 }
7840 temp[count].cli_Active = 1;
7841 }
7842 }
7843 memset(ipaddr,0,sizeof(ipaddr));
7844 }
7845 pclose(fp);
7846 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7847 return RETURN_OK;
7848}
7849//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7850//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7851//To get Band Steering Capability
7852INT wifi_getBandSteeringCapability(BOOL *support)
7853{
7854 *support = FALSE;
7855 return RETURN_OK;
7856}
7857
7858
7859//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7860//To get Band Steering enable status
7861INT wifi_getBandSteeringEnable(BOOL *enable)
7862{
7863 *enable = FALSE;
7864 return RETURN_OK;
7865}
7866
7867//To turn on/off Band steering
7868INT wifi_setBandSteeringEnable(BOOL enable)
7869{
7870 return RETURN_OK;
7871}
7872
7873//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7874//To get Band Steering AP group
7875INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7876{
7877 if (NULL == output_ApGroup)
7878 return RETURN_ERR;
7879
7880 strcpy(output_ApGroup, "1,2");
7881 return RETURN_OK;
7882}
7883
7884//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7885//to set and read the band steering BandUtilizationThreshold parameters
7886INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7887{
7888 return RETURN_ERR;
7889}
7890
7891INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7892{
7893 return RETURN_ERR;
7894}
7895
7896//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7897//to set and read the band steering RSSIThreshold parameters
7898INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7899{
7900 return RETURN_ERR;
7901}
7902
7903INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7904{
7905 return RETURN_ERR;
7906}
7907
7908
7909//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7910//to set and read the band steering physical modulation rate threshold parameters
7911INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7912{
7913 //If chip is not support, return -1
7914 return RETURN_ERR;
7915}
7916
7917INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7918{
7919 //If chip is not support, return -1
7920 return RETURN_ERR;
7921}
7922
7923//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7924//to set and read the inactivity time (in seconds) for steering under overload condition
7925INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7926{
7927 return RETURN_ERR;
7928}
7929
7930INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7931{
7932 return RETURN_ERR;
7933}
7934
7935//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7936//to set and read the inactivity time (in seconds) for steering under Idle condition
7937INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7938{
7939 return RETURN_ERR;
7940}
7941
7942INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7943{
7944 return RETURN_ERR;
7945}
7946
7947//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7948//pClientMAC[64]
7949//pSourceSSIDIndex[64]
7950//pDestSSIDIndex[64]
7951//pSteeringReason[256]
7952INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7953{
7954 //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
7955 *pSteeringTime=time(NULL);
7956 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7957 return RETURN_OK;
7958}
7959
7960INT wifi_ifConfigDown(INT apIndex)
7961{
7962 INT status = RETURN_OK;
7963 char cmd[64];
7964
7965 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7966 printf("%s: %s\n", __func__, cmd);
7967 system(cmd);
7968
7969 return status;
7970}
7971
7972INT wifi_ifConfigUp(INT apIndex)
7973{
developerd946fd62022-12-08 18:03:28 +08007974 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08007975 char cmd[128];
7976 char buf[1024];
7977
developerd946fd62022-12-08 18:03:28 +08007978 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7979 return RETURN_ERR;
7980 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
developer06a01d92022-09-07 16:32:39 +08007981 _syscmd(cmd, buf, sizeof(buf));
7982 return 0;
7983}
7984
7985//>> Deprecated. Replace with wifi_applyRadioSettings
7986INT wifi_pushBridgeInfo(INT apIndex)
7987{
developerd946fd62022-12-08 18:03:28 +08007988 char interface_name[16] = {0};
developer30423732022-12-01 16:17:49 +08007989 char ip[32] = {0};
7990 char subnet[32] = {0};
7991 char bridge[32] = {0};
7992 int vlanId = 0;
7993 char cmd[128] = {0};
7994 char buf[1024] = {0};
developer06a01d92022-09-07 16:32:39 +08007995
7996 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7997 wifi_getApVlanID(apIndex,&vlanId);
7998
developerd946fd62022-12-08 18:03:28 +08007999 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8000 return RETURN_ERR;
8001 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
developer06a01d92022-09-07 16:32:39 +08008002 _syscmd(cmd,buf, sizeof(buf));
8003
8004 return 0;
8005}
8006
8007INT wifi_pushChannel(INT radioIndex, UINT channel)
8008{
developerd946fd62022-12-08 18:03:28 +08008009 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008010 char cmd[128];
8011 char buf[1024];
8012 int apIndex;
8013
8014 apIndex=(radioIndex==0)?0:1;
developerd946fd62022-12-08 18:03:28 +08008015 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8016 return RETURN_ERR;
8017 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
developer06a01d92022-09-07 16:32:39 +08008018 _syscmd(cmd,buf, sizeof(buf));
8019
8020 return 0;
8021}
8022
8023INT wifi_pushChannelMode(INT radioIndex)
8024{
8025 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8026 return RETURN_ERR;
8027}
8028
8029INT wifi_pushDefaultValues(INT radioIndex)
8030{
8031 //Apply Comcast specified default radio settings instantly
8032 //AMPDU=1
8033 //AMPDUFrames=32
8034 //AMPDULim=50000
8035 //txqueuelen=1000
8036
8037 return RETURN_ERR;
8038}
8039
8040INT wifi_pushTxChainMask(INT radioIndex)
8041{
8042 //Apply default TxChainMask instantly
8043 return RETURN_ERR;
8044}
8045
8046INT wifi_pushRxChainMask(INT radioIndex)
8047{
8048 //Apply default RxChainMask instantly
8049 return RETURN_ERR;
8050}
8051
8052INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8053{
8054 INT status;
8055
8056 status = wifi_setSSIDName(apIndex,ssid);
8057 wifi_setApEnable(apIndex,FALSE);
8058 wifi_setApEnable(apIndex,TRUE);
8059
8060 return status;
8061}
8062
8063INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8064{
8065 //Apply default Ssid Advertisement instantly
8066 return RETURN_ERR;
8067}
8068
8069INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8070{
8071 INT status = RETURN_ERR;
8072 *output = 0;
8073 return RETURN_ERR;
8074}
8075
8076INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8077{
8078 return RETURN_OK;
8079}
8080
8081INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8082{
8083 return RETURN_OK;
8084}
8085
8086//To-do
8087INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8088{
developereb199ae2022-09-13 14:04:27 +08008089 char output[16]={'\0'};
8090 char config_file[MAX_BUF_SIZE] = {0};
8091
8092 if (!output_string)
8093 return RETURN_ERR;
8094
8095 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8096 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8097
8098 if (strlen(output) == 0)
8099 snprintf(output_string, 64, "Disabled");
8100 else if (strncmp(output, "0", 1) == 0)
8101 snprintf(output_string, 64, "Disabled");
8102 else if (strncmp(output, "1", 1) == 0)
8103 snprintf(output_string, 64, "Optional");
8104 else if (strncmp(output, "2", 1) == 0)
8105 snprintf(output_string, 64, "Required");
8106 else {
8107 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8108 return RETURN_ERR;
8109 }
8110
8111 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08008112 return RETURN_OK;
8113}
8114INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8115{
developereb199ae2022-09-13 14:04:27 +08008116 char str[MAX_BUF_SIZE]={'\0'};
8117 char cmd[MAX_CMD_SIZE]={'\0'};
8118 struct params params;
8119 char config_file[MAX_BUF_SIZE] = {0};
8120
8121 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8122 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8123 return RETURN_ERR;
8124
8125 params.name = "ieee80211w";
8126 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8127 params.value = "0";
8128 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8129 params.value = "1";
8130 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8131 params.value = "2";
8132 else{
8133 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8134 return RETURN_ERR;
8135 }
8136 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8137 wifi_hostapdWrite(config_file, &params, 1);
8138 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008139 return RETURN_OK;
8140}
8141INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8142{
8143 char output[16]={'\0'};
8144 char config_file[MAX_BUF_SIZE] = {0};
8145
8146 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8147 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8148 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8149
8150 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8151 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8152
8153 return RETURN_OK;
8154}
8155
8156INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8157{
8158 return RETURN_OK;
8159}
8160
8161INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8162{
8163 return RETURN_OK;
8164}
8165
8166INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8167{
8168 return RETURN_OK;
8169}
8170
8171INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8172{
8173 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8174 char config_file[MAX_BUF_SIZE] = {0};
8175
8176 if (NULL == output)
8177 return RETURN_ERR;
8178 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8179 wifi_hostapdRead(config_file,"hw_mode",output,64);
8180
8181 if(strcmp(output,"b")==0)
8182 sprintf(output, "%s", "1,2,5.5,11");
8183 else if (strcmp(output,"a")==0)
8184 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8185 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8186 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8187
8188 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8189 return RETURN_OK;
8190}
8191
8192INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8193{
8194 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8195 char *temp;
8196 char temp_output[128];
8197 char temp_TransmitRates[128];
8198 char config_file[MAX_BUF_SIZE] = {0};
8199
8200 if (NULL == output)
8201 return RETURN_ERR;
8202
8203 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8204 wifi_hostapdRead(config_file,"supported_rates",output,64);
8205
developer5b398df2022-11-17 20:39:48 +08008206 if (strlen(output) == 0) {
8207 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8208 return RETURN_OK;
8209 }
developer06a01d92022-09-07 16:32:39 +08008210 strcpy(temp_TransmitRates,output);
8211 strcpy(temp_output,"");
8212 temp = strtok(temp_TransmitRates," ");
8213 while(temp!=NULL)
8214 {
8215 temp[strlen(temp)-1]=0;
8216 if((temp[0]=='5') && (temp[1]=='\0'))
8217 {
8218 temp="5.5";
8219 }
8220 strcat(temp_output,temp);
8221 temp = strtok(NULL," ");
8222 if(temp!=NULL)
8223 {
8224 strcat(temp_output,",");
8225 }
8226 }
8227 strcpy(output,temp_output);
8228 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8229
8230 return RETURN_OK;
8231}
8232
8233INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8234{
8235 return RETURN_OK;
8236}
8237
8238
8239INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8240{
8241 int i=0;
8242 char *temp;
developeref938762022-10-19 17:21:01 +08008243 char temp1[128] = {0};
8244 char temp_output[128] = {0};
8245 char temp_TransmitRates[128] = {0};
developer06a01d92022-09-07 16:32:39 +08008246 struct params params={'\0'};
8247 char config_file[MAX_BUF_SIZE] = {0};
developeref938762022-10-19 17:21:01 +08008248 wifi_band band = wifi_index_to_band(wlanIndex);
developer06a01d92022-09-07 16:32:39 +08008249
8250 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8251 if(NULL == output)
8252 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08008253 strcpy(temp_TransmitRates,output);
8254
8255 for(i=0;i<strlen(temp_TransmitRates);i++)
8256 {
developeref938762022-10-19 17:21:01 +08008257 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
developer06a01d92022-09-07 16:32:39 +08008258 {
8259 continue;
8260 }
8261 else
8262 {
8263 return RETURN_ERR;
8264 }
8265 }
8266 strcpy(temp_output,"");
developeref938762022-10-19 17:21:01 +08008267 temp = strtok(temp_TransmitRates,",");
developer06a01d92022-09-07 16:32:39 +08008268 while(temp!=NULL)
8269 {
8270 strcpy(temp1,temp);
developeref938762022-10-19 17:21:01 +08008271 if(band == band_5)
developer06a01d92022-09-07 16:32:39 +08008272 {
developeref938762022-10-19 17:21:01 +08008273 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
developer06a01d92022-09-07 16:32:39 +08008274 {
8275 return RETURN_ERR;
8276 }
8277 }
8278
8279 if(strcmp(temp,"5.5")==0)
8280 {
8281 strcpy(temp1,"55");
8282 }
8283 else
8284 {
8285 strcat(temp1,"0");
8286 }
8287 strcat(temp_output,temp1);
developeref938762022-10-19 17:21:01 +08008288 temp = strtok(NULL,",");
developer06a01d92022-09-07 16:32:39 +08008289 if(temp!=NULL)
8290 {
8291 strcat(temp_output," ");
8292 }
8293 }
8294 strcpy(output,temp_output);
8295
developer06a01d92022-09-07 16:32:39 +08008296 params.name = "supported_rates";
8297 params.value = output;
8298
8299 wifi_dbg_printf("\n%s:",__func__);
8300 wifi_dbg_printf("params.value=%s\n",params.value);
8301 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8302 wifi_hostapdWrite(config_file,&params,1);
8303 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8304
8305 return RETURN_OK;
8306}
8307
8308
8309static char *sncopy(char *dst, int dst_sz, const char *src)
8310{
8311 if (src && dst && dst_sz > 0) {
8312 strncpy(dst, src, dst_sz);
8313 dst[dst_sz - 1] = '\0';
8314 }
8315 return dst;
8316}
8317
8318static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8319{
8320 if (0 == strcmp(ht_mode, "HT40") ||
8321 0 == strcmp(ht_mode, "HT80") ||
8322 0 == strcmp(ht_mode, "HT160")) {
8323 switch (channel) {
8324 case 1 ... 7:
8325 case 36:
8326 case 44:
8327 case 52:
8328 case 60:
8329 case 100:
8330 case 108:
8331 case 116:
8332 case 124:
8333 case 132:
8334 case 140:
8335 case 149:
8336 case 157:
8337 return 1;
8338 case 8 ... 13:
8339 case 40:
8340 case 48:
8341 case 56:
8342 case 64:
8343 case 104:
8344 case 112:
8345 case 120:
8346 case 128:
8347 case 136:
8348 case 144:
8349 case 153:
8350 case 161:
8351 return -1;
8352 default:
8353 return -EINVAL;
8354 }
8355 }
8356
8357 return -EINVAL;
8358}
8359
developerb7593de2022-10-18 09:51:57 +08008360static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8361{
8362 int idx = channel%8;
8363 if (0 == strcmp(ht_mode, "HT40") ||
8364 0 == strcmp(ht_mode, "HT80") ||
8365 0 == strcmp(ht_mode, "HT160")) {
8366 switch (idx) {
8367 case 1:
8368 return 1;
8369 case 5:
8370 return -1;
8371 default:
8372 return -EINVAL;
8373 }
8374 }
8375
8376 return -EINVAL;
8377}
developer06a01d92022-09-07 16:32:39 +08008378static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8379{
8380 if (NULL == hw_mode) return;
8381
8382 if (0 == strcmp(hw_mode, "ac"))
8383 sncopy(bw_mode, bw_mode_len, "ht vht");
8384
8385 if (0 == strcmp(hw_mode, "n"))
8386 sncopy(bw_mode, bw_mode_len, "ht");
8387
8388 return;
8389}
8390
8391static int util_chan_to_freq(int chan)
8392{
8393 if (chan == 14)
8394 return 2484;
8395 else if (chan < 14)
8396 return 2407 + chan * 5;
8397 else if (chan >= 182 && chan <= 196)
8398 return 4000 + chan * 5;
8399 else
8400 return 5000 + chan * 5;
8401 return 0;
8402}
8403
developerb7593de2022-10-18 09:51:57 +08008404static int util_6G_chan_to_freq(int chan)
8405{
8406 if (chan)
8407 return 5950 + chan * 5;
8408 else
8409 return 0;
8410
8411}
developer06a01d92022-09-07 16:32:39 +08008412const int *util_unii_5g_chan2list(int chan, int width)
8413{
8414 static const int lists[] = {
8415 // <width>, <chan1>, <chan2>..., 0,
8416 20, 36, 0,
8417 20, 40, 0,
8418 20, 44, 0,
8419 20, 48, 0,
8420 20, 52, 0,
8421 20, 56, 0,
8422 20, 60, 0,
8423 20, 64, 0,
8424 20, 100, 0,
8425 20, 104, 0,
8426 20, 108, 0,
8427 20, 112, 0,
8428 20, 116, 0,
8429 20, 120, 0,
8430 20, 124, 0,
8431 20, 128, 0,
8432 20, 132, 0,
8433 20, 136, 0,
8434 20, 140, 0,
8435 20, 144, 0,
8436 20, 149, 0,
8437 20, 153, 0,
8438 20, 157, 0,
8439 20, 161, 0,
8440 20, 165, 0,
8441 40, 36, 40, 0,
8442 40, 44, 48, 0,
8443 40, 52, 56, 0,
8444 40, 60, 64, 0,
8445 40, 100, 104, 0,
8446 40, 108, 112, 0,
8447 40, 116, 120, 0,
8448 40, 124, 128, 0,
8449 40, 132, 136, 0,
8450 40, 140, 144, 0,
8451 40, 149, 153, 0,
8452 40, 157, 161, 0,
8453 80, 36, 40, 44, 48, 0,
8454 80, 52, 56, 60, 64, 0,
8455 80, 100, 104, 108, 112, 0,
8456 80, 116, 120, 124, 128, 0,
8457 80, 132, 136, 140, 144, 0,
8458 80, 149, 153, 157, 161, 0,
8459 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8460 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8461 -1 // final delimiter
8462 };
8463 const int *start;
8464 const int *p;
8465
8466 for (p = lists; *p != -1; p++) {
8467 if (*p == width) {
8468 for (start = ++p; *p != 0; p++) {
8469 if (*p == chan)
8470 return start;
8471 }
8472 }
8473 // move to the end of channel list of given width
8474 while (*p != 0) {
8475 p++;
8476 }
8477 }
8478
8479 return NULL;
8480}
8481
8482static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8483{
8484 if (NULL == ht_mode)
8485 return 0;
8486
8487 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8488 const int *chans = util_unii_5g_chan2list(channel, width);
8489 int sum = 0;
8490 int cnt = 0;
8491
8492 if (NULL == chans)
8493 return 0;
8494
8495 while (*chans) {
8496 sum += *chans;
8497 cnt++;
8498 chans++;
8499 }
developer30423732022-12-01 16:17:49 +08008500 if (cnt == 0)
8501 return 0;
developer06a01d92022-09-07 16:32:39 +08008502 return sum / cnt;
8503}
8504
developerb7593de2022-10-18 09:51:57 +08008505static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8506{
8507 if (NULL == ht_mode)
8508 return 0;
8509
8510 int width = strtol((ht_mode + 2), NULL, 10);
8511
8512 int idx = 0 ;
8513 int centerchan = 0;
8514 int chan_ofs = 1;
8515
8516 if (width == 40){
8517 idx = ((channel/4) + chan_ofs)%2;
8518 switch (idx) {
8519 case 0:
8520 centerchan = (channel - 2);
8521 break;
8522 case 1:
8523 centerchan = (channel + 2);
8524 break;
8525 default:
8526 return -EINVAL;
8527 }
8528 }else if (width == 80){
8529 idx = ((channel/4) + chan_ofs)%4;
8530 switch (idx) {
8531 case 0:
8532 centerchan = (channel - 6);
8533 break;
8534 case 1:
8535 centerchan = (channel + 6);
8536 break;
8537 case 2:
8538 centerchan = (channel + 2);
8539 break;
8540 case 3:
8541 centerchan = (channel - 2);
8542 break;
8543 default:
8544 return -EINVAL;
8545 }
8546 }else if (width == 160){
8547 switch (channel) {
8548 case 1 ... 29:
8549 centerchan = 15;
8550 break;
8551 case 33 ... 61:
8552 centerchan = 47;
8553 break;
8554 case 65 ... 93:
8555 centerchan = 79;
8556 break;
8557 case 97 ... 125:
8558 centerchan = 111;
8559 break;
8560 case 129 ... 157:
8561 centerchan = 143;
8562 break;
8563 case 161 ... 189:
8564 centerchan = 175;
8565 break;
8566 case 193 ... 221:
8567 centerchan = 207;
8568 break;
8569 default:
8570 return -EINVAL;
8571 }
8572 }
8573 return centerchan;
8574}
developer06a01d92022-09-07 16:32:39 +08008575static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8576{
8577 BOOL onlyG, onlyN, onlyA;
8578 CHAR tmp[64];
8579 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8580 if (ret == RETURN_OK) {
8581 sncopy(hw_mode, hw_mode_size, tmp);
8582 }
8583 return ret;
8584}
8585
8586INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8587{
8588 // Sample commands:
8589 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8590 // hostapd_cli -i wifi0 chan_switch 30 2437
8591 char cmd[MAX_CMD_SIZE] = {0};
8592 char buf[MAX_BUF_SIZE] = {0};
8593 int freq = 0, ret = 0;
8594 char center_freq1_str[32] = ""; // center_freq1=%d
8595 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8596 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8597 char hw_mode[16] = ""; // n|ac
8598 char bw_mode[16] = ""; // ht|ht vht
8599 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
developerd946fd62022-12-08 18:03:28 +08008600 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008601 int sec_chan_offset;
8602 int width;
developer4fb0b922022-09-30 14:29:09 +08008603 char config_file[64] = {0};
8604 BOOL stbcEnable = FALSE;
developer5884e982022-10-06 10:52:50 +08008605 char *ext_str = "None";
developerb7593de2022-10-18 09:51:57 +08008606 wifi_band band = band_invalid;
8607 int center_chan = 0;
8608 int center_freq1 = 0;
developer5884e982022-10-06 10:52:50 +08008609
developer4fb0b922022-09-30 14:29:09 +08008610 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008611
developerd946fd62022-12-08 18:03:28 +08008612 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8613 return RETURN_ERR;
8614
developer06a01d92022-09-07 16:32:39 +08008615 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8616
developerb7593de2022-10-18 09:51:57 +08008617 band = wifi_index_to_band(radioIndex);
8618
developer5884e982022-10-06 10:52:50 +08008619 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
developer06a01d92022-09-07 16:32:39 +08008620
8621 // Get radio mode HT20|HT40|HT80 etc.
developer5884e982022-10-06 10:52:50 +08008622 if (channel){
developerb7593de2022-10-18 09:51:57 +08008623 if (band == band_6){
8624 freq = util_6G_chan_to_freq(channel);
8625 }else{
8626 freq = util_chan_to_freq(channel);
8627 }
developer5884e982022-10-06 10:52:50 +08008628 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
developer06a01d92022-09-07 16:32:39 +08008629
developer5884e982022-10-06 10:52:50 +08008630 // Provide bandwith if specified
8631 if (channel_width_MHz > 20) {
8632 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8633 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8634 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
developer06a01d92022-09-07 16:32:39 +08008635
developer5884e982022-10-06 10:52:50 +08008636 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8637 }else if (channel_width_MHz == 20){
8638 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8639 }
developer06a01d92022-09-07 16:32:39 +08008640
developerb7593de2022-10-18 09:51:57 +08008641
developer5884e982022-10-06 10:52:50 +08008642 if (channel_width_MHz > 20) {
developerb7593de2022-10-18 09:51:57 +08008643 if (band == band_6){
8644 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8645 if(center_chan){
8646 center_freq1 = util_6G_chan_to_freq(center_chan);
8647 }
8648 }else{
8649 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8650 if(center_chan){
8651 center_freq1 = util_chan_to_freq(center_chan);
8652 }
developer5884e982022-10-06 10:52:50 +08008653 }
developerb7593de2022-10-18 09:51:57 +08008654
8655 if (center_freq1)
8656 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8657
8658 }
8659
8660 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8661 if (band == band_6){
8662 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8663 }else{
8664 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
developer06a01d92022-09-07 16:32:39 +08008665 }
developerb7593de2022-10-18 09:51:57 +08008666 if (sec_chan_offset != -EINVAL)
8667 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
developer06a01d92022-09-07 16:32:39 +08008668
developer5884e982022-10-06 10:52:50 +08008669 // Only the first AP, other are hanging on the same radio
8670 int apIndex = radioIndex;
developerd946fd62022-12-08 18:03:28 +08008671 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
8672 interface_name, csa_beacon_count, freq,
developer5884e982022-10-06 10:52:50 +08008673 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8674 wifi_dbg_printf("execute: '%s'\n", cmd);
8675 ret = _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08008676
developer5884e982022-10-06 10:52:50 +08008677 ret = wifi_setRadioChannel(radioIndex, channel);
8678 if (ret != RETURN_OK) {
8679 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8680 return RETURN_ERR;
8681 }
8682
8683 if (sec_chan_offset == 1) ext_str = "Above";
8684 else if (sec_chan_offset == -1) ext_str = "Below";
8685
8686 wifi_setRadioCenterChannel(radioIndex, center_chan);
developer06a01d92022-09-07 16:32:39 +08008687
developer5884e982022-10-06 10:52:50 +08008688 } else {
8689 if (channel_width_MHz > 20)
8690 ext_str = "Above";
8691 }
developer4fb0b922022-09-30 14:29:09 +08008692 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8693 _syscmd(cmd, buf, sizeof(buf));
8694 if (strlen(buf) != 0)
8695 stbcEnable = TRUE;
8696
developer06a01d92022-09-07 16:32:39 +08008697 wifi_setRadioExtChannel(radioIndex, ext_str);
8698
developer4fb0b922022-09-30 14:29:09 +08008699 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8700
developer06a01d92022-09-07 16:32:39 +08008701 char mhz_str[16];
8702 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8703 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8704
8705 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8706
8707 return RETURN_OK;
8708}
8709
8710INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8711{
developer615510b2022-09-27 10:14:35 +08008712 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008713 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008714 char cmd[256]={0};
8715 char buf[128]={0};
8716 char file_name[32] = {0};
8717 char filter_SSID[32] = {0};
8718 char line[256] = {0};
developerd946fd62022-12-08 18:03:28 +08008719 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08008720 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008721 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008722 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008723 size_t len=0;
8724 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008725 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008726 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008727 bool filter_enable = false;
8728 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer033b37b2022-10-18 11:27:46 +08008729 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +08008730
developer615510b2022-09-27 10:14:35 +08008731 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008732
developer615510b2022-09-27 10:14:35 +08008733 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8734 f = fopen(file_name, "r");
8735 if (f != NULL) {
8736 fgets(filter_SSID, sizeof(file_name), f);
8737 if (strlen(filter_SSID) != 0)
8738 filter_enable = true;
8739 fclose(f);
8740 }
8741
developerd946fd62022-12-08 18:03:28 +08008742 if (GetInterfaceName(radio_index, interface_name) != RETURN_OK)
8743 return RETURN_ERR;
8744
developer033b37b2022-10-18 11:27:46 +08008745 phyId = radio_index_to_phy(radio_index);
8746
8747 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
developer615510b2022-09-27 10:14:35 +08008748 _syscmd(cmd, buf, sizeof(buf));
8749 channels_num = strtol(buf, NULL, 10);
8750
developerd946fd62022-12-08 18:03:28 +08008751 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8752 // 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 +08008753 fprintf(stderr, "cmd: %s\n", cmd);
8754 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008755 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8756 return RETURN_ERR;
8757 }
developer5550e242022-09-30 09:59:32 +08008758
8759 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8760 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8761
developer615510b2022-09-27 10:14:35 +08008762 ret = fgets(line, sizeof(line), f);
8763 while (ret != NULL) {
8764 if(strstr(line, "BSS") != NULL) { // new neighbor info
8765 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8766 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8767 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8768
8769 if (!filter_BSS) {
8770 index++;
8771 wifi_neighbor_ap2_t *tmp;
8772 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8773 if (tmp == NULL) { // no more memory to use
8774 index--;
8775 wifi_dbg_printf("%s: realloc failed\n", __func__);
8776 break;
8777 }
8778 scan_array = tmp;
8779 }
8780 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008781
developer615510b2022-09-27 10:14:35 +08008782 filter_BSS = false;
8783 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8784 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8785 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8786 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8787 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008788 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008789 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008790
developer615510b2022-09-27 10:14:35 +08008791 if (freq >= 2412 && freq <= 2484) {
8792 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8793 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8794 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8795 }
8796 else if (freq >= 5160 && freq <= 5805) {
8797 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8798 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8799 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8800 }
developer06a01d92022-09-07 16:32:39 +08008801
developer615510b2022-09-27 10:14:35 +08008802 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008803 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008804 for (int i = 0; i < channels_num; i++) {
8805 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8806 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8807 break;
8808 }
8809 }
developer06a01d92022-09-07 16:32:39 +08008810 }
developer615510b2022-09-27 10:14:35 +08008811 } else if (strstr(line, "beacon interval") != NULL) {
8812 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8813 } else if (strstr(line, "signal") != NULL) {
8814 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8815 } else if (strstr(line,"SSID") != NULL) {
8816 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8817 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8818 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008819 }
developer615510b2022-09-27 10:14:35 +08008820 } else if (strstr(line, "Supported rates") != NULL) {
8821 char SRate[80] = {0}, *tmp = NULL;
8822 memset(buf, 0, sizeof(buf));
8823 strcpy(SRate, line);
8824 tmp = strtok(SRate, ":");
8825 tmp = strtok(NULL, ":");
8826 strcpy(buf, tmp);
8827 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008828
developer615510b2022-09-27 10:14:35 +08008829 tmp = strtok(buf, " \n");
8830 while (tmp != NULL) {
8831 strcat(SRate, tmp);
8832 if (SRate[strlen(SRate) - 1] == '*') {
8833 SRate[strlen(SRate) - 1] = '\0';
8834 }
8835 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008836
developer615510b2022-09-27 10:14:35 +08008837 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008838 }
developer615510b2022-09-27 10:14:35 +08008839 SRate[strlen(SRate) - 1] = '\0';
8840 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8841 } else if (strstr(line, "DTIM") != NULL) {
8842 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8843 } else if (strstr(line, "VHT capabilities") != NULL) {
8844 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8845 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8846 } else if (strstr(line, "HT capabilities") != NULL) {
8847 strcat(scan_array[index].ap_SupportedStandards, ",n");
8848 strcpy(scan_array[index].ap_OperatingStandards, "n");
8849 } else if (strstr(line, "VHT operation") != NULL) {
8850 ret = fgets(line, sizeof(line), f);
8851 sscanf(line," * channel width: %d", &vht_channel_width);
8852 if(vht_channel_width == 1) {
8853 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8854 } else {
8855 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8856 }
8857 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8858 continue;
8859 } else if (strstr(line, "HT operation") != NULL) {
8860 ret = fgets(line, sizeof(line), f);
8861 sscanf(line," * secondary channel offset: %s", &buf);
8862 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008863 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008864 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 +08008865 }
developer615510b2022-09-27 10:14:35 +08008866 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008867 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008868 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8869 } else {
8870 //20Mhz
8871 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 +08008872 }
developer615510b2022-09-27 10:14:35 +08008873 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008874 continue;
developer615510b2022-09-27 10:14:35 +08008875 } else if (strstr(line, "HE capabilities") != NULL) {
8876 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8877 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8878 ret = fgets(line, sizeof(line), f);
8879 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8880 if (strstr(line, "HE40/2.4GHz") != NULL)
8881 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8882 else
8883 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8884 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8885 if (strstr(line, "HE80/5GHz") != NULL) {
8886 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8887 ret = fgets(line, sizeof(line), f);
8888 } else
8889 continue;
8890 if (strstr(line, "HE160/5GHz") != NULL)
8891 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008892 }
developer615510b2022-09-27 10:14:35 +08008893 continue;
8894 } else if (strstr(line, "WPA") != NULL) {
8895 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8896 } else if (strstr(line, "RSN") != NULL) {
8897 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8898 } else if (strstr(line, "Group cipher") != NULL) {
8899 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8900 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8901 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008902 }
developer06a01d92022-09-07 16:32:39 +08008903 }
developer615510b2022-09-27 10:14:35 +08008904 ret = fgets(line, sizeof(line), f);
8905 }
8906
8907 if (!filter_BSS) {
8908 *output_array_size = index + 1;
8909 } else {
8910 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8911 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008912 }
developer06a01d92022-09-07 16:32:39 +08008913 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008914 pclose(f);
developer5550e242022-09-30 09:59:32 +08008915 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008916 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008917 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008918}
developer615510b2022-09-27 10:14:35 +08008919
developer06a01d92022-09-07 16:32:39 +08008920INT wifi_getApAssociatedDeviceStats(
8921 INT apIndex,
8922 mac_address_t *clientMacAddress,
8923 wifi_associated_dev_stats_t *associated_dev_stats,
8924 u64 *handle)
8925{
8926 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8927 char interface_name[50] = {0};
8928 char cmd[1024] = {0};
8929 char mac_str[18] = {0};
8930 char *key = NULL;
8931 char *val = NULL;
8932 FILE *f = NULL;
8933 char *line = NULL;
8934 size_t len = 0;
developer06a01d92022-09-07 16:32:39 +08008935
8936 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8937 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8938 return RETURN_ERR;
8939 }
8940
8941 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8942 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8943 if((f = popen(cmd, "r")) == NULL) {
8944 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8945 return RETURN_ERR;
8946 }
8947
developer30423732022-12-01 16:17:49 +08008948 while ((getline(&line, &len, f)) != -1) {
developer06a01d92022-09-07 16:32:39 +08008949 key = strtok(line,":");
8950 val = strtok(NULL,":");
8951
8952 if(!strncmp(key,"rx bytes",8))
8953 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8954 if(!strncmp(key,"tx bytes",8))
8955 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8956 if(!strncmp(key,"rx packets",10))
8957 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8958 if(!strncmp(key,"tx packets",10))
8959 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8960 if(!strncmp(key,"tx retries",10))
8961 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8962 if(!strncmp(key,"tx failed",9))
8963 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8964 if(!strncmp(key,"rx drop misc",13))
8965 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8966 if(!strncmp(key,"rx bitrate",10)) {
8967 val = strtok(val, " ");
8968 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8969 }
8970 if(!strncmp(key,"tx bitrate",10)) {
8971 val = strtok(val, " ");
8972 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8973 }
8974 }
8975 free(line);
8976 pclose(f);
8977 return RETURN_OK;
8978}
8979
8980INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8981{
developerd946fd62022-12-08 18:03:28 +08008982 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08008983 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8984
8985 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8986 if (NULL == output_string)
8987 return RETURN_ERR;
8988
developerd946fd62022-12-08 18:03:28 +08008989 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8990 return RETURN_ERR;
8991 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 +08008992 _syscmd(cmd, buf, sizeof(buf));
8993
8994 //size of SSID name restricted to value less than 32 bytes
8995 snprintf(output_string, 32, "%s", buf);
8996 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8997
8998 return RETURN_OK;
8999}
9000
9001INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9002{
9003 //char cmd[MAX_CMD_SIZE] = {0};
9004 char config_file[MAX_BUF_SIZE] = {0};
9005 char buf[32] = {0};
9006
9007 if (!output_filterMode)
9008 return RETURN_ERR;
9009
9010 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9011 //_syscmd(cmd, buf, sizeof(buf));
9012 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9013 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08009014 if(strlen(buf) == 0) {
9015 *output_filterMode = 0;
9016 }
9017 else {
9018 int macaddr_acl_mode = strtol(buf, NULL, 10);
9019 if (macaddr_acl_mode == 1) {
9020 *output_filterMode = 1;
9021 } else if (macaddr_acl_mode == 0) {
9022 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9023 if (strlen(buf) == 0) {
9024 *output_filterMode = 0;
9025 } else {
9026 *output_filterMode = 2;
9027 }
9028 } else {
9029 return RETURN_ERR;
9030 }
9031 }
developer06a01d92022-09-07 16:32:39 +08009032
9033 return RETURN_OK;
9034}
9035
9036INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9037{
9038 FILE *fp = NULL;
9039 char str[MAX_BUF_SIZE] = {0};
9040 int wificlientindex = 0 ;
9041 int count = 0;
9042 int signalstrength = 0;
9043 int arr[MACADDRESS_SIZE] = {0};
9044 unsigned char mac[MACADDRESS_SIZE] = {0};
9045 UINT wifi_count = 0;
9046 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9047 char pipeCmd[MAX_CMD_SIZE] = {0};
9048
9049 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9050 *output_array_size = 0;
9051 *associated_dev_array = NULL;
9052 char interface_name[50] = {0};
9053
9054 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9055 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9056 return RETURN_ERR;
9057 }
9058
9059 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9060 fp = popen(pipeCmd, "r");
9061 if (fp == NULL)
9062 {
9063 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9064 return RETURN_ERR;
9065 }
9066
9067 /* Read the output a line at a time - output it. */
9068 fgets(str, sizeof(str)-1, fp);
9069 wifi_count = (unsigned int) atoi ( str );
9070 *output_array_size = wifi_count;
9071 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9072 pclose(fp);
9073
9074 if(wifi_count == 0)
9075 {
9076 return RETURN_OK;
9077 }
9078 else
9079 {
9080 wifi_associated_dev2_t* temp = NULL;
9081 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9082 *associated_dev_array = temp;
9083 if(temp == NULL)
9084 {
9085 printf("Error Statement. Insufficient memory \n");
9086 return RETURN_ERR;
9087 }
9088
9089 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9090 system(pipeCmd);
9091
9092 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9093 if(fp == NULL)
9094 {
9095 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9096 return RETURN_ERR;
9097 }
9098 fclose(fp);
9099
developer30423732022-12-01 16:17:49 +08009100 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
developer06a01d92022-09-07 16:32:39 +08009101 fp = popen(pipeCmd, "r");
9102 if(fp)
9103 {
9104 for(count =0 ; count < wifi_count; count++)
9105 {
9106 fgets(str, MAX_BUF_SIZE, fp);
9107 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9108 {
9109 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9110 {
9111 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9112
9113 }
9114 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9115 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]);
9116 }
9117 temp[count].cli_AuthenticationState = 1; //TODO
9118 temp[count].cli_Active = 1; //TODO
9119 }
9120 pclose(fp);
9121 }
9122
9123 //Updating RSSI per client
developer30423732022-12-01 16:17:49 +08009124 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 +08009125 fp = popen(pipeCmd, "r");
9126 if(fp)
9127 {
9128 pclose(fp);
9129 }
9130 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9131 if(fp)
9132 {
9133 for(count =0 ; count < wifi_count ;count++)
9134 {
9135 fgets(str, MAX_BUF_SIZE, fp);
9136 signalstrength = atoi(str);
9137 temp[count].cli_RSSI = signalstrength;
9138 }
9139 pclose(fp);
9140 }
9141
9142
9143 //LastDataDownlinkRate
developer30423732022-12-01 16:17:49 +08009144 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 +08009145 fp = popen(pipeCmd, "r");
9146 if (fp)
9147 {
9148 pclose(fp);
9149 }
9150 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9151 if (fp)
9152 {
9153 for (count = 0; count < wifi_count; count++)
9154 {
9155 fgets(str, MAX_BUF_SIZE, fp);
9156 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9157 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9158 }
9159 pclose(fp);
9160 }
9161
9162 //LastDataUplinkRate
developer30423732022-12-01 16:17:49 +08009163 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 +08009164 fp = popen(pipeCmd, "r");
9165 if (fp)
9166 {
9167 pclose(fp);
9168 }
9169 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9170 if (fp)
9171 {
9172 for (count = 0; count < wifi_count; count++)
9173 {
9174 fgets(str, MAX_BUF_SIZE, fp);
9175 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9176 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9177 }
9178 pclose(fp);
9179 }
9180 }
9181 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9182 return RETURN_OK;
9183
9184}
9185
9186INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9187{
9188#if 0
9189 /*char buf[1024] = {0};
developerd946fd62022-12-08 18:03:28 +08009190 sprintf(cmd, "ifconfig %s ", interface_name);
developer06a01d92022-09-07 16:32:39 +08009191 _syscmd(cmd, buf, sizeof(buf));*/
9192
9193 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9194 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9195 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9196 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9197
9198 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.
9199 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].
9200 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].
9201 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].
9202 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9203 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9204
9205 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9206 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9207 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9208 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.
9209 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.
9210 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.
9211 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.
9212 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.
9213 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.
9214 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.
9215 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9216#endif
9217
9218 FILE *fp = NULL;
developer06a01d92022-09-07 16:32:39 +08009219 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08009220 char pipeCmd[128] = {0};
9221 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08009222 wifi_ssidTrafficStats2_t *out = output_struct;
9223
developerce736392022-09-13 15:24:34 +08009224 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009225 if (!output_struct)
9226 return RETURN_ERR;
9227
developerce736392022-09-13 15:24:34 +08009228 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
developerdbbd6782022-12-16 14:26:20 +08009229 if (GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
9230 return RETURN_ERR;
developerce736392022-09-13 15:24:34 +08009231 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009232
developer06a01d92022-09-07 16:32:39 +08009233 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009234 if (fp == NULL) {
9235 fprintf(stderr, "%s: popen failed\n", __func__);
9236 return RETURN_ERR;
9237 }
9238 fgets(str, sizeof(str), fp);
developerd946fd62022-12-08 18:03:28 +08009239 pclose(fp);
developer06a01d92022-09-07 16:32:39 +08009240
developerce736392022-09-13 15:24:34 +08009241 if (strlen(str) == 0) // interface not exist
9242 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08009243
developerce736392022-09-13 15:24:34 +08009244 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9245 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009246
developerce736392022-09-13 15:24:34 +08009247 memset(str, 0, sizeof(str));
9248 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08009249 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08009250 if (fp == NULL) {
9251 fprintf(stderr, "%s: popen failed\n", __func__);
9252 return RETURN_ERR;
9253 }
9254 fgets(str, sizeof(str), fp);
9255
9256 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9257 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08009258 pclose(fp);
developerce736392022-09-13 15:24:34 +08009259
9260 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9261 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9262
9263 // Not supported
9264 output_struct->ssid_RetransCount = 0;
9265 output_struct->ssid_FailedRetransCount = 0;
9266 output_struct->ssid_RetryCount = 0;
9267 output_struct->ssid_MultipleRetryCount = 0;
9268 output_struct->ssid_ACKFailureCount = 0;
9269 output_struct->ssid_AggregatedPacketCount = 0;
9270
developer06a01d92022-09-07 16:32:39 +08009271 return RETURN_OK;
9272}
9273
9274//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).
9275INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9276{
9277 char output_val[16]={'\0'};
9278 char config_file[MAX_BUF_SIZE] = {0};
9279
9280 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9281 if (!output)
9282 return RETURN_ERR;
9283 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9284 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9285
9286 if( strcmp(output_val,"1") == 0 )
9287 *output = TRUE;
9288 else
9289 *output = FALSE;
9290 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9291
9292 return RETURN_OK;
9293}
9294
9295INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9296{
9297 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9298 char str[MAX_BUF_SIZE]={'\0'};
9299 char string[MAX_BUF_SIZE]={'\0'};
9300 char cmd[MAX_CMD_SIZE]={'\0'};
9301 char *ch;
9302 char config_file[MAX_BUF_SIZE] = {0};
9303 struct params params;
9304
9305 if(enable == TRUE)
9306 strcpy(string,"1");
9307 else
9308 strcpy(string,"0");
9309
9310 params.name = "ap_isolate";
9311 params.value = string;
9312
9313 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9314 wifi_hostapdWrite(config_file,&params,1);
9315 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9316
9317 return RETURN_OK;
9318}
9319
9320INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9321{
9322 if (NULL == output_dBm)
9323 return RETURN_ERR;
9324
9325 *output_dBm = 0;
9326 return RETURN_OK;
9327}
9328
9329INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9330{
9331 return RETURN_OK;
9332}
9333INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9334{
9335 return RETURN_OK;
9336}
9337INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9338{
9339 return RETURN_OK;
9340}
9341INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9342{
9343 return RETURN_OK;
9344}
9345INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9346{
9347 return RETURN_OK;
9348}
9349INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9350{
9351 char config_file[MAX_BUF_SIZE] = {0};
9352 struct params list;
9353
9354 list.name = "bss_transition";
9355 list.value = activate?"1":"0";
9356 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9357 wifi_hostapdWrite(config_file, &list, 1);
9358
9359 return RETURN_OK;
9360}
9361wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9362
9363void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9364{
9365 return;
9366}
9367
9368INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9369{
9370 // TODO Implement me!
9371 return RETURN_OK;
9372}
9373
9374INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9375{
developera3c68b92022-09-13 15:27:29 +08009376 char file_name[128] = {0};
9377 char buf[128] = {0};
9378 FILE *f = NULL;
developer804c64f2022-10-19 13:54:40 +08009379 int max_num_radios = 0;
developera3c68b92022-09-13 15:27:29 +08009380
9381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9382
developer804c64f2022-10-19 13:54:40 +08009383 wifi_getMaxRadioNumber(&max_num_radios);
developera3c68b92022-09-13 15:27:29 +08009384 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
developer804c64f2022-10-19 13:54:40 +08009385 for (int index = 0; index < max_num_radios; index++) {
developera3c68b92022-09-13 15:27:29 +08009386 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9387 f = fopen(file_name, "w");
9388 if (f == NULL)
9389 return RETURN_ERR;
9390 // For mode == 0 is to disable filter, just don't write to the file.
9391 if (mode)
9392 fprintf(f, "%s", essid);
9393
9394 fclose(f);
9395 }
9396 } else { // special case, need to set AP's SSID as filter for each radio.
9397 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9398 f = fopen(file_name, "w");
9399 if (f == NULL)
9400 return RETURN_ERR;
9401
9402 // For mode == 0 is to disable filter, just don't write to the file.
9403 if (mode)
9404 fprintf(f, "%s", essid);
9405
9406 fclose(f);
9407 }
9408
9409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009410 return RETURN_OK;
9411}
9412
9413INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9414{
9415 // TODO Implement me!
9416 //Apply wifi_pushRadioChannel() instantly
9417 return RETURN_ERR;
9418}
9419
9420INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9421{
9422 // TODO Implement me!
9423 return RETURN_OK;
9424}
9425
9426#ifdef HAL_NETLINK_IMPL
9427static int tidStats_callback(struct nl_msg *msg, void *arg) {
9428 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9429 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9430 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9431 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9432 int rem , tid_index = 0;
9433
9434 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9435 wifi_associated_dev_tid_entry_t *stats_entry;
9436
9437 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9438 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9439 };
9440 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9441 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9442 };
9443
9444 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9445 genlmsg_attrlen(gnlh, 0), NULL);
9446
9447
9448 if (!tb[NL80211_ATTR_STA_INFO]) {
9449 fprintf(stderr, "station stats missing!\n");
9450 return NL_SKIP;
9451 }
9452
9453 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9454 tb[NL80211_ATTR_STA_INFO],
9455 stats_policy)) {
9456 fprintf(stderr, "failed to parse nested attributes!\n");
9457 return NL_SKIP;
9458 }
9459
9460 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9461 {
9462 stats_entry = &out->tid_array[tid_index];
9463
9464 stats_entry->tid = tid_index;
9465 stats_entry->ac = _tid_ac_index_get[tid_index];
9466
9467 if(sinfo[NL80211_STA_INFO_TID_STATS])
9468 {
9469 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9470 printf("failed to parse nested stats attributes!");
9471 return NL_SKIP;
9472 }
9473 }
9474 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9475 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9476
9477 if(tid_index < (PS_MAX_TID - 1))
9478 tid_index++;
9479 }
9480 //ToDo: sum_time_ms, ewma_time_ms
9481 return NL_SKIP;
9482}
9483#endif
9484
9485INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9486{
9487#ifdef HAL_NETLINK_IMPL
9488 Netlink nl;
9489 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009490 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +08009491
developerd946fd62022-12-08 18:03:28 +08009492 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9493 return RETURN_ERR;
9494
9495 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009496
9497 nl.id = initSock80211(&nl);
9498
9499 if (nl.id < 0) {
9500 fprintf(stderr, "Error initializing netlink \n");
9501 return -1;
9502 }
9503
9504 struct nl_msg* msg = nlmsg_alloc();
9505
9506 if (!msg) {
9507 fprintf(stderr, "Failed to allocate netlink message.\n");
9508 nlfree(&nl);
9509 return -2;
9510 }
9511
9512 genlmsg_put(msg,
9513 NL_AUTO_PORT,
9514 NL_AUTO_SEQ,
9515 nl.id,
9516 0,
9517 0,
9518 NL80211_CMD_GET_STATION,
9519 0);
9520
9521 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9522 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9523 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9524 nl_send_auto(nl.socket, msg);
9525 nl_recvmsgs(nl.socket, nl.cb);
9526 nlmsg_free(msg);
9527 nlfree(&nl);
9528 return RETURN_OK;
9529#else
9530//iw implementation
9531#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9532#define TOTAL_MAX_LINES 50
9533
9534 char buf[256] = {'\0'}; /* or other suitable maximum line size */
developerd946fd62022-12-08 18:03:28 +08009535 char if_name[32] = {0};
developer06a01d92022-09-07 16:32:39 +08009536 FILE *fp=NULL;
9537 char pipeCmd[1024]= {'\0'};
9538 int lines,tid_index=0;
9539 char mac_addr[20] = {'\0'};
9540
developerd946fd62022-12-08 18:03:28 +08009541 if (GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9542 return RETURN_ERR;
9543
developer06a01d92022-09-07 16:32:39 +08009544 wifi_associated_dev_tid_entry_t *stats_entry;
9545
developer06a01d92022-09-07 16:32:39 +08009546 strcpy(mac_addr,clientMacAddress);
9547
9548 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9549 fp= popen(pipeCmd,"r");
9550 if(fp == NULL)
9551 {
9552 perror("popen for station dump failed\n");
9553 return RETURN_ERR;
9554 }
9555 pclose(fp);
9556
9557 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9558 fp=popen(pipeCmd,"r");
9559 if(fp == NULL)
9560 {
9561 perror("popen for grep station failed\n");
9562 return RETURN_ERR;
9563 }
9564 else if(fgets(buf,sizeof(buf),fp) != NULL)
9565 lines=atoi(buf);
9566 else
9567 {
9568 pclose(fp);
9569 fprintf(stderr,"No devices are connected \n");
9570 return RETURN_ERR;
9571 }
9572 pclose(fp);
9573
9574 if(lines == 1)
9575 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9576
9577 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9578 {
9579 stats_entry = &tid_stats->tid_array[tid_index];
9580 stats_entry->tid = tid_index;
9581
9582 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);
9583
9584 fp=popen(pipeCmd,"r");
9585 if(fp ==NULL)
9586 {
9587 perror("Failed to read from tid file \n");
9588 return RETURN_ERR;
9589 }
9590 else if(fgets(buf,sizeof(buf),fp) != NULL)
9591 stats_entry->num_msdus = atol(buf);
9592
9593 pclose(fp);
9594 stats_entry->ac = _tid_ac_index_get[tid_index];
9595// TODO:
9596// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9597// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9598 }
9599 return RETURN_OK;
9600#endif
9601}
9602
9603
9604INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9605{
developerd946fd62022-12-08 18:03:28 +08009606 char interface_name[16] = {0};
developer615510b2022-09-27 10:14:35 +08009607 char cmd[128]={0};
9608 char buf[128]={0};
9609 int freq = 0;
9610
9611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9612
9613 // full mode is used to scan all channels.
9614 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9615 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9616 ieee80211_channel_to_frequency(chan_list[0], &freq);
9617
developerd946fd62022-12-08 18:03:28 +08009618 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9619 return RETURN_ERR;
9620
developer615510b2022-09-27 10:14:35 +08009621 if (freq)
developerd946fd62022-12-08 18:03:28 +08009622 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
developer615510b2022-09-27 10:14:35 +08009623 else
developerd946fd62022-12-08 18:03:28 +08009624 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
developer615510b2022-09-27 10:14:35 +08009625
9626 _syscmd(cmd, buf, sizeof(buf));
9627 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9628
developer06a01d92022-09-07 16:32:39 +08009629 return RETURN_OK;
9630}
9631
9632
9633INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9634{
9635 // TODO Implement me!
9636 return RETURN_ERR;
9637}
9638
9639INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9640{
9641 // TODO Implement me!
9642 return RETURN_ERR;
9643}
9644
9645INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9646{
9647 // TODO Implement me!
9648 return RETURN_ERR;
9649}
9650
9651INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9652{
9653 // TODO Implement me!
9654 return RETURN_ERR;
9655}
9656
9657INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9658{
9659 // TODO Implement me!
9660 return RETURN_ERR;
9661}
9662
9663INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9664{
9665 // TODO Implement me!
9666 return RETURN_ERR;
9667}
9668
9669INT wifi_steering_eventUnregister(void)
9670{
9671 // TODO Implement me!
9672 return RETURN_ERR;
9673}
9674
9675INT wifi_delApAclDevices(INT apIndex)
9676{
9677#if 0
9678 char cmd[MAX_BUF_SIZE] = {0};
9679 char buf[MAX_BUF_SIZE] = {0};
9680
9681 /* Not reset proof solution */
developerd946fd62022-12-08 18:03:28 +08009682 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
developer06a01d92022-09-07 16:32:39 +08009683 if(_syscmd(cmd,buf,sizeof(buf)))
9684 return RETURN_ERR;
9685#endif
developere6aafda2022-09-13 14:59:28 +08009686 char cmd[MAX_CMD_SIZE]={0};
9687 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009688
developere6aafda2022-09-13 14:59:28 +08009689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9690 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9691 if(_syscmd(cmd, buf, sizeof(buf)))
9692 return RETURN_ERR;
9693 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009694
9695 return RETURN_OK;
9696}
9697
9698#ifdef HAL_NETLINK_IMPL
9699static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9700 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9701 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9702 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9703 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9704 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9705 char mac_addr[20],dev[20];
9706
9707 nla_parse(tb,
9708 NL80211_ATTR_MAX,
9709 genlmsg_attrdata(gnlh, 0),
9710 genlmsg_attrlen(gnlh, 0),
9711 NULL);
9712
9713 if(!tb[NL80211_ATTR_STA_INFO]) {
9714 fprintf(stderr, "sta stats missing!\n");
9715 return NL_SKIP;
9716 }
9717
9718 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9719 fprintf(stderr, "failed to parse nested attributes!\n");
9720 return NL_SKIP;
9721 }
9722 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9723
9724 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9725
9726 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9727 fprintf(stderr, "failed to parse nested rate attributes!");
9728 return NL_SKIP;
9729 }
9730
9731 if(sinfo[NL80211_STA_INFO_TID_STATS])
9732 {
9733 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9734 printf("failed to parse nested stats attributes!");
9735 return NL_SKIP;
9736 }
9737 }
9738
9739 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9740 {
9741 printf("Type is VHT\n");
9742 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9743 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9744
9745 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9746 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9747 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9748 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9749 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9750 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9751 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9752 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9753 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9754 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9755 }
9756 else
9757 {
9758 printf(" OFDM or CCK \n");
9759 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9760 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9761 }
9762
9763 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9764 if(rinfo[NL80211_RATE_INFO_MCS])
9765 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9766 }
9767 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9768 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9769 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9770 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9771
9772 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9773 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9774
9775 if (sinfo[NL80211_STA_INFO_SIGNAL])
9776 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9777 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9778 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9779 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9780 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9781 //rssi_array need to be filled
9782 return NL_SKIP;
9783}
9784#endif
9785
9786INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9787{
9788#ifdef HAL_NETLINK_IMPL
9789 Netlink nl;
developerd946fd62022-12-08 18:03:28 +08009790 char if_name[32];
9791 if (GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9792 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08009793
9794 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9795
9796 if (*output_array_size <= 0)
9797 return RETURN_OK;
9798
developer06a01d92022-09-07 16:32:39 +08009799 nl.id = initSock80211(&nl);
9800
9801 if (nl.id < 0) {
9802 fprintf(stderr, "Error initializing netlink \n");
9803 return 0;
9804 }
9805
9806 struct nl_msg* msg = nlmsg_alloc();
9807
9808 if (!msg) {
9809 fprintf(stderr, "Failed to allocate netlink message.\n");
9810 nlfree(&nl);
9811 return 0;
9812 }
9813
9814 genlmsg_put(msg,
9815 NL_AUTO_PORT,
9816 NL_AUTO_SEQ,
9817 nl.id,
9818 0,
9819 0,
9820 NL80211_CMD_GET_STATION,
9821 0);
9822
9823 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9824 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9825 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9826 nl_send_auto(nl.socket, msg);
9827 nl_recvmsgs(nl.socket, nl.cb);
9828 nlmsg_free(msg);
9829 nlfree(&nl);
9830 return RETURN_OK;
9831#else
9832 //TODO Implement me
9833 return RETURN_OK;
9834#endif
9835}
9836
9837#ifdef HAL_NETLINK_IMPL
9838static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9839 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9840 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9841 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9842 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9843 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9844 char mac_addr[20],dev[20];
9845
9846 nla_parse(tb,
9847 NL80211_ATTR_MAX,
9848 genlmsg_attrdata(gnlh, 0),
9849 genlmsg_attrlen(gnlh, 0),
9850 NULL);
9851
9852 if(!tb[NL80211_ATTR_STA_INFO]) {
9853 fprintf(stderr, "sta stats missing!\n");
9854 return NL_SKIP;
9855 }
9856
9857 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9858 fprintf(stderr, "failed to parse nested attributes!\n");
9859 return NL_SKIP;
9860 }
9861
9862 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9863
9864 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9865
9866 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9867 fprintf(stderr, "failed to parse nested rate attributes!");
9868 return NL_SKIP;
9869 }
9870
9871 if(sinfo[NL80211_STA_INFO_TID_STATS])
9872 {
9873 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9874 printf("failed to parse nested stats attributes!");
9875 return NL_SKIP;
9876 }
9877 }
9878 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9879 {
9880 printf("Type is VHT\n");
9881 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9882 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9883
9884 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9885 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9886 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9887 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9888 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9889 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9890 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9891 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9892 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9893 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9894 }
9895 else
9896 {
9897 printf(" OFDM or CCK \n");
9898 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9899 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9900 }
9901
9902 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9903 if(rinfo[NL80211_RATE_INFO_MCS])
9904 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9905 }
9906
9907 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9908 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9909 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9910 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9911
9912 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9913 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9914 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9915
9916 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9917 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9918
9919 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9920 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9921
9922 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9923 ((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]);
9924
9925 return NL_SKIP;
9926}
9927#endif
9928
9929INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9930{
9931#ifdef HAL_NETLINK_IMPL
9932 Netlink nl;
9933 char if_name[10];
developerd946fd62022-12-08 18:03:28 +08009934 char interface_name[16] = {0};
9935 if (GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9936 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08009937
9938 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9939
9940 if (*output_array_size <= 0)
9941 return RETURN_OK;
9942
developerd946fd62022-12-08 18:03:28 +08009943 snprintf(if_name, sizeof(if_name), "%s", interface_name);
developer06a01d92022-09-07 16:32:39 +08009944
9945 nl.id = initSock80211(&nl);
9946
9947 if(nl.id < 0) {
9948 fprintf(stderr, "Error initializing netlink \n");
9949 return 0;
9950 }
9951
9952 struct nl_msg* msg = nlmsg_alloc();
9953
9954 if(!msg) {
9955 fprintf(stderr, "Failed to allocate netlink message.\n");
9956 nlfree(&nl);
9957 return 0;
9958 }
9959
9960 genlmsg_put(msg,
9961 NL_AUTO_PORT,
9962 NL_AUTO_SEQ,
9963 nl.id,
9964 0,
9965 0,
9966 NL80211_CMD_GET_STATION,
9967 0);
9968
9969 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9970 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9971 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9972 nl_send_auto(nl.socket, msg);
9973 nl_recvmsgs(nl.socket, nl.cb);
9974 nlmsg_free(msg);
9975 nlfree(&nl);
9976 return RETURN_OK;
9977#else
9978 //TODO Implement me
9979 return RETURN_OK;
9980#endif
9981}
9982
9983INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9984{
9985 // TODO Implement me!
9986 char buf[MAX_BUF_SIZE] = {0};
9987 char config_file[MAX_BUF_SIZE] = {0};
9988
9989 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9990 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9991 *activate = (strncmp("1",buf,1) == 0);
9992
9993 return RETURN_OK;
9994}
9995
9996INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9997{
9998 char config_file[MAX_BUF_SIZE] = {0};
9999 struct params list;
10000
10001 list.name = "rrm_neighbor_report";
10002 list.value = activate?"1":"0";
10003 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10004 wifi_hostapdWrite(config_file, &list, 1);
10005
10006 return RETURN_OK;
10007}
10008
10009INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10010{
10011 char buf[32] = {0};
10012 char config_file[MAX_BUF_SIZE] = {0};
10013
10014 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10015 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10016 *activate = (strncmp("1",buf,1) == 0);
10017
10018 return RETURN_OK;
10019}
10020#undef HAL_NETLINK_IMPL
10021#ifdef HAL_NETLINK_IMPL
10022static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10023 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10024 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10025 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10026 char dev[20];
10027 int freq =0 ;
10028 static int i=0;
10029
10030 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10031
10032 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10033 };
10034
10035 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10036
10037 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10038
10039 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10040 fprintf(stderr, "survey data missing!\n");
10041 return NL_SKIP;
10042 }
10043
10044 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10045 {
10046 fprintf(stderr, "failed to parse nested attributes!\n");
10047 return NL_SKIP;
10048 }
10049
10050
10051 if(out[0].array_size == 1 )
10052 {
10053 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10054 {
10055 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10056 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10057 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10058
10059 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10060 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10061 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10062 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10063 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10064 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10065 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10066 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10067 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10068 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10069 if (sinfo[NL80211_SURVEY_INFO_TIME])
10070 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10071 return NL_STOP;
10072 }
10073 }
10074 else
10075 {
10076 if ( i <= out[0].array_size )
10077 {
10078 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10079 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10080 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10081
10082 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10083 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10084 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10085 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10086 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10087 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10088 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10089 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10090 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10091 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10092 if (sinfo[NL80211_SURVEY_INFO_TIME])
10093 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10094 }
10095 }
10096
10097 i++;
10098 return NL_SKIP;
10099}
10100#endif
10101
10102static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10103{
10104 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10105 FILE *fp;
10106
10107 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10108 {
10109 printf("Creating Frequency-Channel Map\n");
10110 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10111 }
10112 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10113 if((fp = popen(command, "r")))
10114 {
10115 fgets(output, sizeof(output), fp);
10116 *freqMHz = atoi(output);
developer30423732022-12-01 16:17:49 +080010117 pclose(fp);
developer06a01d92022-09-07 16:32:39 +080010118 }
10119
10120 return 0;
10121}
10122
10123static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10124{
10125 int freqMHz = -1;
10126 char cmd[MAX_CMD_SIZE] = {'\0'};
developer033b37b2022-10-18 11:27:46 +080010127 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080010128
10129 ieee80211_channel_to_frequency(channel, &freqMHz);
10130 if (freqMHz == -1) {
10131 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10132 return -1;
10133 }
10134
developer033b37b2022-10-18 11:27:46 +080010135 phyId = radio_index_to_phy(radioIndex);
10136 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 +080010137 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10138 radioIndex, freqMHz);
10139 return -1;
10140 }
10141
10142 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10143 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10144 return -1;
10145 }
10146
10147 return 0;
10148}
10149
10150static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10151{
10152 const char *ptr = buf;
10153 char *key = NULL;
10154 char *val = NULL;
10155 char line[256] = { '\0' };
10156
10157 while (ptr = get_line_from_str_buf(ptr, line)) {
10158 if (strstr(line, "Frequency")) continue;
10159
10160 key = strtok(line, ":");
10161 val = strtok(NULL, " ");
10162 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10163
10164 if (!strcmp(key, "noise")) {
10165 sscanf(val, "%d", &stats->ch_noise);
10166 if (stats->ch_noise == 0) {
10167 // Workaround for missing noise information.
10168 // Assume -95 for 2.4G and -103 for 5G
10169 if (radioIndex == 0) stats->ch_noise = -95;
10170 if (radioIndex == 1) stats->ch_noise = -103;
10171 }
10172 }
10173 else if (!strcmp(key, "channel active time")) {
10174 sscanf(val, "%llu", &stats->ch_utilization_total);
10175 }
10176 else if (!strcmp(key, "channel busy time")) {
10177 sscanf(val, "%llu", &stats->ch_utilization_busy);
10178 }
10179 else if (!strcmp(key, "channel receive time")) {
10180 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10181 }
10182 else if (!strcmp(key, "channel transmit time")) {
10183 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10184 }
10185 };
10186
10187 return 0;
10188}
10189
10190INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10191{
10192 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10193#ifdef HAL_NETLINK_IMPL
10194 Netlink nl;
10195 wifi_channelStats_t_loc local[array_size];
developerd946fd62022-12-08 18:03:28 +080010196 char if_name[32];
developer06a01d92022-09-07 16:32:39 +080010197
10198 local[0].array_size = array_size;
10199
developerd946fd62022-12-08 18:03:28 +080010200 if (GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10201 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080010202
10203 nl.id = initSock80211(&nl);
10204
10205 if (nl.id < 0) {
10206 fprintf(stderr, "Error initializing netlink \n");
10207 return -1;
10208 }
10209
10210 struct nl_msg* msg = nlmsg_alloc();
10211
10212 if (!msg) {
10213 fprintf(stderr, "Failed to allocate netlink message.\n");
10214 nlfree(&nl);
10215 return -2;
10216 }
10217
10218 genlmsg_put(msg,
10219 NL_AUTO_PORT,
10220 NL_AUTO_SEQ,
10221 nl.id,
10222 0,
10223 NLM_F_DUMP,
10224 NL80211_CMD_GET_SURVEY,
10225 0);
10226
10227 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10228 nl_send_auto(nl.socket, msg);
10229 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10230 nl_recvmsgs(nl.socket, nl.cb);
10231 nlmsg_free(msg);
10232 nlfree(&nl);
10233 //Copying the Values
10234 for(int i=0;i<array_size;i++)
10235 {
10236 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10237 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10238 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10239 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10240 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10241 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10242 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10243 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10244 }
10245#else
10246 ULONG channel = 0;
10247 int i;
10248 int number_of_channels = array_size;
10249 char buf[512];
10250 INT ret;
10251 wifi_channelStats_t tmp_stats;
10252
10253 if (number_of_channels == 0) {
10254 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10255 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10256 return RETURN_ERR;
10257 }
10258 number_of_channels = 1;
10259 input_output_channelStats_array[0].ch_number = channel;
10260 }
10261
10262 for (i = 0; i < number_of_channels; i++) {
10263
10264 input_output_channelStats_array[i].ch_noise = 0;
10265 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10266 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10267 input_output_channelStats_array[i].ch_utilization_busy = 0;
10268 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10269 input_output_channelStats_array[i].ch_utilization_total = 0;
10270
10271 memset(buf, 0, sizeof(buf));
10272 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10273 return RETURN_ERR;
10274 }
10275 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10276 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10277 return RETURN_ERR;
10278 }
10279
10280 // XXX: fake missing 'self' counter which is not available in iw survey output
10281 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10282 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10283
10284 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10285 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10286 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10287 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10288 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10289
10290 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",
10291 __func__,
10292 input_output_channelStats_array[i].ch_number,
10293 input_output_channelStats_array[i].ch_noise,
10294 input_output_channelStats_array[i].ch_utilization_total,
10295 input_output_channelStats_array[i].ch_utilization_busy,
10296 input_output_channelStats_array[i].ch_utilization_busy_rx,
10297 input_output_channelStats_array[i].ch_utilization_busy_tx,
10298 input_output_channelStats_array[i].ch_utilization_busy_self,
10299 input_output_channelStats_array[i].ch_utilization_busy_ext);
10300 }
10301#endif
10302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10303 return RETURN_OK;
10304}
10305#define HAL_NETLINK_IMPL
10306
10307/* Hostapd events */
10308
10309#ifndef container_of
10310#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10311#define container_of(ptr, type, member) \
10312 ((type *)((char *)ptr - offset_of(type, member)))
10313#endif /* container_of */
10314
10315struct ctrl {
10316 char sockpath[128];
10317 char sockdir[128];
10318 char bss[IFNAMSIZ];
10319 char reply[4096];
10320 int ssid_index;
10321 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10322 void (*overrun)(struct ctrl *ctrl);
10323 struct wpa_ctrl *wpa;
10324 unsigned int ovfl;
10325 size_t reply_len;
10326 int initialized;
10327 ev_timer retry;
10328 ev_timer watchdog;
10329 ev_stat stat;
10330 ev_io io;
10331};
10332static wifi_newApAssociatedDevice_callback clients_connect_cb;
10333static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10334static struct ctrl wpa_ctrl[MAX_APS];
10335static int initialized;
10336
10337static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10338{
10339 char cbuf[256] = {};
10340 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10341 struct cmsghdr *cmsg;
10342 unsigned int ovfl = ctrl->ovfl;
10343 unsigned int drop;
10344
10345 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10346 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10347 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10348 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10349
10350 drop = ovfl - ctrl->ovfl;
10351 ctrl->ovfl = ovfl;
10352
10353 return drop;
10354}
10355
10356static void ctrl_close(struct ctrl *ctrl)
10357{
10358 if (ctrl->io.cb)
10359 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10360 if (ctrl->retry.cb)
10361 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10362 if (!ctrl->wpa)
10363 return;
10364
10365 wpa_ctrl_detach(ctrl->wpa);
10366 wpa_ctrl_close(ctrl->wpa);
10367 ctrl->wpa = NULL;
10368 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10369}
10370
10371static void ctrl_process(struct ctrl *ctrl)
10372{
10373 const char *str;
10374 int drops;
10375 int level;
10376 int err;
10377
10378 /* Example events:
10379 *
10380 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10381 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10382 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10383 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10384 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10385 */
10386 if (!(str = index(ctrl->reply, '>')))
10387 return;
10388 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10389 return;
10390
10391 str++;
10392
10393 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10394 if (!(str = index(ctrl->reply, ' ')))
10395 return;
10396 wifi_associated_dev_t sta;
10397 memset(&sta, 0, sizeof(sta));
10398
10399 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10400 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10401 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10402
10403 sta.cli_Active=true;
10404
10405 (clients_connect_cb)(ctrl->ssid_index, &sta);
10406 goto handled;
10407 }
10408
10409 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10410 if (!(str = index(ctrl->reply, ' ')))
10411 return;
10412
10413 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10414 goto handled;
10415 }
10416
10417 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10418 printf("CTRL_WPA: handle TERMINATING event\n");
10419 goto retry;
10420 }
10421
10422 if (strncmp("AP-DISABLED", str, 11) == 0) {
10423 printf("CTRL_WPA: handle AP-DISABLED\n");
10424 goto retry;
10425 }
10426
10427 printf("Event not supported!!\n");
10428
10429handled:
10430
10431 if ((drops = ctrl_get_drops(ctrl))) {
10432 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10433 if (ctrl->overrun)
10434 ctrl->overrun(ctrl);
10435 }
10436
10437 return;
10438
10439retry:
10440 printf("WPA_CTRL: closing\n");
10441 ctrl_close(ctrl);
10442 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10443 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10444}
10445
10446static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10447{
10448 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10449 int err;
10450
10451 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10452 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10453 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10454 ctrl->reply[ctrl->reply_len] = 0;
10455 if (err < 0) {
10456 if (errno == EAGAIN || errno == EWOULDBLOCK)
10457 return;
10458 ctrl_close(ctrl);
10459 ev_timer_again(EV_A_ &ctrl->retry);
10460 return;
10461 }
10462
10463 ctrl_process(ctrl);
10464}
10465
10466static int ctrl_open(struct ctrl *ctrl)
10467{
10468 int fd;
10469
10470 if (ctrl->wpa)
10471 return 0;
10472
10473 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10474 if (!ctrl->wpa)
10475 goto err;
10476
10477 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10478 goto err_close;
10479
10480 fd = wpa_ctrl_get_fd(ctrl->wpa);
10481 if (fd < 0)
10482 goto err_detach;
10483
10484 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10485 goto err_detach;
10486
10487 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10488 ev_io_start(EV_DEFAULT_ &ctrl->io);
10489
10490 return 0;
10491
10492err_detach:
10493 wpa_ctrl_detach(ctrl->wpa);
10494err_close:
10495 wpa_ctrl_close(ctrl->wpa);
10496err:
10497 ctrl->wpa = NULL;
10498 return -1;
10499}
10500
10501static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10502{
10503 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10504
10505 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10506 ctrl_open(ctrl);
10507}
10508
10509static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10510{
10511 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10512
10513 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10514 if (ctrl_open(ctrl) == 0) {
10515 printf("WPA_CTRL: retry successful\n");
10516 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10517 }
10518}
10519
10520int ctrl_enable(struct ctrl *ctrl)
10521{
10522 if (ctrl->wpa)
10523 return 0;
10524
10525 if (!ctrl->stat.cb) {
10526 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10527 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10528 }
10529
10530 if (!ctrl->retry.cb) {
10531 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10532 }
10533
10534 return ctrl_open(ctrl);
10535}
10536
10537static void
10538ctrl_msg_cb(char *buf, size_t len)
10539{
10540 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10541
10542 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10543 ctrl_process(ctrl);
10544}
10545
10546static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10547{
10548 int err;
10549
10550 if (!ctrl->wpa)
10551 return -1;
10552 if (*reply_len < 2)
10553 return -1;
10554
10555 (*reply_len)--;
10556 ctrl->reply_len = sizeof(ctrl->reply);
10557 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10558 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10559 if (err < 0)
10560 return err;
10561
10562 if (ctrl->reply_len > *reply_len)
10563 ctrl->reply_len = *reply_len;
10564
10565 *reply_len = ctrl->reply_len;
10566 memcpy(reply, ctrl->reply, *reply_len);
10567 reply[*reply_len - 1] = 0;
10568 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10569 return 0;
10570}
10571
10572static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10573{
10574 const char *pong = "PONG";
10575 const char *ping = "PING";
10576 char reply[1024];
10577 size_t len = sizeof(reply);
10578 int err;
10579 ULONG s, snum;
10580 INT ret;
10581 BOOL status;
10582
10583 printf("WPA_CTRL: watchdog cb\n");
10584
10585 ret = wifi_getSSIDNumberOfEntries(&snum);
10586 if (ret != RETURN_OK) {
10587 printf("%s: failed to get SSID count", __func__);
10588 return;
10589 }
10590
10591 if (snum > MAX_APS) {
10592 printf("more ssid than supported! %lu\n", snum);
10593 return;
10594 }
10595
10596 for (s = 0; s < snum; s++) {
10597 if (wifi_getApEnable(s, &status) != RETURN_OK) {
developer30423732022-12-01 16:17:49 +080010598 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
developer06a01d92022-09-07 16:32:39 +080010599 continue;
10600 }
10601 if (status == false) continue;
10602
10603 memset(reply, 0, sizeof(reply));
10604 len = sizeof(reply);
10605 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10606 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10607 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10608 continue;
10609
10610 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10611 ctrl_close(&wpa_ctrl[s]);
developer30423732022-12-01 16:17:49 +080010612 printf("WPA_CTRL: ev_timer_again %lu\n", s);
developer06a01d92022-09-07 16:32:39 +080010613 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10614 }
10615}
10616
10617static int init_wpa()
10618{
10619 int ret = 0, i = 0;
10620 ULONG s, snum;
10621
10622 ret = wifi_getSSIDNumberOfEntries(&snum);
10623 if (ret != RETURN_OK) {
10624 printf("%s: failed to get SSID count", __func__);
10625 return RETURN_ERR;
10626 }
10627
10628 if (snum > MAX_APS) {
10629 printf("more ssid than supported! %lu\n", snum);
10630 return RETURN_ERR;
10631 }
10632
10633 for (s = 0; s < snum; s++) {
10634 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10635 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10636 wpa_ctrl[s].ssid_index = s;
10637 ctrl_enable(&wpa_ctrl[s]);
10638 }
10639
10640 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10641 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10642
10643 initialized = 1;
10644 printf("WPA_CTRL: initialized\n");
10645
10646 return RETURN_OK;
10647}
10648
10649void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10650{
10651 clients_connect_cb = callback_proc;
10652 if (!initialized)
10653 init_wpa();
10654}
10655
10656void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10657{
10658 clients_disconnect_cb = callback_proc;
10659 if (!initialized)
10660 init_wpa();
10661}
10662
10663INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10664{
10665 // TODO Implement me!
10666 return RETURN_ERR;
10667}
10668
10669INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10670{
10671 // TODO Implement me!
10672 return RETURN_ERR;
10673}
10674
10675INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10676{
10677 int i;
10678 char cmd[256];
10679 char channel_numbers_buf[256];
10680 char dfs_state_buf[256];
10681 char line[256];
10682 const char *ptr;
10683
10684 memset(cmd, 0, sizeof(cmd));
10685 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10686 memset(line, 0, sizeof(line));
10687 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10688 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10689
10690 if (radioIndex == 0) { // 2.4G - all allowed
10691 if (outputMapSize < 11) {
10692 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10693 return RETURN_ERR;
10694 }
10695
10696 for (i = 0; i < 11; i++) {
10697 outputMap[i].ch_number = i + 1;
10698 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10699 }
10700
10701 return RETURN_OK;
10702 }
10703
10704 if (radioIndex == 1) { // 5G
10705// Example output of iw list:
10706//
10707// Frequencies:
10708// * 5180 MHz [36] (17.0 dBm)
10709// * 5200 MHz [40] (17.0 dBm)
10710// * 5220 MHz [44] (17.0 dBm)
10711// * 5240 MHz [48] (17.0 dBm)
10712// * 5260 MHz [52] (23.0 dBm) (radar detection)
10713// DFS state: usable (for 78930 sec)
10714// DFS CAC time: 60000 ms
10715// * 5280 MHz [56] (23.0 dBm) (radar detection)
10716// DFS state: usable (for 78930 sec)
10717// DFS CAC time: 60000 ms
10718// * 5300 MHz [60] (23.0 dBm) (radar detection)
10719// DFS state: usable (for 78930 sec)
10720// DFS CAC time: 60000 ms
10721// * 5320 MHz [64] (23.0 dBm) (radar detection)
10722// DFS state: usable (for 78930 sec)
10723// DFS CAC time: 60000 ms
10724// * 5500 MHz [100] (disabled)
10725// * 5520 MHz [104] (disabled)
10726// * 5540 MHz [108] (disabled)
10727// * 5560 MHz [112] (disabled)
10728//
10729// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10730 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10731 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10732 return RETURN_ERR;
10733 }
10734
10735 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10736 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10737 return RETURN_ERR;
10738 }
10739
10740 ptr = channel_numbers_buf;
10741 i = 0;
10742 while (ptr = get_line_from_str_buf(ptr, line)) {
10743 if (i >= outputMapSize) {
10744 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10745 return RETURN_ERR;
10746 }
10747 sscanf(line, "%d", &outputMap[i].ch_number);
10748
10749 memset(cmd, 0, sizeof(cmd));
10750 // Below command should fetch string for DFS state (usable, available or unavailable)
10751 // Example line: "DFS state: usable (for 78930 sec)"
10752 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) {
10753 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10754 return RETURN_ERR;
10755 }
10756
10757 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10758 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10759 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10760 return RETURN_ERR;
10761 }
10762
10763 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10764
10765 if (!strcmp(dfs_state_buf, "usable")) {
10766 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10767 } else if (!strcmp(dfs_state_buf, "available")) {
10768 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10769 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10770 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10771 } else {
10772 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10773 }
10774 i++;
10775 }
10776
10777 return RETURN_OK;
10778 }
10779
10780 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10781 return RETURN_ERR;
10782}
10783
10784INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10785{
10786 // TODO Implement me!
10787 return RETURN_ERR;
10788}
10789
10790INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10791{
10792 return RETURN_OK;
10793}
10794
10795INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10796{
10797 // TODO Implement me!
10798 return RETURN_ERR;
10799}
10800
10801INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10802{
10803 // TODO API refrence Implementaion is present on RPI hal
10804 return RETURN_ERR;
10805}
10806
10807INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10808{
developerd946fd62022-12-08 18:03:28 +080010809 char interface_name[16] = {0};
developera5005b62022-09-13 15:43:35 +080010810 char cmd[128]={'\0'};
10811 char buf[128]={'\0'};
10812 char *support;
10813 int maximum_tx = 0, current_tx = 0;
10814
10815 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10816 if(txpwr_pcntg == NULL)
10817 return RETURN_ERR;
10818
developerd946fd62022-12-08 18:03:28 +080010819 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10820 return RETURN_ERR;
10821
developera5005b62022-09-13 15:43:35 +080010822 // Get the maximum tx power of the device
developerd946fd62022-12-08 18:03:28 +080010823 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 +080010824 _syscmd(cmd, buf, sizeof(buf));
10825 maximum_tx = strtol(buf, NULL, 10);
10826
10827 // Get the current tx power
10828 memset(cmd, 0, sizeof(cmd));
10829 memset(buf, 0, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080010830 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 +080010831 _syscmd(cmd, buf, sizeof(buf));
10832 current_tx = strtol(buf, NULL, 10);
10833
10834 // Get the power supported list and find the current power percentage in supported list
10835 memset(buf, 0, sizeof(buf));
10836 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10837 support = strtok(buf, ",");
10838 while(true)
10839 {
10840 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 +080010841 *txpwr_pcntg = 100;
developera5005b62022-09-13 15:43:35 +080010842 wifi_dbg_printf("current power is not in supported list\n");
developer033b37b2022-10-18 11:27:46 +080010843 return RETURN_OK;
developera5005b62022-09-13 15:43:35 +080010844 }
10845 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10846 if (tmp == current_tx) {
10847 *txpwr_pcntg = strtol(support, NULL, 10);
10848 break;
10849 }
10850 support = strtok(NULL, ",");
10851 }
10852 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010853 return RETURN_OK;
10854}
10855
10856INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10857{
developer58599c22022-09-13 16:40:34 +080010858 // TODO precac feature.
10859 struct params params = {0};
10860 char config_file[128] = {0};
10861
10862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10863
10864 params.name = "enable_background_radar";
10865 params.value = enable?"1":"0";
10866 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10867 wifi_hostapdWrite(config_file, &params, 1);
10868 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10869
10870 /* TODO precac feature */
10871
10872 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10873 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010874}
10875
10876INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10877{
developer58599c22022-09-13 16:40:34 +080010878 char config_file[128] = {0};
10879 char buf[64] = {0};
10880
10881 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10882 if (NULL == enable || NULL == precac)
10883 return RETURN_ERR;
10884
10885 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10886 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10887 if (strncmp(enable, "1", 1) == 0)
10888 *enable = true;
10889 else
10890 *enable = false;
10891
10892 /* TODO precac feature */
10893
10894 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10895 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010896}
10897
10898INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10899{
developer58599c22022-09-13 16:40:34 +080010900 *supported = TRUE;
10901 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010902}
10903
developer3e6b1692022-09-30 18:04:05 +080010904INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10905{
10906 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10907 struct params params = {0};
10908 char config_file[64] = {0};
10909 char buf[64] = {0};
10910 unsigned int set_mu_type = 0;
10911 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10912
10913 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10914 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10915
10916 if (strlen(buf) > 0)
10917 set_mu_type = strtol(buf, NULL, 10);
10918
10919 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10920 set_mu_type &= ~0x05; // unset bit 0, 2
10921 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10922 set_mu_type |= 0x01;
10923 set_mu_type &= ~0x04;
10924 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10925 set_mu_type &= ~0x01;
10926 set_mu_type |= 0x04;
10927 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10928 set_mu_type |= 0x05; // set bit 0, 2
10929 }
10930
10931 params.name = "hemu_onoff";
10932 sprintf(buf, "%u", set_mu_type);
10933 params.value = buf;
10934 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10935 wifi_hostapdWrite(config_file, &params, 1);
10936 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10937
10938 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10939 return RETURN_OK;
10940}
10941
10942INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10943{
10944 struct params params={0};
10945 char config_file[64] = {0};
10946 char buf[64] = {0};
10947 unsigned int get_mu_type = 0;
10948
10949 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10950
10951 if (mu_type == NULL)
10952 return RETURN_ERR;
10953
10954 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10955 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10956 get_mu_type = strtol(buf, NULL, 10);
10957
10958 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10959 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10960 else if (get_mu_type & 0x04)
10961 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10962 else if (get_mu_type & 0x01)
10963 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10964 else
10965 *mu_type = WIFI_DL_MU_TYPE_NONE;
10966
10967 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10968 return RETURN_OK;
10969}
10970
10971INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10972{
10973 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10974 struct params params={0};
10975 char config_file[64] = {0};
10976 char buf[64] = {0};
10977 unsigned int set_mu_type = 0;
10978 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10979
10980 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10981 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10982
10983 if (strlen(buf) > 0)
10984 set_mu_type = strtol(buf, NULL, 10);
10985
10986 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10987 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10988 set_mu_type &= ~0x0a;
10989 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10990 set_mu_type |= 0x02;
10991 set_mu_type &= ~0x08;
10992 }
10993
10994 params.name = "hemu_onoff";
10995 sprintf(buf, "%u", set_mu_type);
10996 params.value = buf;
10997 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10998 wifi_hostapdWrite(config_file, &params, 1);
10999 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11000
11001 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11002 return RETURN_OK;
11003}
11004
11005INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11006{
11007 struct params params={0};
11008 char config_file[64] = {0};
11009 char buf[64] = {0};
11010 unsigned int get_mu_type = 0;
11011
11012 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11013
11014 if (mu_type == NULL)
11015 return RETURN_ERR;
11016
11017 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11018 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11019
11020 get_mu_type = strtol(buf, NULL, 10);
11021 if (get_mu_type & 0x02)
11022 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11023 else
11024 *mu_type = WIFI_DL_MU_TYPE_NONE;
11025
11026 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11027 return RETURN_OK;
11028}
11029
11030
developer454b9462022-09-13 15:29:16 +080011031INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11032{
11033 char cmd[128] = {0};
developer254882b2022-09-30 17:12:31 +080011034 char buf[256] = {0};
11035 char config_file[64] = {0};
developer454b9462022-09-13 15:29:16 +080011036 char GI[8] = {0};
developer254882b2022-09-30 17:12:31 +080011037 int mode_map = 0;
developer454b9462022-09-13 15:29:16 +080011038 FILE *f = NULL;
developer254882b2022-09-30 17:12:31 +080011039 wifi_band band = band_invalid;
developer454b9462022-09-13 15:29:16 +080011040
11041 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11042
developer254882b2022-09-30 17:12:31 +080011043 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
developer454b9462022-09-13 15:29:16 +080011044 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11045 return RETURN_ERR;
11046 }
developer454b9462022-09-13 15:29:16 +080011047
developer254882b2022-09-30 17:12:31 +080011048 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
developer454b9462022-09-13 15:29:16 +080011049 band = wifi_index_to_band(radio_index);
developer454b9462022-09-13 15:29:16 +080011050
developer254882b2022-09-30 17:12:31 +080011051 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11052 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
developer6372c2b2022-10-27 17:39:51 +080011053 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011054 _syscmd(cmd, buf, sizeof(buf));
11055 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11056 wifi_hostapdRead(config_file, "ht_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 '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
developer254882b2022-09-30 17:12:31 +080011059 _syscmd(cmd, buf, sizeof(buf));
11060 }
11061 if (band == band_5) {
11062 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11063 if (strstr(buf, "[SHORT-GI-") == NULL) {
developer6372c2b2022-10-27 17:39:51 +080011064 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 +080011065 _syscmd(cmd, buf, sizeof(buf));
11066 }
11067 }
11068 }
11069 wifi_reloadAp(radio_index);
developer454b9462022-09-13 15:29:16 +080011070
developer254882b2022-09-30 17:12:31 +080011071 if (guard_interval == wifi_guard_interval_400)
11072 strcpy(GI, "0.4");
11073 else if (guard_interval == wifi_guard_interval_800)
11074 strcpy(GI, "0.8");
11075 else if (guard_interval == wifi_guard_interval_1600)
11076 strcpy(GI, "1.6");
11077 else if (guard_interval == wifi_guard_interval_3200)
11078 strcpy(GI, "3.2");
11079 else if (guard_interval == wifi_guard_interval_auto)
11080 strcpy(GI, "auto");
developer454b9462022-09-13 15:29:16 +080011081 // Record GI for get GI function
11082 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11083 f = fopen(buf, "w");
developer254882b2022-09-30 17:12:31 +080011084 if (f == NULL)
11085 return RETURN_ERR;
11086 fprintf(f, "%s", GI);
developer454b9462022-09-13 15:29:16 +080011087 fclose(f);
11088 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11089 return RETURN_OK;
11090}
11091
11092INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11093{
11094 char buf[32] = {0};
11095 char cmd[64] = {0};
11096
11097 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11098
11099 if (guard_interval == NULL)
11100 return RETURN_ERR;
11101
11102 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11103 _syscmd(cmd, buf, sizeof(buf));
11104
11105 if (strncmp(buf, "0.4", 3) == 0)
11106 *guard_interval = wifi_guard_interval_400;
11107 else if (strncmp(buf, "0.8", 3) == 0)
11108 *guard_interval = wifi_guard_interval_800;
11109 else if (strncmp(buf, "1.6", 3) == 0)
11110 *guard_interval = wifi_guard_interval_1600;
11111 else if (strncmp(buf, "3.2", 3) == 0)
11112 *guard_interval = wifi_guard_interval_3200;
11113 else
11114 *guard_interval = wifi_guard_interval_auto;
11115
11116 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11117 return RETURN_OK;
11118}
11119
developer3cc61d12022-09-13 16:36:05 +080011120INT wifi_setBSSColor(INT radio_index, UCHAR color)
11121{
11122 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11123 struct params params = {0};
11124 char config_file[128] = {0};
11125 char bss_color[4] ={0};
11126
11127 params.name = "he_bss_color";
11128 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11129 params.value = bss_color;
11130 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11131 wifi_hostapdWrite(config_file, &params, 1);
11132 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11133
11134 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11135 return RETURN_OK;
11136}
11137
11138INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11139{
11140 char config_file[128] = {0};
11141 char buf[64] = {0};
11142 char temp_output[128] = {'\0'};
11143
11144 wifi_dbg_printf("\nFunc=%s\n", __func__);
11145 if (NULL == color)
11146 return RETURN_ERR;
11147
11148 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11149 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11150
11151 if(strlen(buf) > 0) {
11152 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11153 } else {
11154 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11155 }
11156
11157 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11158 wifi_dbg_printf("\noutput_string=%s\n", color);
11159
11160 return RETURN_OK;
11161}
11162
developer06a01d92022-09-07 16:32:39 +080011163/* multi-psk support */
11164INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11165{
11166 char cmd[256];
developerd946fd62022-12-08 18:03:28 +080011167 char interface_name[16] = {0};
11168
11169 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11170 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011171
developerd946fd62022-12-08 18:03:28 +080011172 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11173 interface_name,
developer06a01d92022-09-07 16:32:39 +080011174 mac[0],
11175 mac[1],
11176 mac[2],
11177 mac[3],
11178 mac[4],
11179 mac[5]
11180 );
11181 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11182 _syscmd(cmd, key->wifi_keyId, 64);
11183
11184
11185 return RETURN_OK;
11186}
11187
11188INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11189{
developerd946fd62022-12-08 18:03:28 +080011190 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011191 FILE *fd = NULL;
11192 char fname[100];
11193 char cmd[128] = {0};
11194 char out[64] = {0};
11195 wifi_key_multi_psk_t * key = NULL;
11196 if(keysNumber < 0)
11197 return RETURN_ERR;
11198
developer431128d2022-12-16 15:30:41 +080011199 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011200 fd = fopen(fname, "w");
11201 if (!fd) {
11202 return RETURN_ERR;
11203 }
11204 key= (wifi_key_multi_psk_t *) keys;
11205 for(int i=0; i<keysNumber; ++i, key++) {
11206 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11207 }
11208 fclose(fd);
11209
11210 //reload file
developerd946fd62022-12-08 18:03:28 +080011211 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11212 return RETURN_ERR;
11213 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
developer06a01d92022-09-07 16:32:39 +080011214 _syscmd(cmd, out, 64);
11215 return RETURN_OK;
11216}
11217
11218INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11219{
11220 FILE *fd = NULL;
11221 char fname[100];
11222 char * line = NULL;
11223 char * pos = NULL;
11224 size_t len = 0;
11225 ssize_t read = 0;
11226 INT ret = RETURN_OK;
11227 wifi_key_multi_psk_t *keys_it = NULL;
11228
11229 if (keysNumber < 1) {
11230 return RETURN_ERR;
11231 }
11232
developer431128d2022-12-16 15:30:41 +080011233 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
developer06a01d92022-09-07 16:32:39 +080011234 fd = fopen(fname, "r");
11235 if (!fd) {
11236 return RETURN_ERR;
11237 }
11238
11239 if (keys == NULL) {
11240 ret = RETURN_ERR;
11241 goto close;
11242 }
11243
11244 keys_it = keys;
11245 while ((read = getline(&line, &len, fd)) != -1) {
11246 //Strip trailing new line if present
11247 if (read > 0 && line[read-1] == '\n') {
11248 line[read-1] = '\0';
11249 }
11250
11251 if(strcmp(line,"keyid=")) {
11252 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11253 if (!(pos = index(line, ' '))) {
11254 ret = RETURN_ERR;
11255 goto close;
11256 }
11257 pos++;
11258 //Here should be 00:00:00:00:00:00
11259 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11260 printf("Not supported MAC: %s\n", pos);
11261 }
11262 if (!(pos = index(pos, ' '))) {
11263 ret = RETURN_ERR;
11264 goto close;
11265 }
11266 pos++;
11267
11268 //The rest is PSK
11269 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11270 keys_it++;
11271
11272 if(--keysNumber <= 0)
11273 break;
11274 }
11275 }
11276
11277close:
11278 free(line);
11279 fclose(fd);
11280 return ret;
11281}
11282/* end of multi-psk support */
11283
11284INT wifi_setNeighborReports(UINT apIndex,
11285 UINT numNeighborReports,
11286 wifi_NeighborReport_t *neighborReports)
11287{
11288 char cmd[256] = { 0 };
11289 char hex_bssid[13] = { 0 };
11290 char bssid[18] = { 0 };
11291 char nr[256] = { 0 };
11292 char ssid[256];
11293 char hex_ssid[256];
developerd946fd62022-12-08 18:03:28 +080011294 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080011295 INT ret;
11296
11297 /*rmeove all neighbors*/
developerd946fd62022-12-08 18:03:28 +080011298 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
11299 if (GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11300 return RETURN_ERR;
11301 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 +080011302 system(cmd);
11303
11304 for(unsigned int i = 0; i < numNeighborReports; i++)
11305 {
11306 memset(ssid, 0, sizeof(ssid));
11307 ret = wifi_getSSIDName(apIndex, ssid);
11308 if (ret != RETURN_OK)
11309 return RETURN_ERR;
11310
11311 memset(hex_ssid, 0, sizeof(hex_ssid));
11312 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11313 sprintf(hex_ssid + k,"%02x", ssid[j]);
11314
11315 snprintf(hex_bssid, sizeof(hex_bssid),
11316 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11317 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11318 snprintf(bssid, sizeof(bssid),
11319 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11320 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11321
11322 snprintf(nr, sizeof(nr),
11323 "%s" // bssid
11324 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11325 "%02hhx" // operclass
11326 "%02hhx" // channel
11327 "%02hhx", // phy_mode
11328 hex_bssid,
11329 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11330 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11331 neighborReports[i].opClass,
11332 neighborReports[i].channel,
11333 neighborReports[i].phyTable);
11334
11335 snprintf(cmd, sizeof(cmd),
11336 "hostapd_cli set_neighbor "
11337 "%s " // bssid
11338 "ssid=%s " // ssid
11339 "nr=%s " // nr
developerd946fd62022-12-08 18:03:28 +080011340 "-i %s",
11341 bssid,hex_ssid,nr, interface_name);
developer06a01d92022-09-07 16:32:39 +080011342
11343 if (WEXITSTATUS(system(cmd)) != 0)
11344 {
11345 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11346 }
11347 }
11348
11349 return RETURN_OK;
11350}
11351
11352INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11353{
11354 return RETURN_OK;
11355}
11356
11357#ifdef _WIFI_HAL_TEST_
11358int main(int argc,char **argv)
11359{
11360 int index;
11361 INT ret=0;
11362 char buf[1024]="";
11363
11364 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11365 if(argc<3)
11366 {
11367 if(argc==2)
11368 {
11369 if(!strcmp(argv[1], "init"))
11370 return wifi_init();
11371 if(!strcmp(argv[1], "reset"))
11372 return wifi_reset();
11373 if(!strcmp(argv[1], "wifi_getHalVersion"))
11374 {
11375 char buffer[64];
11376 if(wifi_getHalVersion(buffer)==RETURN_OK)
11377 printf("Version: %s\n", buffer);
11378 else
11379 printf("Error in wifi_getHalVersion\n");
11380 return RETURN_OK;
11381 }
11382 }
11383 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11384 exit(-1);
11385 }
11386
11387 index = atoi(argv[2]);
11388 if(strstr(argv[1], "wifi_getApName")!=NULL)
11389 {
11390 wifi_getApName(index,buf);
11391 printf("Ap name is %s \n",buf);
11392 return 0;
11393 }
11394 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11395 {
11396 BOOL b = FALSE;
11397 BOOL *output_bool = &b;
11398 wifi_getRadioAutoChannelEnable(index,output_bool);
11399 printf("Channel enabled = %d \n",b);
11400 return 0;
11401 }
11402 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11403 {
11404 wifi_getApWpaEncryptionMode(index,buf);
11405 printf("encryption enabled = %s\n",buf);
11406 return 0;
11407 }
11408 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11409 {
11410 BOOL b = FALSE;
11411 BOOL *output_bool = &b;
11412 wifi_getApSsidAdvertisementEnable(index,output_bool);
11413 printf("advertisment enabled = %d\n",b);
11414 return 0;
11415 }
11416 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11417 {
11418 if(argc <= 3 )
11419 {
11420 printf("Insufficient arguments \n");
11421 exit(-1);
11422 }
11423
11424 char sta[20] = {'\0'};
11425 ULLONG handle= 0;
11426 strcpy(sta,argv[3]);
11427 mac_address_t st;
11428 mac_addr_aton(st,sta);
11429
11430 wifi_associated_dev_tid_stats_t tid_stats;
11431 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11432 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11433 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);
11434 }
11435
11436 if(strstr(argv[1], "getApEnable")!=NULL) {
11437 BOOL enable;
11438 ret=wifi_getApEnable(index, &enable);
11439 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11440 }
11441 else if(strstr(argv[1], "setApEnable")!=NULL) {
11442 BOOL enable = atoi(argv[3]);
11443 ret=wifi_setApEnable(index, enable);
11444 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11445 }
11446 else if(strstr(argv[1], "getApStatus")!=NULL) {
11447 char status[64];
11448 ret=wifi_getApStatus(index, status);
11449 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11450 }
11451 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11452 {
11453 wifi_getSSIDNameStatus(index,buf);
11454 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11455 return 0;
11456 }
11457 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11458 wifi_ssidTrafficStats2_t stats={0};
11459 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11460 printf("%s %d: returns %d\n", argv[1], index, ret);
11461 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11462 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11463 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11464 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11465 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11466 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11467 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11468 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11469 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11470 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11471 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11472 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11473 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11474 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11475 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11476 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11477 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11478 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11479 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11480 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11481 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11482 }
11483 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11484 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11485 UINT array_size=0;
11486 UINT i=0;
11487 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11488 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11489 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11490 printf(" neighbor %d:\n", i);
11491 printf(" ap_SSID =%s\n", pt->ap_SSID);
11492 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11493 printf(" ap_Mode =%s\n", pt->ap_Mode);
11494 printf(" ap_Channel =%d\n", pt->ap_Channel);
11495 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11496 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11497 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11498 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11499 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11500 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11501 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11502 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11503 printf(" ap_Noise =%d\n", pt->ap_Noise);
11504 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11505 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11506 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11507 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11508 }
11509 if(neighbor_ap_array)
11510 free(neighbor_ap_array); //make sure to free the list
11511 }
11512 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11513 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11514 UINT array_size=0;
11515 UINT i=0;
11516 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11517 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11518 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11519 printf(" associated_dev %d:\n", i);
11520 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11521 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11522 printf(" cli_SNR =%d\n", pt->cli_SNR);
11523 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11524 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11525 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11526 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11527 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11528 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11529 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11530 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11531 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11532 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11533 }
11534 if(associated_dev_array)
11535 free(associated_dev_array); //make sure to free the list
11536 }
11537
11538 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11539 {
11540#define MAX_ARRAY_SIZE 64
11541 int i, array_size;
11542 char *p, *ch_str;
11543 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11544
11545 if(argc != 5)
11546 {
11547 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11548 exit(-1);
11549 }
11550 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11551
11552 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11553 {
11554 strtok_r(ch_str, ",", &p);
11555 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11556 }
11557 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11558 if(!array_size)
11559 array_size=1;//Need to print current channel statistics
11560 for(i=0; i<array_size; i++)
11561 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11562 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11563 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11564 input_output_channelStats_array[i].ch_number,\
11565 input_output_channelStats_array[i].ch_noise,\
11566 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11567 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11568 input_output_channelStats_array[i].ch_utilization_busy,\
11569 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11570 input_output_channelStats_array[i].ch_utilization_total);
11571 }
11572
11573 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11574 {
11575 if(argc <= 3 )
11576 {
11577 printf("Insufficient arguments \n");
11578 exit(-1);
11579 }
11580 char mac_addr[20] = {'\0'};
11581 wifi_device_t output_struct;
11582 int dev_index = atoi(argv[3]);
11583
11584 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11585 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11586 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);
11587 }
11588
11589 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11590 {
11591 if (argc <= 3)
11592 {
11593 printf("Insufficient arguments\n");
11594 exit(-1);
11595 }
11596 char args[256];
11597 wifi_NeighborReport_t *neighborReports;
11598
11599 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11600 if (!neighborReports)
11601 {
11602 printf("Failed to allocate memory");
11603 exit(-1);
11604 }
11605
11606 for (int i = 3; i < argc; ++i)
11607 {
11608 char *val;
11609 int j = 0;
11610 memset(args, 0, sizeof(args));
11611 strncpy(args, argv[i], sizeof(args));
11612 val = strtok(args, ";");
11613 while (val != NULL)
11614 {
11615 if (j == 0)
11616 {
11617 mac_addr_aton(neighborReports[i - 3].bssid, val);
11618 } else if (j == 1)
11619 {
11620 neighborReports[i - 3].info = strtol(val, NULL, 16);
11621 } else if (j == 2)
11622 {
11623 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11624 } else if (j == 3)
11625 {
11626 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11627 } else if (j == 4)
11628 {
11629 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11630 } else {
11631 printf("Insufficient arguments]n\n");
11632 exit(-1);
11633 }
11634 val = strtok(NULL, ";");
11635 j++;
11636 }
11637 }
11638
11639 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11640 if (ret != RETURN_OK)
11641 {
11642 printf("wifi_setNeighborReports ret = %d", ret);
11643 exit(-1);
11644 }
11645 }
11646 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11647 {
11648 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11649 printf("%s.\n", buf);
11650 else
11651 printf("Error returned\n");
11652 }
11653 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11654 {
11655 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11656 printf("%s.\n", buf);
11657 else
11658 printf("Error returned\n");
11659 }
11660 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11661 {
11662 if (argc <= 2)
11663 {
11664 printf("Insufficient arguments\n");
11665 exit(-1);
11666 }
11667 char buf[64]= {'\0'};
11668 wifi_getRadioOperatingChannelBandwidth(index,buf);
11669 printf("Current bandwidth is %s \n",buf);
11670 return 0;
11671 }
11672 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11673 {
11674 if (argc <= 5)
11675 {
11676 printf("Insufficient arguments\n");
11677 exit(-1);
11678 }
11679 UINT channel = atoi(argv[3]);
11680 UINT width = atoi(argv[4]);
11681 UINT beacon = atoi(argv[5]);
11682 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11683 printf("Result = %d", ret);
11684 }
11685
11686 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11687 return 0;
11688}
11689
11690#endif
11691
11692#ifdef WIFI_HAL_VERSION_3
11693
developer1e5aa162022-09-13 16:06:24 +080011694INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11695{
11696 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11697 if (bitMap & WIFI_BITRATE_1MBPS)
11698 strcat(BasicRate, "1,");
11699 if (bitMap & WIFI_BITRATE_2MBPS)
11700 strcat(BasicRate, "2,");
11701 if (bitMap & WIFI_BITRATE_5_5MBPS)
11702 strcat(BasicRate, "5.5,");
11703 if (bitMap & WIFI_BITRATE_6MBPS)
11704 strcat(BasicRate, "6,");
11705 if (bitMap & WIFI_BITRATE_9MBPS)
11706 strcat(BasicRate, "9,");
11707 if (bitMap & WIFI_BITRATE_11MBPS)
11708 strcat(BasicRate, "11,");
11709 if (bitMap & WIFI_BITRATE_12MBPS)
11710 strcat(BasicRate, "12,");
11711 if (bitMap & WIFI_BITRATE_18MBPS)
11712 strcat(BasicRate, "18,");
11713 if (bitMap & WIFI_BITRATE_24MBPS)
11714 strcat(BasicRate, "24,");
11715 if (bitMap & WIFI_BITRATE_36MBPS)
11716 strcat(BasicRate, "36,");
11717 if (bitMap & WIFI_BITRATE_48MBPS)
11718 strcat(BasicRate, "48,");
11719 if (bitMap & WIFI_BITRATE_54MBPS)
11720 strcat(BasicRate, "54,");
11721 if (strlen(BasicRate) != 0) // remove last comma
11722 BasicRate[strlen(BasicRate) - 1] = '\0';
11723 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11724 return RETURN_OK;
11725}
11726
11727INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11728{
11729 UINT BitMap = 0;
11730 char *rate;
11731
11732 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11733 rate = strtok(BasicRatesList, ",");
11734 while(rate != NULL)
11735 {
11736 if (strcmp(rate, "1") == 0)
11737 BitMap |= WIFI_BITRATE_1MBPS;
11738 else if (strcmp(rate, "2") == 0)
11739 BitMap |= WIFI_BITRATE_2MBPS;
11740 else if (strcmp(rate, "5.5") == 0)
11741 BitMap |= WIFI_BITRATE_5_5MBPS;
11742 else if (strcmp(rate, "6") == 0)
11743 BitMap |= WIFI_BITRATE_6MBPS;
11744 else if (strcmp(rate, "9") == 0)
11745 BitMap |= WIFI_BITRATE_9MBPS;
11746 else if (strcmp(rate, "11") == 0)
11747 BitMap |= WIFI_BITRATE_11MBPS;
11748 else if (strcmp(rate, "12") == 0)
11749 BitMap |= WIFI_BITRATE_12MBPS;
11750 else if (strcmp(rate, "18") == 0)
11751 BitMap |= WIFI_BITRATE_18MBPS;
11752 else if (strcmp(rate, "24") == 0)
11753 BitMap |= WIFI_BITRATE_24MBPS;
11754 else if (strcmp(rate, "36") == 0)
11755 BitMap |= WIFI_BITRATE_36MBPS;
11756 else if (strcmp(rate, "48") == 0)
11757 BitMap |= WIFI_BITRATE_48MBPS;
11758 else if (strcmp(rate, "54") == 0)
11759 BitMap |= WIFI_BITRATE_54MBPS;
11760 rate = strtok(NULL, ",");
11761 }
11762 *basicRateBitMap = BitMap;
11763 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11764 return RETURN_OK;
11765}
11766
11767// 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 +080011768INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11769{
developer1e5aa162022-09-13 16:06:24 +080011770 char buf[128] = {0};
11771 char cmd[128] = {0};
11772 char config_file[64] = {0};
11773 int bandwidth;
developer517a9792022-10-05 19:37:42 +080011774 int set_mode = 0;
developer1e5aa162022-09-13 16:06:24 +080011775 wifi_radio_operationParam_t current_param;
11776
11777 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11778
11779 multiple_set = TRUE;
11780 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11781 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11782 return RETURN_ERR;
11783 }
11784 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11785 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11786 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11787 return RETURN_ERR;
11788 }
11789 }
developer5884e982022-10-06 10:52:50 +080011790
11791 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11792 bandwidth = 20;
11793 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11794 bandwidth = 40;
11795 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11796 bandwidth = 80;
11797 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11798 bandwidth = 160;
11799 if (operationParam->autoChannelEnabled){
11800 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11801 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11802 return RETURN_ERR;
11803 }
11804 }else{
developer1e5aa162022-09-13 16:06:24 +080011805 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11806 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11807 return RETURN_ERR;
11808 }
11809 }
developer5884e982022-10-06 10:52:50 +080011810
developer1e5aa162022-09-13 16:06:24 +080011811 if (current_param.variant != operationParam->variant) {
11812 // Two different definition bit map, so need to check every bit.
11813 if (operationParam->variant & WIFI_80211_VARIANT_A)
11814 set_mode |= WIFI_MODE_A;
11815 if (operationParam->variant & WIFI_80211_VARIANT_B)
11816 set_mode |= WIFI_MODE_B;
11817 if (operationParam->variant & WIFI_80211_VARIANT_G)
11818 set_mode |= WIFI_MODE_G;
11819 if (operationParam->variant & WIFI_80211_VARIANT_N)
11820 set_mode |= WIFI_MODE_N;
11821 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11822 set_mode |= WIFI_MODE_AC;
11823 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11824 set_mode |= WIFI_MODE_AX;
11825 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11826 memset(buf, 0, sizeof(buf));
11827 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11828 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11829 return RETURN_ERR;
11830 }
11831 }
11832 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11833 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11834 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11835 return RETURN_ERR;
11836 }
11837 }
11838 if (current_param.beaconInterval != operationParam->beaconInterval) {
11839 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11840 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11841 return RETURN_ERR;
11842 }
11843 }
11844 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11845 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11846 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11847 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11848 return RETURN_ERR;
11849 }
11850 }
11851 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11852 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11853 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11854 return RETURN_ERR;
11855 }
11856 }
11857 if (current_param.guardInterval != operationParam->guardInterval) {
11858 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11859 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11860 return RETURN_ERR;
11861 }
11862 }
11863 if (current_param.transmitPower != operationParam->transmitPower) {
11864 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11865 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11866 return RETURN_ERR;
11867 }
11868 }
11869 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11870 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11871 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11872 return RETURN_ERR;
11873 }
11874 }
11875 if (current_param.obssCoex != operationParam->obssCoex) {
11876 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11877 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11878 return RETURN_ERR;
11879 }
11880 }
11881 if (current_param.stbcEnable != operationParam->stbcEnable) {
11882 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11883 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11884 return RETURN_ERR;
11885 }
11886 }
11887 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11888 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11889 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11890 return RETURN_ERR;
11891 }
11892 }
11893
11894 // if enable is true, then restart the radio
11895 wifi_setRadioEnable(index, FALSE);
11896 if (operationParam->enable == TRUE)
11897 wifi_setRadioEnable(index, TRUE);
11898 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11899
developer06a01d92022-09-07 16:32:39 +080011900 return RETURN_OK;
11901}
11902
11903INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11904{
developer1e5aa162022-09-13 16:06:24 +080011905 char band[64] = {0};
11906 char buf[256] = {0};
11907 char config_file[64] = {0};
11908 char cmd[128] = {0};
11909 int ret = RETURN_ERR;
11910 int mode = 0;
11911 ULONG channel = 0;
11912 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011913
11914 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11915 printf("Entering %s index = %d\n", __func__, (int)index);
11916
developer1e5aa162022-09-13 16:06:24 +080011917 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11918 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11919 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011920 {
developer1e5aa162022-09-13 16:06:24 +080011921 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011922 return RETURN_ERR;
11923 }
11924 operationParam->enable = enabled;
11925
11926 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011927 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011928 {
developer1e5aa162022-09-13 16:06:24 +080011929 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011930 return RETURN_ERR;
11931 }
11932
11933 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011934 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011935 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011936 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011937 else if (!strcmp(band, "6GHz"))
11938 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011939 else
11940 {
developer1e5aa162022-09-13 16:06:24 +080011941 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011942 band);
11943 }
11944
developer1e5aa162022-09-13 16:06:24 +080011945 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11946 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11947 operationParam->channel = 0;
11948 operationParam->autoChannelEnabled = TRUE;
11949 } else {
11950 operationParam->channel = strtol(buf, NULL, 10);
11951 operationParam->autoChannelEnabled = FALSE;
11952 }
11953
developer06a01d92022-09-07 16:32:39 +080011954 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011955 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11956 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11957 return RETURN_ERR;
11958 }
developer06a01d92022-09-07 16:32:39 +080011959 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11960 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11961 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer87d5a782022-10-07 13:23:27 +080011962 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11963 else if (!strcmp(buf, "80+80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011964 else
11965 {
developer1e5aa162022-09-13 16:06:24 +080011966 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11967 return false;
developer06a01d92022-09-07 16:32:39 +080011968 }
11969
developer1e5aa162022-09-13 16:06:24 +080011970 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11971 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11972 return RETURN_ERR;
11973 }
11974 // Two different definition bit map, so need to check every bit.
11975 if (mode & WIFI_MODE_A)
11976 operationParam->variant |= WIFI_80211_VARIANT_A;
11977 if (mode & WIFI_MODE_B)
11978 operationParam->variant |= WIFI_80211_VARIANT_B;
11979 if (mode & WIFI_MODE_G)
11980 operationParam->variant |= WIFI_80211_VARIANT_G;
11981 if (mode & WIFI_MODE_N)
11982 operationParam->variant |= WIFI_80211_VARIANT_N;
11983 if (mode & WIFI_MODE_AC)
11984 operationParam->variant |= WIFI_80211_VARIANT_AC;
11985 if (mode & WIFI_MODE_AX)
11986 operationParam->variant |= WIFI_80211_VARIANT_AX;
11987 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11988 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11989 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011990 }
developer1e5aa162022-09-13 16:06:24 +080011991 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11992 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11993 return RETURN_ERR;
11994 }
11995 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11996 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11997 return RETURN_ERR;
11998 }
developer06a01d92022-09-07 16:32:39 +080011999
developer1e5aa162022-09-13 16:06:24 +080012000 memset(buf, 0, sizeof(buf));
12001 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12002 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12003 return RETURN_ERR;
12004 }
12005 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12006
12007 memset(buf, 0, sizeof(buf));
12008 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12009 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12010 return RETURN_ERR;
12011 }
12012 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12013
12014 memset(buf, 0, sizeof(buf));
12015 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12016 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12017
12018 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12019 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12020 return RETURN_ERR;
12021 }
12022 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12023 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12024 return RETURN_ERR;
12025 }
12026
12027 memset(buf, 0, sizeof(buf));
12028 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12029 if (strcmp(buf, "-1") == 0) {
12030 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12031 operationParam->ctsProtection = FALSE;
12032 } else {
12033 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12034 operationParam->ctsProtection = TRUE;
12035 }
12036
12037 memset(buf, 0, sizeof(buf));
12038 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12039 if (strcmp(buf, "0") == 0)
12040 operationParam->obssCoex = FALSE;
12041 else
12042 operationParam->obssCoex = TRUE;
12043
12044 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12045 _syscmd(cmd, buf, sizeof(buf));
12046 if (strlen(buf) != 0)
12047 operationParam->stbcEnable = TRUE;
12048 else
12049 operationParam->stbcEnable = FALSE;
12050
12051 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12052 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12053 return RETURN_ERR;
12054 }
12055
12056 // Below value is hardcoded
12057
12058 operationParam->numSecondaryChannels = 0;
12059 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12060 operationParam->channelSecondary[i] = 0;
12061 }
12062 operationParam->csa_beacon_count = 15;
12063 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080012064
12065 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12066 return RETURN_OK;
12067}
12068
12069static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12070{
developerc086fb72022-10-04 10:18:22 +080012071 int max_radio_num = 0;
12072
12073 wifi_getMaxRadioNumber(&max_radio_num);
developer30423732022-12-01 16:17:49 +080012074 if (radioIndex >= max_radio_num) {
developerc086fb72022-10-04 10:18:22 +080012075 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12076 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012077 }
12078
developerc086fb72022-10-04 10:18:22 +080012079 return (arrayIndex * max_radio_num) + radioIndex;
12080}
developer06a01d92022-09-07 16:32:39 +080012081
developerc086fb72022-10-04 10:18:22 +080012082wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12083 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12084 return WIFI_BITRATE_1MBPS;
12085 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12086 return WIFI_BITRATE_2MBPS;
12087 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12088 return WIFI_BITRATE_5_5MBPS;
12089 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12090 return WIFI_BITRATE_6MBPS;
12091 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12092 return WIFI_BITRATE_9MBPS;
12093 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12094 return WIFI_BITRATE_11MBPS;
12095 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12096 return WIFI_BITRATE_12MBPS;
12097 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12098 return WIFI_BITRATE_18MBPS;
12099 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12100 return WIFI_BITRATE_24MBPS;
12101 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12102 return WIFI_BITRATE_36MBPS;
12103 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12104 return WIFI_BITRATE_48MBPS;
12105 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12106 return WIFI_BITRATE_54MBPS;
12107 return WIFI_BITRATE_DEFAULT;
developer06a01d92022-09-07 16:32:39 +080012108}
12109
developer1d57d002022-10-12 18:03:15 +080012110INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12111{
12112 if (beacon == WIFI_BITRATE_1MBPS)
12113 strcpy(beacon_str, "1Mbps");
12114 else if (beacon == WIFI_BITRATE_2MBPS)
12115 strcpy(beacon_str, "2Mbps");
12116 else if (beacon == WIFI_BITRATE_5_5MBPS)
12117 strcpy(beacon_str, "5.5Mbps");
12118 else if (beacon == WIFI_BITRATE_6MBPS)
12119 strcpy(beacon_str, "6Mbps");
12120 else if (beacon == WIFI_BITRATE_9MBPS)
12121 strcpy(beacon_str, "9Mbps");
12122 else if (beacon == WIFI_BITRATE_11MBPS)
12123 strcpy(beacon_str, "11Mbps");
12124 else if (beacon == WIFI_BITRATE_12MBPS)
12125 strcpy(beacon_str, "12Mbps");
12126 else if (beacon == WIFI_BITRATE_18MBPS)
12127 strcpy(beacon_str, "18Mbps");
12128 else if (beacon == WIFI_BITRATE_24MBPS)
12129 strcpy(beacon_str, "24Mbps");
12130 else if (beacon == WIFI_BITRATE_36MBPS)
12131 strcpy(beacon_str, "36Mbps");
12132 else if (beacon == WIFI_BITRATE_48MBPS)
12133 strcpy(beacon_str, "48Mbps");
12134 else if (beacon == WIFI_BITRATE_54MBPS)
12135 strcpy(beacon_str, "54Mbps");
12136 return RETURN_OK;
12137}
12138
developer06a01d92022-09-07 16:32:39 +080012139INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12140{
developerc086fb72022-10-04 10:18:22 +080012141 INT mode = 0;
12142 INT ret = -1;
12143 INT output = 0;
12144 int i = 0;
12145 int vap_index = 0;
12146 BOOL enabled = FALSE;
12147 char buf[256] = {0};
developer30423732022-12-01 16:17:49 +080012148 wifi_vap_security_t security = {0};
developerc086fb72022-10-04 10:18:22 +080012149 map->num_vaps = 5; // Hardcoded
developer06a01d92022-09-07 16:32:39 +080012150
12151 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12152 printf("Entering %s index = %d\n", __func__, (int)index);
12153
developer06a01d92022-09-07 16:32:39 +080012154 for (i = 0; i < 5; i++)
12155 {
developerc086fb72022-10-04 10:18:22 +080012156 map->vap_array[i].radio_index = index;
12157
developer06a01d92022-09-07 16:32:39 +080012158 vap_index = array_index_to_vap_index(index, i);
12159 if (vap_index < 0)
developer06a01d92022-09-07 16:32:39 +080012160 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012161
developerc086fb72022-10-04 10:18:22 +080012162 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
developer06a01d92022-09-07 16:32:39 +080012163
12164 map->vap_array[i].vap_index = vap_index;
12165
12166 memset(buf, 0, sizeof(buf));
developerc086fb72022-10-04 10:18:22 +080012167 ret = wifi_getApName(vap_index, buf);
12168 if (ret != RETURN_OK) {
12169 printf("%s: wifi_getApName return error\n", __func__);
12170 return RETURN_ERR;
12171 }
12172 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12173
12174 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012175 ret = wifi_getSSIDName(vap_index, buf);
developerc086fb72022-10-04 10:18:22 +080012176 if (ret != RETURN_OK) {
developer1d57d002022-10-12 18:03:15 +080012177 printf("%s: wifi_getSSIDName return error\n", __func__);
developerc086fb72022-10-04 10:18:22 +080012178 return RETURN_ERR;
12179 }
12180 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 +080012181
12182 ret = wifi_getSSIDEnable(vap_index, &enabled);
developerc086fb72022-10-04 10:18:22 +080012183 if (ret != RETURN_OK) {
12184 printf("%s: wifi_getSSIDEnable return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012185 return RETURN_ERR;
12186 }
12187 map->vap_array[i].u.bss_info.enabled = enabled;
12188
developerc086fb72022-10-04 10:18:22 +080012189 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12190 if (ret != RETURN_OK) {
12191 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12192 return RETURN_ERR;
12193 }
developer06a01d92022-09-07 16:32:39 +080012194 map->vap_array[i].u.bss_info.showSsid = enabled;
developerc086fb72022-10-04 10:18:22 +080012195
12196 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12197 if (ret != RETURN_OK) {
12198 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12199 return RETURN_ERR;
12200 }
12201 map->vap_array[i].u.bss_info.isolation = enabled;
12202
12203 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12204 if (ret != RETURN_OK) {
12205 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12206 return RETURN_ERR;
12207 }
12208 map->vap_array[i].u.bss_info.bssMaxSta = output;
12209
12210 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12211 if (ret != RETURN_OK) {
12212 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12213 return RETURN_ERR;
12214 }
12215 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012216
developerc086fb72022-10-04 10:18:22 +080012217 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12218 if (ret != RETURN_OK) {
12219 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12220 return RETURN_ERR;
12221 }
12222 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
developer06a01d92022-09-07 16:32:39 +080012223
developerc086fb72022-10-04 10:18:22 +080012224 ret = wifi_getApSecurity(vap_index, &security);
12225 if (ret != RETURN_OK) {
12226 printf("%s: wifi_getApSecurity return error\n", __func__);
12227 return RETURN_ERR;
12228 }
12229 map->vap_array[i].u.bss_info.security = security;
developer06a01d92022-09-07 16:32:39 +080012230
developerc086fb72022-10-04 10:18:22 +080012231 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12232 if (ret != RETURN_OK) {
12233 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12234 return RETURN_ERR;
12235 }
12236 if (mode == 0)
12237 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12238 else
12239 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12240 if (mode == 1)
12241 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12242 else if (mode == 2)
12243 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
developer06a01d92022-09-07 16:32:39 +080012244
developerc086fb72022-10-04 10:18:22 +080012245 ret = wifi_getApWmmEnable(vap_index, &enabled);
12246 if (ret != RETURN_OK) {
12247 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12248 return RETURN_ERR;
12249 }
12250 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012251
developerc086fb72022-10-04 10:18:22 +080012252 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12253 if (ret != RETURN_OK) {
12254 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
developer06a01d92022-09-07 16:32:39 +080012255 return RETURN_ERR;
12256 }
developerc086fb72022-10-04 10:18:22 +080012257 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
developer06a01d92022-09-07 16:32:39 +080012258
12259 memset(buf, 0, sizeof(buf));
developer1d57d002022-10-12 18:03:15 +080012260 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
developerc086fb72022-10-04 10:18:22 +080012261 if (ret != RETURN_OK) {
12262 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12263 return RETURN_ERR;
12264 }
12265 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
developer06a01d92022-09-07 16:32:39 +080012266
developerc086fb72022-10-04 10:18:22 +080012267 memset(buf, 0, sizeof(buf));
12268 ret = wifi_getBaseBSSID(vap_index, buf);
12269 if (ret != RETURN_OK) {
12270 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12271 return RETURN_ERR;
12272 }
12273 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12274 &map->vap_array[i].u.bss_info.bssid[0],
12275 &map->vap_array[i].u.bss_info.bssid[1],
12276 &map->vap_array[i].u.bss_info.bssid[2],
12277 &map->vap_array[i].u.bss_info.bssid[3],
12278 &map->vap_array[i].u.bss_info.bssid[4],
12279 &map->vap_array[i].u.bss_info.bssid[5]);
developer1d57d002022-10-12 18:03:15 +080012280 // 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]);
12281
12282 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12283 if (ret != RETURN_OK) {
12284 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12285 return RETURN_ERR;
12286 }
12287 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
developer06a01d92022-09-07 16:32:39 +080012288
developerc086fb72022-10-04 10:18:22 +080012289 // TODO: wps, noack
developer06a01d92022-09-07 16:32:39 +080012290 }
12291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12292 return RETURN_OK;
12293}
12294
developer431128d2022-12-16 15:30:41 +080012295void checkVapStatus(int apIndex, bool *enable)
12296{
12297 char if_name[16] = {0};
12298 char cmd[128] = {0};
12299 char buf[128] = {0};
12300
12301 *enable = FALSE;
12302 if (GetInterfaceName(apIndex, if_name) != RETURN_OK)
12303 return;
12304
12305 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12306 _syscmd(cmd, buf, sizeof(buf));
12307 if (strlen(buf) > 0)
12308 *enable = TRUE;
12309 return;
12310}
12311
developerd946fd62022-12-08 18:03:28 +080012312static int prepareInterface(UINT apIndex, char *new_interface)
12313{
12314 char cur_interface[16] = {0};
12315 char config_file[128] = {0};
12316 char cmd[128] = {0};
12317 char buf[16] = {0};
12318 int max_radio_num = 0;
12319 int radioIndex = -1;
12320 int phyIndex = -1;
12321
12322 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12323 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12324
12325 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12326 wifi_getMaxRadioNumber(&max_radio_num);
12327 radioIndex = apIndex % max_radio_num;
12328 phyIndex = radio_index_to_phy(radioIndex);
12329 // disable and del old interface, then add new interface
12330 wifi_setApEnable(apIndex, FALSE);
developer431128d2022-12-16 15:30:41 +080012331 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 +080012332 _syscmd(cmd, buf, sizeof(buf));
12333 }
developer431128d2022-12-16 15:30:41 +080012334 // update the vap status file
12335 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12336 _syscmd(cmd, buf, sizeof(buf));
developerd946fd62022-12-08 18:03:28 +080012337 return RETURN_OK;
12338}
12339
developer06a01d92022-09-07 16:32:39 +080012340INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12341{
developerd946fd62022-12-08 18:03:28 +080012342 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080012343 unsigned int i;
12344 wifi_vap_info_t *vap_info = NULL;
12345 int acl_mode;
developer1d57d002022-10-12 18:03:15 +080012346 int ret = 0;
developer06a01d92022-09-07 16:32:39 +080012347 char *sec_str = NULL;
developer1d57d002022-10-12 18:03:15 +080012348 char buf[256] = {0};
12349 char cmd[128] = {0};
12350 char config_file[64] = {0};
12351 char bssid[32] = {0};
12352 char psk_file[64] = {0};
developer431128d2022-12-16 15:30:41 +080012353 bool enable = FALSE;
developer06a01d92022-09-07 16:32:39 +080012354
12355 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12356 printf("Entering %s index = %d\n", __func__, (int)index);
12357 for (i = 0; i < map->num_vaps; i++)
12358 {
developer1d57d002022-10-12 18:03:15 +080012359 multiple_set = TRUE;
developer06a01d92022-09-07 16:32:39 +080012360 vap_info = &map->vap_array[i];
developer431128d2022-12-16 15:30:41 +080012361
12362 // Check vap status file to enable multiple ap if the system boot.
12363 checkVapStatus(vap_info->vap_index, &enable);
12364 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
developer1d57d002022-10-12 18:03:15 +080012365 continue;
developer06a01d92022-09-07 16:32:39 +080012366
developer1d57d002022-10-12 18:03:15 +080012367 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12368
developer431128d2022-12-16 15:30:41 +080012369 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12370 enable = FALSE;
12371
12372 // multi-ap first up need to copy current radio config
12373 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
developer1d57d002022-10-12 18:03:15 +080012374 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12375 _syscmd(cmd, buf, sizeof(buf));
developer431128d2022-12-16 15:30:41 +080012376 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12377 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12378 } else {
12379 // Check whether the interface name is valid or this ap change it.
12380 int apIndex = -1;
12381 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12382 if (apIndex != -1 && apIndex != vap_info->vap_index)
12383 continue;
12384 prepareInterface(vap_info->vap_index, vap_info->vap_name);
developer06a01d92022-09-07 16:32:39 +080012385 }
developer06a01d92022-09-07 16:32:39 +080012386
developer1d57d002022-10-12 18:03:15 +080012387 struct params params[3];
developer1d57d002022-10-12 18:03:15 +080012388 params[0].name = "interface";
12389 params[0].value = vap_info->vap_name;
12390 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12391 params[1].name = "bssid";
12392 params[1].value = bssid;
developer431128d2022-12-16 15:30:41 +080012393 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
developer1d57d002022-10-12 18:03:15 +080012394 params[2].name = "wpa_psk_file";
12395 params[2].value = psk_file;
12396
12397 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12398 wifi_hostapdWrite(config_file, params, 3);
12399
12400 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12401 _syscmd(cmd, buf, sizeof(buf));
12402
12403 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12404 if (ret != RETURN_OK) {
12405 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12406 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012407 }
developer1d57d002022-10-12 18:03:15 +080012408
12409 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12410 if (ret != RETURN_OK) {
12411 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12412 return RETURN_ERR;
12413 }
12414
12415 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12416 if (ret != RETURN_OK) {
12417 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12418 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080012419 }
12420
developer1d57d002022-10-12 18:03:15 +080012421 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12422 if (ret != RETURN_OK) {
12423 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices 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_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12428 if (ret != RETURN_OK) {
12429 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12430 return RETURN_ERR;
12431 }
developer06a01d92022-09-07 16:32:39 +080012432
developer1d57d002022-10-12 18:03:15 +080012433 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12434 if (ret != RETURN_OK) {
12435 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12436 return RETURN_ERR;
12437 }
12438
developer804c64f2022-10-19 13:54:40 +080012439 if (vap_info->u.bss_info.mac_filter_enable == false){
developer1d57d002022-10-12 18:03:15 +080012440 acl_mode = 0;
developer804c64f2022-10-19 13:54:40 +080012441 }else {
12442 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
developer1d57d002022-10-12 18:03:15 +080012443 acl_mode = 2;
developer804c64f2022-10-19 13:54:40 +080012444 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12445 _syscmd(cmd, buf, sizeof(buf));
12446 }else{
developer1d57d002022-10-12 18:03:15 +080012447 acl_mode = 1;
developer804c64f2022-10-19 13:54:40 +080012448 }
developer1d57d002022-10-12 18:03:15 +080012449 }
12450
12451 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12452 if (ret != RETURN_OK) {
12453 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12454 return RETURN_ERR;
12455 }
12456
12457 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12458 if (ret != RETURN_OK) {
12459 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12460 return RETURN_ERR;
12461 }
12462
12463 memset(buf, 0, sizeof(buf));
12464 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12465 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12466 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12467 if (ret != RETURN_OK) {
12468 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12469 return RETURN_ERR;
12470 }
12471
12472 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12473 if (ret != RETURN_OK) {
12474 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12475 return RETURN_ERR;
12476 }
12477
12478 wifi_setApEnable(vap_info->vap_index, TRUE);
12479 multiple_set = FALSE;
12480
12481 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12482 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12483 if (ret != RETURN_OK) {
12484 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12485 return RETURN_ERR;
12486 }
12487
12488 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12489 if (ret != RETURN_OK) {
12490 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12491 return RETURN_ERR;
12492 }
developer06a01d92022-09-07 16:32:39 +080012493
developer1d57d002022-10-12 18:03:15 +080012494 // TODO mgmtPowerControl, interworking, wps
developer06a01d92022-09-07 16:32:39 +080012495 }
12496 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12497 return RETURN_OK;
12498}
12499
12500int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12501{
12502 char *token, *next;
12503 const char s[2] = ",";
12504 int count =0;
12505
12506 /* get the first token */
12507 token = strtok_r(pchannels, s, &next);
12508
12509 /* walk through other tokens */
12510 while( token != NULL && count < MAX_CHANNELS) {
12511 chlistptr->channels_list[count++] = atoi(token);
12512 token = strtok_r(NULL, s, &next);
12513 }
12514
12515 return count;
12516}
12517
12518static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12519{
12520 INT status;
12521 wifi_channels_list_t *chlistp;
12522 CHAR output_string[64];
12523 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080012524 wifi_band band;
developer033b37b2022-10-18 11:27:46 +080012525 int phyId = 0;
developer06a01d92022-09-07 16:32:39 +080012526
12527 if(rcap == NULL)
12528 {
12529 return RETURN_ERR;
12530 }
12531
12532 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080012533 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080012534
developer1e5aa162022-09-13 16:06:24 +080012535 if (band == band_2_4)
12536 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12537 else if (band == band_5)
12538 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12539 else if (band == band_6)
12540 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080012541
12542 chlistp = &(rcap->channel_list[0]);
12543 memset(pchannels, 0, sizeof(pchannels));
12544
12545 /* possible number of radio channels */
12546 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12547 {
12548 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12549 }
12550 /* Number of channels and list*/
12551 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12552
12553 /* autoChannelSupported */
12554 /* always ON with wifi_getRadioAutoChannelSupported */
12555 rcap->autoChannelSupported = TRUE;
12556
12557 /* DCSSupported */
12558 /* always ON with wifi_getRadioDCSSupported */
12559 rcap->DCSSupported = TRUE;
12560
12561 /* zeroDFSSupported - TBD */
12562 rcap->zeroDFSSupported = FALSE;
12563
12564 /* Supported Country List*/
12565 memset(output_string, 0, sizeof(output_string));
12566 status = wifi_getRadioCountryCode(radioIndex, output_string);
12567 if( status != 0 ) {
12568 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12569 return RETURN_ERR;
12570 } else {
12571 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12572 }
12573 if(!strcmp(output_string,"US")){
12574 rcap->countrySupported[0] = wifi_countrycode_US;
12575 rcap->countrySupported[1] = wifi_countrycode_CA;
12576 } else if (!strcmp(output_string,"CA")) {
12577 rcap->countrySupported[0] = wifi_countrycode_CA;
12578 rcap->countrySupported[1] = wifi_countrycode_US;
12579 } else {
12580 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12581 }
12582
12583 rcap->numcountrySupported = 2;
12584
12585 /* csi */
12586 rcap->csi.maxDevices = 8;
12587 rcap->csi.soudingFrameSupported = TRUE;
12588
developer033b37b2022-10-18 11:27:46 +080012589 phyId = radio_index_to_phy(radioIndex);
12590 snprintf(rcap->ifaceName, 64, "%s%d", RADIO_PREFIX, phyId);
developer06a01d92022-09-07 16:32:39 +080012591
12592 /* channelWidth - all supported bandwidths */
12593 int i=0;
12594 rcap->channelWidth[i] = 0;
12595 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12596 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12597 WIFI_CHANNELBANDWIDTH_40MHZ);
12598
12599 }
developer1e5aa162022-09-13 16:06:24 +080012600 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080012601 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12602 WIFI_CHANNELBANDWIDTH_40MHZ |
12603 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12604 }
12605
12606
12607 /* mode - all supported variants */
12608 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12609 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012610 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 +080012611 }
12612 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080012613 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12614 }
12615 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12616 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080012617 }
12618 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12619 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12620
12621 /* supportedBitRate - all supported bitrates */
12622 rcap->supportedBitRate[i] = 0;
12623 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12624 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12625 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12626 }
developer1e5aa162022-09-13 16:06:24 +080012627 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080012628 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12629 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12630 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12631 }
12632
12633
12634 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12635 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12636 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12637 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12638 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12639 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12640 rcap->cipherSupported = 0;
12641 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12642 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12643
12644 return RETURN_OK;
12645}
12646
12647INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12648{
developer30423732022-12-01 16:17:49 +080012649 INT status = 0, radioIndex = 0;
12650 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +080012651 int iter = 0;
developer30423732022-12-01 16:17:49 +080012652 unsigned int j = 0;
12653 wifi_interface_name_idex_map_t *iface_info = NULL;
developer06a01d92022-09-07 16:32:39 +080012654
12655 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12656
12657 memset(cap, 0, sizeof(wifi_hal_capability_t));
12658
12659 /* version */
12660 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12661 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12662
12663 /* number of radios platform property */
12664 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
12665 _syscmd(cmd, output, sizeof(output));
developer804c64f2022-10-19 13:54:40 +080012666 cap->wifi_prop.numRadios = atoi(output) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS: atoi(output) ;
developer06a01d92022-09-07 16:32:39 +080012667
12668 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12669 {
12670 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12671 if (status != 0) {
12672 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12673 return RETURN_ERR;
12674 }
12675
12676 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12677 {
developer804c64f2022-10-19 13:54:40 +080012678 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
developer06a01d92022-09-07 16:32:39 +080012679 {
12680 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12681 return RETURN_ERR;
12682 }
12683 iface_info = &cap->wifi_prop.interface_map[iter];
12684 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12685 iface_info->rdk_radio_index = radioIndex;
12686 memset(output, 0, sizeof(output));
12687 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12688 {
12689 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12690 }
12691 // TODO: bridge name
12692 // TODO: vlan id
12693 // TODO: primary
12694 iface_info->index = array_index_to_vap_index(radioIndex, j);
12695 memset(output, 0, sizeof(output));
developer30423732022-12-01 16:17:49 +080012696 if (iface_info->index >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080012697 {
12698 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12699 }
12700 iter++;
12701 }
12702 }
12703
12704 cap->BandSteeringSupported = FALSE;
12705 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12706 return RETURN_OK;
12707}
12708
developer9df4e652022-10-11 11:27:38 +080012709INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12710{
12711 struct params h_config={0};
12712 char config_file[64] = {0};
12713
12714 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12715
12716 h_config.name = "okc";
12717 h_config.value = okc_enable?"1":"0";
12718
12719 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12720 wifi_hostapdWrite(config_file, &h_config, 1);
12721 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12722
12723 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12724 return RETURN_OK;
12725}
12726
12727INT wifi_setSAEMFP(int ap_index, BOOL enable)
12728{
12729 struct params h_config={0};
12730 char config_file[64] = {0};
12731 char buf[128] = {0};
12732
12733 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12734
12735 h_config.name = "sae_require_mfp";
12736 h_config.value = enable?"1":"0";
12737
12738 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12739 wifi_hostapdWrite(config_file, &h_config, 1);
12740 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12741
12742 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12743 return RETURN_OK;
12744}
12745
12746INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12747{
12748 struct params h_config={0};
12749 char config_file[64] = {0};
12750 char buf[128] = {0};
12751
12752 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12753
12754 h_config.name = "sae_pwe";
12755 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12756 h_config.value = buf;
12757
12758 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12759 wifi_hostapdWrite(config_file, &h_config, 1);
12760 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12761
12762 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12763 return RETURN_OK;
12764}
12765
12766INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12767{
12768 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12769 struct params h_config={0};
12770 char config_file[64] = {0};
12771
12772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12773
12774 h_config.name = "wpa_disable_eapol_key_retries";
12775 h_config.value = disable_EAPOL_retries?"1":"0";
12776
12777 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12778 wifi_hostapdWrite(config_file, &h_config, 1);
12779 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12780
12781 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12782 return RETURN_OK;
12783}
12784
developer06a01d92022-09-07 16:32:39 +080012785INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12786{
developer587c1b62022-09-27 15:58:59 +080012787 char buf[128] = {0};
12788 char config_file[128] = {0};
12789 char password[64] = {0};
12790 char mfp[32] = {0};
12791 char wpa_mode[32] = {0};
developer9df4e652022-10-11 11:27:38 +080012792 BOOL okc_enable = FALSE;
12793 BOOL sae_MFP = FALSE;
12794 BOOL disable_EAPOL_retries = TRUE;
12795 int sae_pwe = 0;
developer587c1b62022-09-27 15:58:59 +080012796 struct params params = {0};
developer9df4e652022-10-11 11:27:38 +080012797 wifi_band band = band_invalid;
developer587c1b62022-09-27 15:58:59 +080012798
12799 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12800
12801 multiple_set = TRUE;
12802 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12803 if (security->mode == wifi_security_mode_none) {
12804 strcpy(wpa_mode, "None");
12805 } else if (security->mode == wifi_security_mode_wpa_personal)
12806 strcpy(wpa_mode, "WPA-Personal");
12807 else if (security->mode == wifi_security_mode_wpa2_personal)
12808 strcpy(wpa_mode, "WPA2-Personal");
12809 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12810 strcpy(wpa_mode, "WPA-WPA2-Personal");
12811 else if (security->mode == wifi_security_mode_wpa_enterprise)
12812 strcpy(wpa_mode, "WPA-Enterprise");
12813 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12814 strcpy(wpa_mode, "WPA2-Enterprise");
12815 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12816 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012817 else if (security->mode == wifi_security_mode_wpa3_personal) {
developer587c1b62022-09-27 15:58:59 +080012818 strcpy(wpa_mode, "WPA3-Personal");
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_transition) {
developer4a359672022-10-13 15:30:46 +080012824 strcpy(wpa_mode, "WPA3-Personal-Transition");
developer9df4e652022-10-11 11:27:38 +080012825 okc_enable = TRUE;
12826 sae_MFP = TRUE;
12827 sae_pwe = 2;
12828 disable_EAPOL_retries = FALSE;
12829 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
developer587c1b62022-09-27 15:58:59 +080012830 strcpy(wpa_mode, "WPA3-Enterprise");
developer9df4e652022-10-11 11:27:38 +080012831 sae_MFP = TRUE;
12832 sae_pwe = 2;
12833 disable_EAPOL_retries = FALSE;
12834 }
12835
12836 band = wifi_index_to_band(ap_index);
12837 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12838 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12839 return RETURN_ERR;
12840 }
developer587c1b62022-09-27 15:58:59 +080012841
12842 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
developer9df4e652022-10-11 11:27:38 +080012843 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
developerc0830312022-10-13 13:22:36 +080012844 wifi_setSAEMFP(ap_index, sae_MFP);
12845 wifi_setSAEpwe(ap_index, sae_pwe);
developer9df4e652022-10-11 11:27:38 +080012846 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
developer587c1b62022-09-27 15:58:59 +080012847
developer9df4e652022-10-11 11:27:38 +080012848 if (security->mode != wifi_security_mode_none) {
12849 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12850 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12851 password[63] = '\0';
12852 wifi_setApSecurityKeyPassphrase(ap_index, password);
12853 }
12854 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12855 params.name = "sae_password";
12856 params.value = security->u.key.key;
12857 wifi_hostapdWrite(config_file, &params, 1);
12858 }
12859 }
developer587c1b62022-09-27 15:58:59 +080012860
12861 if (security->mode != wifi_security_mode_none) {
12862 memset(&params, 0, sizeof(params));
12863 params.name = "wpa_pairwise";
12864 if (security->encr == wifi_encryption_tkip)
12865 params.value = "TKIP";
12866 else if (security->encr == wifi_encryption_aes)
12867 params.value = "CCMP";
12868 else if (security->encr == wifi_encryption_aes_tkip)
12869 params.value = "TKIP CCMP";
12870 wifi_hostapdWrite(config_file, &params, 1);
12871 }
12872
12873 if (security->mfp == wifi_mfp_cfg_disabled)
developerc0830312022-10-13 13:22:36 +080012874 strcpy(mfp, "Disabled");
developer587c1b62022-09-27 15:58:59 +080012875 else if (security->mfp == wifi_mfp_cfg_optional)
12876 strcpy(mfp, "Optional");
12877 else if (security->mfp == wifi_mfp_cfg_required)
12878 strcpy(mfp, "Required");
12879 wifi_setApSecurityMFPConfig(ap_index, mfp);
12880
12881 memset(&params, 0, sizeof(params));
12882 params.name = "transition_disable";
12883 if (security->wpa3_transition_disable == TRUE)
12884 params.value = "0x01";
12885 else
12886 params.value = "0x00";
12887 wifi_hostapdWrite(config_file, &params, 1);
12888
12889 memset(&params, 0, sizeof(params));
12890 params.name = "wpa_group_rekey";
12891 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12892 params.value = buf;
12893 wifi_hostapdWrite(config_file, &params, 1);
12894
12895 memset(&params, 0, sizeof(params));
12896 params.name = "wpa_strict_rekey";
12897 params.value = security->strict_rekey?"1":"0";
12898 wifi_hostapdWrite(config_file, &params, 1);
12899
12900 memset(&params, 0, sizeof(params));
12901 params.name = "wpa_pairwise_update_count";
12902 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12903 params.value = buf;
12904 wifi_hostapdWrite(config_file, &params, 1);
12905
12906 memset(&params, 0, sizeof(params));
12907 params.name = "disable_pmksa_caching";
12908 params.value = security->disable_pmksa_caching?"1":"0";
12909 wifi_hostapdWrite(config_file, &params, 1);
12910
12911 wifi_setApEnable(ap_index, FALSE);
12912 wifi_setApEnable(ap_index, TRUE);
12913
12914 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12915
developer06a01d92022-09-07 16:32:39 +080012916 return RETURN_OK;
12917}
12918
12919INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12920{
developer9df4e652022-10-11 11:27:38 +080012921 char buf[256] = {0};
developer587c1b62022-09-27 15:58:59 +080012922 char config_file[128] = {0};
12923 int disable = 0;
12924 // struct params params = {0};
12925
12926 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12927 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12928 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12929 security->mode = wifi_security_mode_none;
12930 if (strlen(buf) != 0) {
developer517a9792022-10-05 19:37:42 +080012931 if (!strcmp(buf, "WPA-Personal"))
developer587c1b62022-09-27 15:58:59 +080012932 security->mode = wifi_security_mode_wpa_personal;
developer517a9792022-10-05 19:37:42 +080012933 else if (!strcmp(buf, "WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012934 security->mode = wifi_security_mode_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012935 else if (!strcmp(buf, "WPA-WPA2-Personal"))
developer587c1b62022-09-27 15:58:59 +080012936 security->mode = wifi_security_mode_wpa_wpa2_personal;
developer517a9792022-10-05 19:37:42 +080012937 else if (!strcmp(buf, "WPA-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012938 security->mode = wifi_security_mode_wpa_enterprise;
developer517a9792022-10-05 19:37:42 +080012939 else if (!strcmp(buf, "WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012940 security->mode = wifi_security_mode_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012941 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012942 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
developer517a9792022-10-05 19:37:42 +080012943 else if (!strcmp(buf, "WPA3-Personal"))
developer587c1b62022-09-27 15:58:59 +080012944 security->mode = wifi_security_mode_wpa3_personal;
developer4a359672022-10-13 15:30:46 +080012945 else if (!strcmp(buf, "WPA3-Personal-Transition"))
developer587c1b62022-09-27 15:58:59 +080012946 security->mode = wifi_security_mode_wpa3_transition;
developer517a9792022-10-05 19:37:42 +080012947 else if (!strcmp(buf, "WPA3-Enterprise"))
developer587c1b62022-09-27 15:58:59 +080012948 security->mode = wifi_security_mode_wpa3_enterprise;
12949 }
12950
12951 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12952 if (security->mode == wifi_security_mode_none)
12953 security->encr = wifi_encryption_none;
12954 else {
12955 if (strcmp(buf, "TKIP") == 0)
12956 security->encr = wifi_encryption_tkip;
12957 else if (strcmp(buf, "CCMP") == 0)
12958 security->encr = wifi_encryption_aes;
12959 else
12960 security->encr = wifi_encryption_aes_tkip;
12961 }
12962
developer9df4e652022-10-11 11:27:38 +080012963 if (security->mode != wifi_encryption_none) {
12964 memset(buf, 0, sizeof(buf));
12965 // wpa3 can use one or both configs as password, so we check sae_password first.
12966 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
12967 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
12968 security->u.key.type = wifi_security_key_type_sae;
12969 } else {
12970 security->u.key.type = wifi_security_key_type_psk;
12971 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
12972 }
12973 strncpy(security->u.key.key, buf, sizeof(buf));
12974 security->u.key.key[255] = '\0';
12975 }
12976
developer587c1b62022-09-27 15:58:59 +080012977 memset(buf, 0, sizeof(buf));
12978 wifi_getApSecurityMFPConfig(ap_index, buf);
12979 if (strcmp(buf, "Disabled") == 0)
12980 security->mfp = wifi_mfp_cfg_disabled;
12981 else if (strcmp(buf, "Optional") == 0)
12982 security->mfp = wifi_mfp_cfg_optional;
12983 else if (strcmp(buf, "Required") == 0)
12984 security->mfp = wifi_mfp_cfg_required;
12985
12986 memset(buf, 0, sizeof(buf));
12987 security->wpa3_transition_disable = FALSE;
12988 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12989 disable = strtol(buf, NULL, 16);
12990 if (disable != 0)
12991 security->wpa3_transition_disable = TRUE;
12992
12993 memset(buf, 0, sizeof(buf));
12994 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12995 if (strlen(buf) == 0)
12996 security->rekey_interval = 86400;
12997 else
12998 security->rekey_interval = strtol(buf, NULL, 10);
12999
13000 memset(buf, 0, sizeof(buf));
13001 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13002 if (strlen(buf) == 0)
13003 security->strict_rekey = 1;
13004 else
13005 security->strict_rekey = strtol(buf, NULL, 10);
13006
13007 memset(buf, 0, sizeof(buf));
13008 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13009 if (strlen(buf) == 0)
13010 security->eapol_key_retries = 4;
13011 else
13012 security->eapol_key_retries = strtol(buf, NULL, 10);
13013
13014 memset(buf, 0, sizeof(buf));
13015 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13016 if (strlen(buf) == 0)
13017 security->disable_pmksa_caching = FALSE;
13018 else
13019 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13020
13021 /* TODO
13022 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13023 */
13024 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13025 security->eap_identity_req_timeout = 0;
13026 security->eap_identity_req_retries = 0;
13027 security->eap_req_timeout = 0;
13028 security->eap_req_retries = 0;
13029 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080013030 return RETURN_OK;
13031}
13032
13033#endif /* WIFI_HAL_VERSION_3 */
13034
13035#ifdef WIFI_HAL_VERSION_3_PHASE2
13036INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13037{
developerd946fd62022-12-08 18:03:28 +080013038 char interface_name[16] = {0};
developer13df9332022-09-27 16:53:22 +080013039 char cmd[128] = {0};
13040 char buf[128] = {0};
13041 char *mac_addr = NULL;
13042 BOOL status = FALSE;
13043 size_t len = 0;
13044
13045 if(ap_index > MAX_APS)
13046 return RETURN_ERR;
13047
13048 *output_numDevices = 0;
13049 wifi_getApEnable(ap_index, &status);
13050 if (status == FALSE)
13051 return RETURN_OK;
13052
developerd946fd62022-12-08 18:03:28 +080013053 if (GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13054 return RETURN_ERR;
13055 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
developer13df9332022-09-27 16:53:22 +080013056 _syscmd(cmd, buf, sizeof(buf));
13057
13058 mac_addr = strtok(buf, "\n");
13059 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13060 *output_numDevices = i + 1;
13061 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13062 addr_ptr = output_deviceMacAddressArray[i];
13063 mac_addr_aton(addr_ptr, mac_addr);
13064 mac_addr = strtok(NULL, "\n");
13065 }
13066
13067 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080013068}
13069#else
13070INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13071{
developerd946fd62022-12-08 18:03:28 +080013072 char interface_name[16] = {0};
developer06a01d92022-09-07 16:32:39 +080013073 char cmd[128];
13074 BOOL status = false;
13075
13076 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13077 return RETURN_ERR;
13078
13079 output_buf[0] = '\0';
13080
13081 wifi_getApEnable(ap_index,&status);
13082 if (!status)
13083 return RETURN_OK;
13084
developerd946fd62022-12-08 18:03:28 +080013085 if (GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13086 return RETURN_ERR;
13087 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
developer06a01d92022-09-07 16:32:39 +080013088 _syscmd(cmd, output_buf, output_buf_size);
13089
13090 return RETURN_OK;
13091}
13092#endif
developer2f513ab2022-09-13 14:26:06 +080013093
13094INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13095{
13096 char output[16]={'\0'};
13097 char config_file[MAX_BUF_SIZE] = {0};
13098
13099 if (!enable)
13100 return RETURN_ERR;
13101
13102 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13103 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13104
13105 if (strlen(output) == 0)
13106 *enable = FALSE;
13107 else if (strncmp(output, "1", 1) == 0)
13108 *enable = TRUE;
13109 else
13110 *enable = FALSE;
13111
13112 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13113 return RETURN_OK;
13114}
developer2d9c30f2022-09-13 15:06:14 +080013115
13116INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13117{
developer804c64f2022-10-19 13:54:40 +080013118 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
developer2d9c30f2022-09-13 15:06:14 +080013119 return RETURN_ERR;
13120 *output_enable=TRUE;
13121 return RETURN_OK;
13122}
developerfd7d2892022-09-13 16:44:53 +080013123
13124INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13125{
13126 char cmd[128] = {0};
13127 char buf[128] = {0};
13128 char line[128] = {0};
13129 size_t len = 0;
developerfd7d2892022-09-13 16:44:53 +080013130 FILE *f = NULL;
13131 int index = 0;
13132 int exp = 0;
13133 int mantissa = 0;
13134 int duration = 0;
13135 int radio_index = 0;
13136 int max_radio_num = 0;
13137 uint twt_wake_interval = 0;
developer033b37b2022-10-18 11:27:46 +080013138 int phyId = 0;
developerfd7d2892022-09-13 16:44:53 +080013139 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13140
13141 wifi_getMaxRadioNumber(&max_radio_num);
developer033b37b2022-10-18 11:27:46 +080013142
developerfd7d2892022-09-13 16:44:53 +080013143 radio_index = ap_index % max_radio_num;
developer033b37b2022-10-18 11:27:46 +080013144
13145 phyId = radio_index_to_phy(radio_index);
13146 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
developerfd7d2892022-09-13 16:44:53 +080013147 _syscmd(cmd, buf, sizeof(buf));
13148 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13149 if (*numSessionReturned > maxNumberSessions)
13150 *numSessionReturned = maxNumberSessions;
13151 else if (*numSessionReturned < 1) {
13152 *numSessionReturned = 0;
13153 return RETURN_OK;
13154 }
13155
developer033b37b2022-10-18 11:27:46 +080013156 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 +080013157 if ((f = popen(cmd, "r")) == NULL) {
13158 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13159 return RETURN_ERR;
13160 }
13161
13162 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
developer30423732022-12-01 16:17:49 +080013163 while((fgets(line, sizeof(line), f)) != NULL) {
developerfd7d2892022-09-13 16:44:53 +080013164 char *tmp = NULL;
13165 strcpy(buf, line);
13166 tmp = strtok(buf, " ");
13167 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13168 tmp = strtok(NULL, " ");
13169 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13170 tmp = strtok(NULL, " ");
13171 if (strstr(tmp, "t")) {
13172 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13173 }
13174 if (strstr(tmp, "a")) {
13175 twtSessions[index].twtParameters.operation.announced = TRUE;
13176 }
13177 tmp = strtok(NULL, " ");
13178 exp = strtol(tmp, NULL, 10);
13179 tmp = strtok(NULL, " ");
13180 mantissa = strtol(tmp, NULL, 10);
13181 tmp = strtok(NULL, " ");
13182 duration = strtol(tmp, NULL, 10);
13183
13184 // only implicit supported
13185 twtSessions[index].twtParameters.operation.implicit = TRUE;
13186 // only individual agreement supported
13187 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13188
13189 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13190 twt_wake_interval = mantissa * (1 << exp);
developer30423732022-12-01 16:17:49 +080013191 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
developerfd7d2892022-09-13 16:44:53 +080013192 // Overflow handling
13193 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13194 } else {
13195 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13196 }
13197 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13198 index++;
13199 }
13200
13201 pclose(f);
13202 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13203 return RETURN_OK;
13204}