blob: 94cf88232f699363ff3849ac63345335f075fd67 [file] [log] [blame]
developer72fb0bb2023-01-11 09:46:29 +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*/
37#define MTK_IMPL
38#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 256
67#define MAX_CMD_SIZE 256
68#define IF_NAME_SIZE 16
69#define CONFIG_PREFIX "/nvram/hostapd"
70#define ACL_PREFIX "/nvram/hostapd-acl"
71#define DENY_PREFIX "/nvram/hostapd-deny"
72//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
73#define SOCK_PREFIX "/var/run/hostapd/wifi"
74#define VAP_STATUS_FILE "/nvram/vap-status"
75#define ESSID_FILE "/tmp/essid"
76#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
77#define CHANNEL_STATS_FILE "/tmp/channel_stats"
78#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
79#define VLAN_FILE "/nvram/hostapd.vlan"
80#define PSK_FILE "/nvram/hostapd"
81#define MCS_FILE "/tmp/MCS"
82#define NOACK_MAP_FILE "/tmp/NoAckMap"
83
84#define BRIDGE_NAME "brlan0"
85
86/*
87 MAX_APS - Number of all AP available in system
88 2x Home AP
89 2x Backhaul AP
90 2x Guest AP
91 2x Secure Onboard AP
92 2x Service AP
93
94*/
95
96
97#define MAX_APS MAX_NUM_RADIOS*5
98#ifndef AP_PREFIX
99#define AP_PREFIX "wifi"
100#endif
101
102#ifndef RADIO_PREFIX
103#define RADIO_PREFIX "wlan"
104#endif
105
106#define MAX_ASSOCIATED_STA_NUM 2007
107
108//Uncomment to enable debug logs
109//#define WIFI_DEBUG
110
111#ifdef WIFI_DEBUG
112#define wifi_dbg_printf printf
113#define WIFI_ENTRY_EXIT_DEBUG printf
114#else
115#define wifi_dbg_printf(format, args...) printf("")
116#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
117#endif
118
119#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
120#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
121#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
122#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
123#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
124#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
125#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
126#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
127#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
128#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
129
130#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
131
132#define BW_FNAME "/nvram/bw_file.txt"
133
134#define PS_MAX_TID 16
135
136static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
137 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
138 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
139 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
140 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
141 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
142 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
143 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
144 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
145 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
147 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
148 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
150 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
152 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
153};
154
155typedef unsigned long long u64;
156
157/* Enum to define WiFi Bands */
158typedef enum
159{
160 band_invalid = -1,
161 band_2_4 = 0,
162 band_5 = 1,
163 band_6 = 2,
164} wifi_band;
165
166typedef enum {
167 WIFI_MODE_A = 0x01,
168 WIFI_MODE_B = 0x02,
169 WIFI_MODE_G = 0x04,
170 WIFI_MODE_N = 0x08,
171 WIFI_MODE_AC = 0x10,
172 WIFI_MODE_AX = 0x20,
173} wifi_ieee80211_Mode;
174
175#ifdef WIFI_HAL_VERSION_3
176
177// Return number of elements in array
178#ifndef ARRAY_SIZE
179#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
180#endif /* ARRAY_SIZE */
181
182#ifndef ARRAY_AND_SIZE
183#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
184#endif /* ARRAY_AND_SIZE */
185
186#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
187
188typedef struct {
189 int32_t value;
190 int32_t param;
191 intptr_t key;
192 intptr_t data;
193} wifi_secur_list;
194
195static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
196static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
197wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
198wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
199char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
200static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
201
202static wifi_secur_list map_security[] =
203{
204 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
205 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
206 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
207 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
208 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
209 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
210 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
216};
217
218wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
219{
220 wifi_secur_list *item;
221 int i;
222
223 for (item = list,i = 0;i < list_sz; item++, i++) {
224 if ((int)(item->key) == key) {
225 return item;
226 }
227 }
228
229 return NULL;
230}
231
232char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
233{
234 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
235
236 if (!item) {
237 return "";
238 }
239
240 return (char *)(item->data);
241}
242
243wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
244{
245 wifi_secur_list *item;
246 int i;
247
248 for (item = list,i = 0;i < list_sz; item++, i++) {
249 if (strcmp((char *)(item->data), str) == 0) {
250 return item;
251 }
252 }
253
254 return NULL;
255}
256#endif /* WIFI_HAL_VERSION_3 */
257
258#ifdef HAL_NETLINK_IMPL
259typedef struct {
260 int id;
261 struct nl_sock* socket;
262 struct nl_cb* cb;
263} Netlink;
264
265static int mac_addr_aton(unsigned char *mac_addr, char *arg)
266{
267 unsigned int mac_addr_int[6]={};
268 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);
269 mac_addr[0] = mac_addr_int[0];
270 mac_addr[1] = mac_addr_int[1];
271 mac_addr[2] = mac_addr_int[2];
272 mac_addr[3] = mac_addr_int[3];
273 mac_addr[4] = mac_addr_int[4];
274 mac_addr[5] = mac_addr_int[5];
275 return 0;
276}
277
278static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
279{
280 unsigned int mac_addr_int[6]={};
281 mac_addr_int[0] = arg[0];
282 mac_addr_int[1] = arg[1];
283 mac_addr_int[2] = arg[2];
284 mac_addr_int[3] = arg[3];
285 mac_addr_int[4] = arg[4];
286 mac_addr_int[5] = arg[5];
287 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]);
288 return;
289}
290
291static int ieee80211_frequency_to_channel(int freq)
292{
293 /* see 802.11-2007 17.3.8.3.2 and Annex J */
294 if (freq == 2484)
295 return 14;
296 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
297 else if (freq == 5935)
298 return 2;
299 else if (freq < 2484)
300 return (freq - 2407) / 5;
301 else if (freq >= 4910 && freq <= 4980)
302 return (freq - 4000) / 5;
303 else if (freq < 5950)
304 return (freq - 5000) / 5;
305 else if (freq <= 45000) /* DMG band lower limit */
306 /* see 802.11ax D6.1 27.3.23.2 */
307 return (freq - 5950) / 5;
308 else if (freq >= 58320 && freq <= 70200)
309 return (freq - 56160) / 2160;
310 else
311 return 0;
312}
313
314static int initSock80211(Netlink* nl) {
315 nl->socket = nl_socket_alloc();
316 if (!nl->socket) {
317 fprintf(stderr, "Failing to allocate the sock\n");
318 return -ENOMEM;
319 }
320
321 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
322
323 if (genl_connect(nl->socket)) {
324 fprintf(stderr, "Failed to connect\n");
325 nl_close(nl->socket);
326 nl_socket_free(nl->socket);
327 return -ENOLINK;
328 }
329
330 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
331 if (nl->id< 0) {
332 fprintf(stderr, "interface not found.\n");
333 nl_close(nl->socket);
334 nl_socket_free(nl->socket);
335 return -ENOENT;
336 }
337
338 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
339 if ((!nl->cb)) {
340 fprintf(stderr, "Failed to allocate netlink callback.\n");
341 nl_close(nl->socket);
342 nl_socket_free(nl->socket);
343 return ENOMEM;
344 }
345
346 return nl->id;
347}
348
349static int nlfree(Netlink *nl)
350{
351 nl_cb_put(nl->cb);
352 nl_close(nl->socket);
353 nl_socket_free(nl->socket);
354 return 0;
355}
356
357static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
358 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
359 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
360 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
361};
362
363static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
364};
365
366static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
367};
368
369typedef struct _wifi_channelStats_loc {
370 INT array_size;
371 INT ch_number;
372 BOOL ch_in_pool;
373 INT ch_noise;
374 BOOL ch_radar_noise;
375 INT ch_max_80211_rssi;
376 INT ch_non_80211_noise;
377 INT ch_utilization;
378 ULLONG ch_utilization_total;
379 ULLONG ch_utilization_busy;
380 ULLONG ch_utilization_busy_tx;
381 ULLONG ch_utilization_busy_rx;
382 ULLONG ch_utilization_busy_self;
383 ULLONG ch_utilization_busy_ext;
384} wifi_channelStats_t_loc;
385
386typedef struct wifi_device_info {
387 INT wifi_devIndex;
388 UCHAR wifi_devMacAddress[6];
389 CHAR wifi_devIPAddress[64];
390 BOOL wifi_devAssociatedDeviceAuthentiationState;
391 INT wifi_devSignalStrength;
392 INT wifi_devTxRate;
393 INT wifi_devRxRate;
394} wifi_device_info_t;
395
396#endif
397
398//For 5g Alias Interfaces
399static BOOL priv_flag = TRUE;
400static BOOL pub_flag = TRUE;
401static BOOL Radio_flag = TRUE;
402//wifi_setApBeaconRate(1, beaconRate);
403
404BOOL multiple_set = FALSE;
405
406struct params
407{
408 char * name;
409 char * value;
410};
411
412static int _syscmd(char *cmd, char *retBuf, int retBufSize)
413{
414 FILE *f;
415 char *ptr = retBuf;
416 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
417
418 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
419 if((f = popen(cmd, "r")) == NULL) {
420 fprintf(stderr,"\npopen %s error\n", cmd);
421 return RETURN_ERR;
422 }
423
424 while(!feof(f))
425 {
426 *ptr = 0;
427 if(bufSize>=128) {
428 bufbytes=128;
429 } else {
430 bufbytes=bufSize-1;
431 }
432
433 fgets(ptr,bufbytes,f);
434 readbytes=strlen(ptr);
435
436 if(!readbytes)
437 break;
438
439 bufSize-=readbytes;
440 ptr += readbytes;
441 }
442 cmd_ret = pclose(f);
443 retBuf[retBufSize-1]=0;
444 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
445
446 return cmd_ret >> 8;
447}
448
449INT radio_index_to_phy(int radioIndex)
450{
451 char cmd[128] = {0};
452 char buf[64] = {0};
453 int phyIndex = 0;
454 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
455 _syscmd(cmd, buf, sizeof(buf));
456
457 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
458 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
459 return RETURN_ERR;
460 }
461 sscanf(buf, "phy%d", &phyIndex);
462
463 return phyIndex;
464}
465
466INT wifi_getMaxRadioNumber(INT *max_radio_num)
467{
468 char cmd[64] = {0};
469 char buf[4] = {0};
470
471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
472
473 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
474 _syscmd(cmd, buf, sizeof(buf));
475 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
476
477 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
478
479 return RETURN_OK;
480}
481
482wifi_band wifi_index_to_band(int apIndex)
483{
484 char cmd[128] = {0};
485 char buf[64] = {0};
486 int nl80211_band = 0;
487 int i = 0;
488 int phyIndex = 0;
489 int radioIndex = 0;
490 int max_radio_num = 0;
491 wifi_band band = band_invalid;
492
493 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
494
495 wifi_getMaxRadioNumber(&max_radio_num);
496 radioIndex = apIndex % max_radio_num;
497 phyIndex = radio_index_to_phy(radioIndex);
498 while(i < 10){
499 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
500 _syscmd(cmd, buf, sizeof(buf));
501 nl80211_band = strtol(buf, NULL, 10);
502 if (nl80211_band == 1)
503 band = band_2_4;
504 else if (nl80211_band == 2)
505 band = band_5;
506 else if (nl80211_band == 4) // band == 3 is 60GHz
507 band = band_6;
508
509 if(band != band_invalid)
510 break;
511
512 i++;
513 sleep(1);
514 }
515
516 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
517 return band;
518}
519
520static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
521{
522 char cmd[MAX_CMD_SIZE]={'\0'};
523 char buf[MAX_BUF_SIZE]={'\0'};
524 int ret = 0;
525
526 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
527 ret = _syscmd(cmd, buf, sizeof(buf));
528 if ((ret != 0) && (strlen(buf) == 0))
529 return -1;
530 snprintf(output, output_size, "%s", buf);
531
532 return 0;
533}
534
535static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
536{
537 char cmd[MAX_CMD_SIZE]={'\0'};
538 char buf[MAX_BUF_SIZE]={'\0'};
539
540 for(int i=0;i<item_count;i++)
541 {
542 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
543 if (strlen(buf) == 0) //Insert
544 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
545 else //Update
546 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
547
548 if(_syscmd(cmd, buf, sizeof(buf)))
549 return -1;
550 }
551
552 return 0;
553}
554
555//For Getting Current Interface Name from corresponding hostapd configuration
556static int wifi_GetInterfaceName(int apIndex, char *interface_name)
557{
558 char config_file[128] = {0};
559
560 if (interface_name == NULL)
561 return RETURN_ERR;
562
563 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
564
565 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
566 wifi_hostapdRead(config_file, "interface", interface_name, 16);
567 if (strlen(interface_name) == 0)
568 return RETURN_ERR;
569
570 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
571 return RETURN_OK;
572}
573
574// wifi agent will call this function, do not change the parameter
575void GetInterfaceName(char *interface_name, char *conf_file)
576{
577 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
578 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
579 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
580}
581
582static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
583{
584 char interface_name[16] = {0};
585 if (multiple_set == TRUE)
586 return RETURN_OK;
587 char cmd[MAX_CMD_SIZE]="", output[32]="";
588 FILE *fp;
589 int i;
590 //NOTE RELOAD should be done in ApplySSIDSettings
591 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
592 return RETURN_ERR;
593 for(i=0; i<item_count; i++, list++)
594 {
595 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
596 if((fp = popen(cmd, "r"))==NULL)
597 {
598 perror("popen failed");
599 return -1;
600 }
601 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
602 {
603 pclose(fp);
604 perror("fgets failed");
605 return -1;
606 }
607 pclose(fp);
608 }
609 return 0;
610}
611
612static int wifi_reloadAp(int apIndex)
613{
614 char interface_name[16] = {0};
615 if (multiple_set == TRUE)
616 return RETURN_OK;
617 char cmd[MAX_CMD_SIZE]="";
618 char buf[MAX_BUF_SIZE]="";
619
620 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
621 return RETURN_ERR;
622 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
623 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
624 return RETURN_ERR;
625
626 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
627 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
628 return RETURN_ERR;
629
630 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
631 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
632 return RETURN_ERR;
633
634 return RETURN_OK;
635}
636
637INT File_Reading(CHAR *file, char *Value)
638{
639 FILE *fp = NULL;
640 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
641 int count = 0;
642
643 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
644 fp = popen(file,"r");
645 if(fp == NULL)
646 return RETURN_ERR;
647
648 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
649 {
650 for(count=0;buf[count]!='\n';count++)
651 copy_buf[count]=buf[count];
652 copy_buf[count]='\0';
653 }
654 strcpy(Value,copy_buf);
655 pclose(fp);
656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
657
658 return RETURN_OK;
659}
660
661void wifi_RestartHostapd_2G()
662{
663 int Public2GApIndex = 4;
664
665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
666 wifi_setApEnable(Public2GApIndex, FALSE);
667 wifi_setApEnable(Public2GApIndex, TRUE);
668 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
669}
670
671void wifi_RestartHostapd_5G()
672{
673 int Public5GApIndex = 5;
674
675 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
676 wifi_setApEnable(Public5GApIndex, FALSE);
677 wifi_setApEnable(Public5GApIndex, TRUE);
678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
679}
680
681void wifi_RestartPrivateWifi_2G()
682{
683 int PrivateApIndex = 0;
684
685 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
686 wifi_setApEnable(PrivateApIndex, FALSE);
687 wifi_setApEnable(PrivateApIndex, TRUE);
688 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
689}
690
691void wifi_RestartPrivateWifi_5G()
692{
693 int Private5GApIndex = 1;
694
695 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
696 wifi_setApEnable(Private5GApIndex, FALSE);
697 wifi_setApEnable(Private5GApIndex, TRUE);
698 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
699}
700
701static int writeBandWidth(int radioIndex,char *bw_value)
702{
703 char buf[MAX_BUF_SIZE];
704 char cmd[MAX_CMD_SIZE];
705
706 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
707 if(_syscmd(cmd, buf, sizeof(buf)))
708 {
709 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
710 _syscmd(cmd, buf, sizeof(buf));
711 return RETURN_OK;
712 }
713
714 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
715 _syscmd(cmd,buf,sizeof(buf));
716 return RETURN_OK;
717}
718
719static int readBandWidth(int radioIndex,char *bw_value)
720{
721 char buf[MAX_BUF_SIZE] = {0};
722 char cmd[MAX_CMD_SIZE] = {0};
723 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
724 _syscmd(cmd,buf,sizeof(buf));
725 if(NULL!=strstr(buf,"20MHz"))
726 {
727 strcpy(bw_value,"20MHz");
728 }
729 else if(NULL!=strstr(buf,"40MHz"))
730 {
731 strcpy(bw_value,"40MHz");
732 }
733 else if(NULL!=strstr(buf,"80MHz"))
734 {
735 strcpy(bw_value,"80MHz");
736 }
737 else
738 {
739 return RETURN_ERR;
740 }
741 return RETURN_OK;
742}
743
744// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
745INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
746{
747 struct params params={'\0'};
748 char config_file[MAX_BUF_SIZE] = {0};
749 char buf[MAX_BUF_SIZE] = {'\0'};
750
751 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
752 // Copy the numeric value
753 if (strlen (beaconRate) >= 5) {
754 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
755 buf[strlen(beaconRate) - 4] = '\0';
756 } else if (strlen(beaconRate) > 0)
757 strcpy(buf, beaconRate);
758 else
759 return RETURN_ERR;
760
761 params.name = "beacon_rate";
762 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
763 if (strncmp(buf, "5.5", 3) == 0) {
764 snprintf(buf, sizeof(buf), "55");
765 params.value = buf;
766 } else {
767 strcat(buf, "0");
768 params.value = buf;
769 }
770
771 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
772 wifi_hostapdWrite(config_file, &params, 1);
773 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
774 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
775
776 return RETURN_OK;
777}
778
779INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
780{
781 char config_file[128] = {'\0'};
782 char temp_output[128] = {'\0'};
783 char buf[128] = {'\0'};
784 char cmd[128] = {'\0'};
785 int rate = 0;
786 int phyId = 0;
787
788 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
789 if (NULL == beaconRate)
790 return RETURN_ERR;
791
792 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
793 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
794 phyId = radio_index_to_phy(radioIndex);
795 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
796 if(strlen(buf) > 0) {
797 if (strncmp(buf, "55", 2) == 0)
798 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
799 else {
800 rate = strtol(buf, NULL, 10)/10;
801 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
802 }
803 } else {
804 // config not set, so we would use lowest rate as default
805 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
806 _syscmd(cmd, buf, sizeof(buf));
807 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
808 }
809 strncpy(beaconRate, temp_output, sizeof(temp_output));
810 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
811
812 return RETURN_OK;
813}
814
815INT wifi_setLED(INT radioIndex, BOOL enable)
816{
817 return 0;
818}
819INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
820{
821 return RETURN_OK;
822}
823/**********************************************************************************
824 *
825 * Wifi Subsystem level function prototypes
826 *
827**********************************************************************************/
828//---------------------------------------------------------------------------------------------------
829//Wifi system api
830//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
831INT wifi_getHalVersion(CHAR *output_string) //RDKB
832{
833 if(!output_string)
834 return RETURN_ERR;
835 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
836
837 return RETURN_OK;
838}
839
840
841/* wifi_factoryReset() function */
842/**
843* @description Clears internal variables to implement a factory reset of the Wi-Fi
844* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
845*
846* @param None
847*
848* @return The status of the operation.
849* @retval RETURN_OK if successful.
850* @retval RETURN_ERR if any error is detected
851*
852* @execution Synchronous
853* @sideeffect None
854*
855* @note This function must not suspend and must not invoke any blocking system
856* calls. It should probably just send a message to a driver event handler task.
857*
858*/
859INT wifi_factoryReset()
860{
861 char cmd[128];
862
863 /*delete running hostapd conf files*/
864 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
865 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
866 system(cmd);
867 system("systemctl restart hostapd.service");
868
869 return RETURN_OK;
870}
871
872/* wifi_factoryResetRadios() function */
873/**
874* @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.
875*
876* @param None
877* @return The status of the operation
878* @retval RETURN_OK if successful
879* @retval RETURN_ERR if any error is detected
880*
881* @execution Synchronous
882*
883* @sideeffect None
884*
885* @note This function must not suspend and must not invoke any blocking system
886* calls. It should probably just send a message to a driver event handler task.
887*
888*/
889INT wifi_factoryResetRadios()
890{
891 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
892 return RETURN_OK;
893
894 return RETURN_ERR;
895}
896
897
898/* wifi_factoryResetRadio() function */
899/**
900* @description Restore selected radio parameters without touching access point parameters
901*
902* @param radioIndex - Index of Wi-Fi Radio channel
903*
904* @return The status of the operation.
905* @retval RETURN_OK if successful.
906* @retval RETURN_ERR if any error is detected
907*
908* @execution Synchronous.
909* @sideeffect None.
910*
911* @note This function must not suspend and must not invoke any blocking system
912* calls. It should probably just send a message to a driver event handler task.
913*
914*/
915INT wifi_factoryResetRadio(int radioIndex) //RDKB
916{
917 system("systemctl stop hostapd.service");
918
919 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
920 if(radioIndex == 0)
921 system("rm /nvram/hostapd0.conf");
922 else if(radioIndex == 1)
923 system("rm /nvram/hostapd1.conf");
924 else
925 return RETURN_ERR;
926
927 system("systemctl start hostapd.service");
928 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
929 return RETURN_OK;
930}
931
932/* wifi_initRadio() function */
933/**
934* Description: This function call initializes the specified radio.
935* Implementation specifics may dictate the functionality since
936* different hardware implementations may have different initilization requirements.
937* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
938*
939* @return The status of the operation.
940* @retval RETURN_OK if successful.
941* @retval RETURN_ERR if any error is detected
942*
943* @execution Synchronous.
944* @sideeffect None.
945*
946* @note This function must not suspend and must not invoke any blocking system
947* calls. It should probably just send a message to a driver event handler task.
948*
949*/
950INT wifi_initRadio(INT radioIndex)
951{
952 //TODO: Initializes the wifi subsystem (for specified radio)
953 return RETURN_OK;
954}
955void macfilter_init()
956{
957 char count[4]={'\0'};
958 char buf[253]={'\0'};
959 char tmp[19]={'\0'};
960 int dev_count,block,mac_entry=0;
961 char res[4]={'\0'};
962 char acl_file_path[64] = {'\0'};
963 FILE *fp = NULL;
964 int index=0;
965 char iface[10]={'\0'};
966 char config_file[MAX_BUF_SIZE] = {0};
967
968
969 sprintf(acl_file_path,"/tmp/mac_filter.sh");
970
971 fp=fopen(acl_file_path,"w+");
972 if (fp == NULL) {
973 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
974 return RETURN_ERR;
975 }
976 sprintf(buf,"#!/bin/sh \n");
977 fprintf(fp,"%s\n",buf);
978
979 system("chmod 0777 /tmp/mac_filter.sh");
980
981 for(index=0;index<=1;index++)
982 {
983 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
984 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
985 sprintf(buf,"syscfg get %dcountfilter",index);
986 _syscmd(buf,count,sizeof(count));
987 mac_entry=atoi(count);
988
989 sprintf(buf,"syscfg get %dblockall",index);
990 _syscmd(buf,res,sizeof(res));
991 block = atoi(res);
992
993 //Allow only those macs mentioned in ACL
994 if(block==1)
995 {
996 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
997 fprintf(fp,"%s\n",buf);
998 for(dev_count=1;dev_count<=mac_entry;dev_count++)
999 {
1000 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1001 _syscmd(buf,tmp,sizeof(tmp));
1002 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1003 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1004 fprintf(fp,"%s\n",buf);
1005 }
1006 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1007 fprintf(fp,"%s\n",buf);
1008 }
1009
1010 //Block all the macs mentioned in ACL
1011 else if(block==2)
1012 {
1013 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1014 fprintf(fp,"%s\n",buf);
1015
1016 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1017 {
1018 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1019 _syscmd(buf,tmp,sizeof(tmp));
1020 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1021 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1022 fprintf(fp,"%s\n",buf);
1023 }
1024 }
1025 }
1026 fclose(fp);
1027}
1028
1029// Initializes the wifi subsystem (all radios)
1030INT wifi_init() //RDKB
1031{
1032 char interface[MAX_BUF_SIZE]={'\0'};
1033 char bridge_name[MAX_BUF_SIZE]={'\0'};
1034 INT len=0;
1035
1036 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1037 //Not intitializing macfilter for Turris-Omnia Platform for now
1038 //macfilter_init();
1039
1040 system("/usr/sbin/iw reg set US");
1041 // system("systemctl start hostapd.service");
1042 sleep(2);//sleep to wait for hostapd to start
1043
1044 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1045
1046 return RETURN_OK;
1047}
1048
1049/* wifi_reset() function */
1050/**
1051* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1052* Implementation specifics may dictate what is actualy reset since
1053* different hardware implementations may have different requirements.
1054* Parameters : None
1055*
1056* @return The status of the operation.
1057* @retval RETURN_OK if successful.
1058* @retval RETURN_ERR if any error is detected
1059*
1060* @execution Synchronous.
1061* @sideeffect None.
1062*
1063* @note This function must not suspend and must not invoke any blocking system
1064* calls. It should probably just send a message to a driver event handler task.
1065*
1066*/
1067INT wifi_reset()
1068{
1069 //TODO: resets the wifi subsystem, deletes all APs
1070 system("systemctl stop hostapd.service");
1071 sleep(2);
1072 system("systemctl start hostapd.service");
1073 sleep(5);
1074 return RETURN_OK;
1075}
1076
1077/* wifi_down() function */
1078/**
1079* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1080* Implementation specifics may dictate some functionality since
1081* different hardware implementations may have different requirements.
1082*
1083* @param None
1084*
1085* @return The status of the operation
1086* @retval RETURN_OK if successful
1087* @retval RETURN_ERR if any error is detected
1088*
1089* @execution Synchronous
1090* @sideeffect None
1091*
1092* @note This function must not suspend and must not invoke any blocking system
1093* calls. It should probably just send a message to a driver event handler task.
1094*
1095*/
1096INT wifi_down()
1097{
1098 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
1099 system("systemctl stop hostapd.service");
1100 sleep(2);
1101 return RETURN_OK;
1102}
1103
1104
1105/* wifi_createInitialConfigFiles() function */
1106/**
1107* @description This function creates wifi configuration files. The format
1108* and content of these files are implementation dependent. This function call is
1109* used to trigger this task if necessary. Some implementations may not need this
1110* function. If an implementation does not need to create config files the function call can
1111* do nothing and return RETURN_OK.
1112*
1113* @param None
1114*
1115* @return The status of the operation
1116* @retval RETURN_OK if successful
1117* @retval RETURN_ERR if any error is detected
1118*
1119* @execution Synchronous
1120* @sideeffect None
1121*
1122* @note This function must not suspend and must not invoke any blocking system
1123* calls. It should probably just send a message to a driver event handler task.
1124*
1125*/
1126INT wifi_createInitialConfigFiles()
1127{
1128 //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)
1129 return RETURN_OK;
1130}
1131
1132// outputs the country code to a max 64 character string
1133INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1134{
1135 char interface_name[16] = {0};
1136 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1137 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
1138 return RETURN_ERR;
1139
1140 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1141 return RETURN_ERR;
1142 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
1143 _syscmd(cmd, buf, sizeof(buf));
1144 if(strlen(buf) > 0)
1145 snprintf(output_string, 64, "%s", buf);
1146 else
1147 return RETURN_ERR;
1148
1149 return RETURN_OK;
1150}
1151
1152INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1153{
1154 //Set wifi config. Wait for wifi reset to apply
1155 char str[MAX_BUF_SIZE]={'\0'};
1156 char cmd[MAX_CMD_SIZE]={'\0'};
1157 struct params params;
1158 char config_file[MAX_BUF_SIZE] = {0};
1159
1160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1161 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1162 return RETURN_ERR;
1163
1164 if (strlen(CountryCode) == 0)
1165 strcpy(CountryCode, "US");
1166
1167 params.name = "country_code";
1168 params.value = CountryCode;
1169 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1170 int ret = wifi_hostapdWrite(config_file, &params, 1);
1171 if (ret) {
1172 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1173 ,__func__, ret);
1174 }
1175
1176 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1177 if (ret) {
1178 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1179 ,__func__, ret);
1180 }
1181 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1182
1183 return RETURN_OK;
1184}
1185
1186INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1187{
1188 char interface_name[16] = {0};
1189 char channel_util_file[64] = {0};
1190 char cmd[128] = {0};
1191 char buf[128] = {0};
1192 char line[128] = {0};
1193 char *param = NULL, *value = NULL;
1194 int read = 0;
1195 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1196 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1197 size_t len = 0;
1198 FILE *f = NULL;
1199
1200 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1201
1202 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1203 return RETURN_ERR;
1204 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
1205 _syscmd(cmd, buf, sizeof(buf));
1206 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1207
1208 memset(cmd, 0, sizeof(cmd));
1209 memset(buf, 0, sizeof(buf));
1210 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
1211 if ((f = popen(cmd, "r")) == NULL) {
1212 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1213 return RETURN_ERR;
1214 }
1215
1216 read = getline(&line, &len, f);
1217 while (read != -1) {
1218 param = strtok(line, ":\t");
1219 value = strtok(NULL, " ");
1220 if(strstr(param, "frequency") != NULL) {
1221 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1222 }
1223 if(strstr(param, "noise") != NULL) {
1224 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1225 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1226 }
1227 if(strstr(param, "channel active time") != NULL) {
1228 ActiveTime = strtol(value, NULL, 10);
1229 }
1230 if(strstr(param, "channel busy time") != NULL) {
1231 BusyTime = strtol(value, NULL, 10);
1232 }
1233 if(strstr(param, "channel transmit time") != NULL) {
1234 TransmitTime = strtol(value, NULL, 10);
1235 }
1236 read = getline(&line, &len, f);
1237 }
1238 pclose(f);
1239
1240 // The file should store the last active, busy and transmit time
1241 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1242 f = fopen(channel_util_file, "r");
1243 if (f != NULL) {
1244 read = getline(&line, &len, f);
1245 preActiveTime = strtol(line, NULL, 10);
1246 read = getline(&line, &len, f);
1247 preBusyTime = strtol(line, NULL, 10);
1248 read = getline(&line, &len, f);
1249 preTransmitTime = strtol(line, NULL, 10);
1250 fclose(f);
1251 }
1252
1253 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1254 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1255
1256 f = fopen(channel_util_file, "w");
1257 if (f != NULL) {
1258 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1259 fclose(f);
1260 }
1261 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1262 return RETURN_OK;
1263}
1264
1265/**********************************************************************************
1266 *
1267 * Wifi radio level function prototypes
1268 *
1269**********************************************************************************/
1270
1271//Get the total number of radios in this wifi subsystem
1272INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1273{
1274 if (NULL == output)
1275 return RETURN_ERR;
1276 *output = MAX_NUM_RADIOS;
1277
1278 return RETURN_OK;
1279}
1280
1281//Get the total number of SSID entries in this wifi subsystem
1282INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1283{
1284 if (NULL == output)
1285 return RETURN_ERR;
1286 *output = MAX_APS;
1287
1288 return RETURN_OK;
1289}
1290
1291//Get the Radio enable config parameter
1292INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1293{
1294 char interface_name[16] = {0};
1295 char buf[128] = {0}, cmd[128] = {0};
1296
1297 if (NULL == output_bool)
1298 return RETURN_ERR;
1299
1300 *output_bool = FALSE;
1301 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
1302 return RETURN_ERR;
1303
1304 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1305 return RETURN_ERR;
1306 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1307 _syscmd(cmd, buf, sizeof(buf));
1308
1309 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1310 *output_bool = TRUE;
1311 return RETURN_OK;
1312}
1313
1314INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1315{
1316 char interface_name[16] = {0};
1317 char cmd[MAX_CMD_SIZE] = {0};
1318 char buf[MAX_CMD_SIZE] = {0};
1319 int apIndex, ret;
1320 int max_radio_num = 0;
1321 int phyId = 0;
1322
1323 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1324
1325 phyId = radio_index_to_phy(radioIndex);
1326
1327 wifi_getMaxRadioNumber(&max_radio_num);
1328
1329 if(enable==FALSE)
1330 {
1331 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1332 {
1333 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1334 return RETURN_ERR;
1335
1336 //Detaching %s%d from hostapd daemon
1337 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
1338 _syscmd(cmd, buf, sizeof(buf));
1339 if(strncmp(buf, "OK", 2))
1340 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
1341
1342 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
1343 _syscmd(cmd, buf, sizeof(buf));
1344 }
1345 }
1346 else
1347 {
1348 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1349 {
1350 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1351 return RETURN_ERR;
1352
1353 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1354 ret = _syscmd(cmd, buf, sizeof(buf));
1355 if ( ret == RETURN_ERR)
1356 {
1357 fprintf(stderr, "VAP interface creation failed\n");
1358 continue;
1359 }
1360 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
1361 _syscmd(cmd, buf, sizeof(buf));
1362 if(*buf == '1')
1363 {
1364 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1365 phyId, apIndex);
1366 _syscmd(cmd, buf, sizeof(buf));
1367 if(strncmp(buf, "OK", 2))
1368 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
1369 }
1370 }
1371 }
1372
1373 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1374 return RETURN_OK;
1375}
1376
1377//Get the Radio enable status
1378INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1379{
1380 if (NULL == output_bool)
1381 return RETURN_ERR;
1382
1383 return wifi_getRadioEnable(radioIndex, output_bool);
1384}
1385
1386//Get the Radio Interface name from platform, eg "wlan0"
1387INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1388{
1389 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
1390 return RETURN_ERR;
1391 return wifi_GetInterfaceName(radioIndex, output_string);
1392}
1393
1394//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1395//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.
1396INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1397{
1398 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1399 // For max bit rate, we should always choose the best MCS
1400 char mode[64] = {0};
1401 char channel_bandwidth_str[64] = {0};
1402 char *tmp = NULL;
1403 UINT mode_map = 0;
1404 UINT num_subcarrier = 0;
1405 UINT code_bits = 0;
1406 float code_rate = 0; // use max code rate
1407 int NSS = 0;
1408 UINT Symbol_duration = 0;
1409 UINT GI_duration = 0;
1410 wifi_band band = band_invalid;
1411 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1412 BOOL enable = FALSE;
1413 float bit_rate = 0;
1414
1415 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1416 if (NULL == output_string)
1417 return RETURN_ERR;
1418
1419 wifi_getRadioEnable(radioIndex, &enable);
1420 if (enable == FALSE) {
1421 snprintf(output_string, 64, "0 Mb/s");
1422 return RETURN_OK;
1423 }
1424
1425 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1426 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1427 return RETURN_ERR;
1428 }
1429
1430 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1431 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1432 return RETURN_ERR;
1433 }
1434
1435 if (gi == wifi_guard_interval_3200)
1436 GI_duration = 32;
1437 else if (gi == wifi_guard_interval_1600)
1438 GI_duration = 16;
1439 else if (gi == wifi_guard_interval_800)
1440 GI_duration = 8;
1441 else // auto, 400
1442 GI_duration = 4;
1443
1444 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1445 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1446 return RETURN_ERR;
1447 }
1448
1449 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1450 strcpy(channel_bandwidth_str, "160");
1451
1452 if (mode_map & WIFI_MODE_AX) {
1453 if (strstr(channel_bandwidth_str, "160") != NULL)
1454 num_subcarrier = 1960;
1455 else if (strstr(channel_bandwidth_str, "80") != NULL)
1456 num_subcarrier = 980;
1457 else if (strstr(channel_bandwidth_str, "40") != NULL)
1458 num_subcarrier = 468;
1459 else if (strstr(channel_bandwidth_str, "20") != NULL)
1460 num_subcarrier = 234;
1461 code_bits = 10;
1462 code_rate = (float)5/6;
1463 Symbol_duration = 128;
1464 } else if (mode_map & WIFI_MODE_AC) {
1465 if (strstr(channel_bandwidth_str, "160") != NULL)
1466 num_subcarrier = 468;
1467 else if (strstr(channel_bandwidth_str, "80") != NULL)
1468 num_subcarrier = 234;
1469 else if (strstr(channel_bandwidth_str, "40") != NULL)
1470 num_subcarrier = 108;
1471 else if (strstr(channel_bandwidth_str, "20") != NULL)
1472 num_subcarrier = 52;
1473 code_bits = 8;
1474 code_rate = (float)5/6;
1475 Symbol_duration = 32;
1476 } else if (mode_map & WIFI_MODE_N) {
1477 if (strstr(channel_bandwidth_str, "160") != NULL)
1478 num_subcarrier = 468;
1479 else if (strstr(channel_bandwidth_str, "80") != NULL)
1480 num_subcarrier = 234;
1481 else if (strstr(channel_bandwidth_str, "40") != NULL)
1482 num_subcarrier = 108;
1483 else if (strstr(channel_bandwidth_str, "20") != NULL)
1484 num_subcarrier = 52;
1485 code_bits = 6;
1486 code_rate = (float)3/4;
1487 Symbol_duration = 32;
1488 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1489 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1490 snprintf(output_string, 64, "65 Mb/s");
1491 return RETURN_OK;
1492 } else {
1493 snprintf(output_string, 64, "0 Mb/s");
1494 return RETURN_OK;
1495 }
1496
1497 // Spatial streams
1498 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1499 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1500 return RETURN_ERR;
1501 }
1502
1503 // multiple 10 is to align duration unit (0.1 us)
1504 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1505 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1506
1507 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1508
1509 return RETURN_OK;
1510}
1511#if 0
1512INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1513{
1514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1515 char cmd[64];
1516 char buf[1024];
1517 int apIndex;
1518
1519 if (NULL == output_string)
1520 return RETURN_ERR;
1521
1522 apIndex=(radioIndex==0)?0:1;
1523
1524 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
1525 _syscmd(cmd,buf, sizeof(buf));
1526
1527 snprintf(output_string, 64, "%s", buf);
1528 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1529 return RETURN_OK;
1530}
1531#endif
1532
1533
1534//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1535//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.
1536INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1537{
1538 wifi_band band = band_invalid;
1539
1540 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1541 if (NULL == output_string)
1542 return RETURN_ERR;
1543
1544 band = wifi_index_to_band(radioIndex);
1545
1546 memset(output_string, 0, 10);
1547 if (band == band_2_4)
1548 strcpy(output_string, "2.4GHz");
1549 else if (band == band_5)
1550 strcpy(output_string, "5GHz");
1551 else if (band == band_6)
1552 strcpy(output_string, "6GHz");
1553 else
1554 return RETURN_ERR;
1555 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1556
1557 return RETURN_OK;
1558#if 0
1559 char buf[MAX_BUF_SIZE]={'\0'};
1560 char str[MAX_BUF_SIZE]={'\0'};
1561 char cmd[MAX_CMD_SIZE]={'\0'};
1562 char *ch=NULL;
1563 char *ch2=NULL;
1564
1565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1566 if (NULL == output_string)
1567 return RETURN_ERR;
1568
1569
1570 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1571
1572 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1573 {
1574 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1575 return RETURN_ERR;
1576 }
1577 ch=strchr(buf,'\n');
1578 *ch='\0';
1579 ch=strchr(buf,'=');
1580 if(ch==NULL)
1581 return RETURN_ERR;
1582
1583
1584 ch++;
1585
1586 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1587 strcpy(buf,"0");
1588 if(strlen(ch) == 1)
1589 ch=strcat(buf,ch);
1590
1591
1592 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1593
1594 if(_syscmd(cmd,str,64) == RETURN_ERR)
1595 {
1596 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1597 return RETURN_ERR;
1598 }
1599
1600
1601 ch2=strchr(str,'\n');
1602 //replace \n with \0
1603 *ch2='\0';
1604 ch2=strchr(str,'=');
1605 if(ch2==NULL)
1606 {
1607 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1608 return RETURN_ERR;
1609 }
1610 else
1611 wifi_dbg_printf("%s",ch2+1);
1612
1613
1614 ch2++;
1615
1616
1617 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1618
1619 memset(buf,'\0',sizeof(buf));
1620 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1621 {
1622 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1623 return RETURN_ERR;
1624 }
1625 if (strstr(buf,"2.4") != NULL )
1626 strcpy(output_string,"2.4GHz");
1627 else if(strstr(buf,"5.") != NULL )
1628 strcpy(output_string,"5GHz");
1629 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1630
1631 return RETURN_OK;
1632#endif
1633}
1634
1635//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1636//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.
1637INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1638{
1639 wifi_band band = band_invalid;
1640 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1641 if (NULL == output_string)
1642 return RETURN_ERR;
1643 band = wifi_index_to_band(radioIndex);
1644
1645 if (band == band_2_4)
1646 snprintf(output_string, 64, "2.4GHz");
1647 else if (band == band_5)
1648 snprintf(output_string, 64, "5GHz");
1649 else if (band == band_6)
1650 snprintf(output_string, 64, "6GHz");
1651
1652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1653
1654 return RETURN_OK;
1655#if 0
1656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1657 char buf[MAX_BUF_SIZE]={'\0'};
1658 char str[MAX_BUF_SIZE]={'\0'};
1659 char cmd[MAX_CMD_SIZE]={'\0'};
1660 char *ch=NULL;
1661 char *ch2=NULL;
1662 char ch1[5]="0";
1663
1664 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1665
1666 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1667 {
1668 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1669 return RETURN_ERR;
1670 }
1671
1672 ch=strchr(buf,'\n');
1673 *ch='\0';
1674 ch=strchr(buf,'=');
1675 if(ch==NULL)
1676 return RETURN_ERR;
1677 ch++;
1678
1679 if(strlen(ch)==1)
1680 {
1681 strcat(ch1,ch);
1682
1683 }
1684 else
1685 {
1686 strcpy(ch1,ch);
1687 }
1688
1689
1690
1691 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1692 if(_syscmd(cmd,str,64) == RETURN_ERR)
1693 {
1694 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1695 return RETURN_ERR;
1696 }
1697
1698
1699 ch2=strchr(str,'\n');
1700 //replace \n with \0
1701 *ch2='\0';
1702 ch2=strchr(str,'=');
1703 if(ch2==NULL)
1704 {
1705 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1706 return RETURN_ERR;
1707 }
1708 else
1709 wifi_dbg_printf("%s",ch2+1);
1710 ch2++;
1711
1712
1713 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1714 memset(buf,'\0',sizeof(buf));
1715 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1716 {
1717 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1718 return RETURN_ERR;
1719 }
1720
1721
1722 if(strstr(buf,"2.4")!=NULL)
1723 {
1724 strcpy(output_string,"2.4GHz");
1725 }
1726 if(strstr(buf,"5.")!=NULL)
1727 {
1728 strcpy(output_string,"5GHz");
1729 }
1730 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1731 return RETURN_OK;
1732#endif
1733}
1734
1735//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1736//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.
1737INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1738{
1739 char cmd[128]={0};
1740 char buf[128]={0};
1741 char temp_output[128] = {0};
1742 wifi_band band;
1743 int phyId = 0;
1744
1745 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1746 if (NULL == output_string)
1747 return RETURN_ERR;
1748
1749 band = wifi_index_to_band(radioIndex);
1750 if (band == band_2_4) {
1751 strcat(temp_output, "b,g,");
1752 } else if (band == band_5) {
1753 strcat(temp_output, "a,");
1754 }
1755 phyId = radio_index_to_phy(radioIndex);
1756 // ht capabilities
1757 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);
1758 _syscmd(cmd, buf, sizeof(buf));
1759 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
1760 strcat(temp_output, "n,");
1761 }
1762
1763 // vht capabilities
1764 if (band == band_5) {
1765 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
1766 _syscmd(cmd, buf, sizeof(buf));
1767 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
1768 strcat(temp_output, "ac,");
1769 }
1770 }
1771
1772 // he capabilities
1773 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);
1774 _syscmd(cmd, buf, sizeof(buf));
1775 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
1776 strcat(temp_output, "ax,");
1777 }
1778
1779 // Remove the last comma
1780 if (strlen(temp_output) != 0)
1781 temp_output[strlen(temp_output)-1] = '\0';
1782 strncpy(output_string, temp_output, strlen(temp_output));
1783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1784 return RETURN_OK;
1785}
1786
1787//Get the radio operating mode, and pure mode flag. eg: "ac"
1788//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.
1789INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1790{
1791 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1792 if (NULL == output_string)
1793 return RETURN_ERR;
1794
1795 if (radioIndex == 0) {
1796 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1797 *gOnly = FALSE;
1798 *nOnly = TRUE;
1799 *acOnly = FALSE;
1800 } else {
1801 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1802 *gOnly = FALSE;
1803 *nOnly = FALSE;
1804 *acOnly = FALSE;
1805 }
1806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1807
1808 return RETURN_OK;
1809#if 0
1810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1811 char buf[64] = {0};
1812 char config_file[MAX_BUF_SIZE] = {0};
1813
1814 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1815 return RETURN_ERR;
1816
1817 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1818 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1819
1820 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1821 if (strlen(buf) == 0)
1822 {
1823 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1824 return RETURN_ERR;
1825 }
1826 if(strcmp(buf,"g")==0)
1827 {
1828 wifi_dbg_printf("\nG\n");
1829 *gOnly=TRUE;
1830 *nOnly=FALSE;
1831 *acOnly=FALSE;
1832 }
1833 else if(strcmp(buf,"n")==0)
1834 {
1835 wifi_dbg_printf("\nN\n");
1836 *gOnly=FALSE;
1837 *nOnly=TRUE;
1838 *acOnly=FALSE;
1839 }
1840 else if(strcmp(buf,"ac")==0)
1841 {
1842 wifi_dbg_printf("\nac\n");
1843 *gOnly=FALSE;
1844 *nOnly=FALSE;
1845 *acOnly=TRUE;
1846 }
1847 /* hostapd-5G.conf has "a" as hw_mode */
1848 else if(strcmp(buf,"a")==0)
1849 {
1850 wifi_dbg_printf("\na\n");
1851 *gOnly=FALSE;
1852 *nOnly=FALSE;
1853 *acOnly=FALSE;
1854 }
1855 else
1856 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1857
1858 //for a,n mode
1859 if(radioIndex == 1)
1860 {
1861 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1862 if(strcmp(buf,"1")==0)
1863 {
1864 strncpy(output_string, "n", 1);
1865 *nOnly=FALSE;
1866 }
1867 }
1868
1869 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1870 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1871 return RETURN_OK;
1872#endif
1873}
1874
1875INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1876{
1877 char cmd[128] = {0};
1878 char buf[64] = {0};
1879 char config_file[64] = {0};
1880 wifi_band band;
1881
1882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1883 if(NULL == output_string || NULL == pureMode)
1884 return RETURN_ERR;
1885
1886 // grep all of the ieee80211 protocol config set to 1
1887 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1888 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1889 _syscmd(cmd, buf, sizeof(buf));
1890
1891 band = wifi_index_to_band(radioIndex);
1892 // puremode is a bit map
1893 *pureMode = 0;
1894 if (band == band_2_4) {
1895 strcat(output_string, "b,g");
1896 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1897 if (strstr(buf, "n") != NULL) {
1898 strcat(output_string, ",n");
1899 *pureMode |= WIFI_MODE_N;
1900 }
1901 if (strstr(buf, "ax") != NULL) {
1902 strcat(output_string, ",ax");
1903 *pureMode |= WIFI_MODE_AX;
1904 }
1905 } else if (band == band_5) {
1906 strcat(output_string, "a");
1907 *pureMode |= WIFI_MODE_A;
1908 if (strstr(buf, "n") != NULL) {
1909 strcat(output_string, ",n");
1910 *pureMode |= WIFI_MODE_N;
1911 }
1912 if (strstr(buf, "ac") != NULL) {
1913 strcat(output_string, ",ac");
1914 *pureMode |= WIFI_MODE_AC;
1915 }
1916 if (strstr(buf, "ax") != NULL) {
1917 strcat(output_string, ",ax");
1918 *pureMode |= WIFI_MODE_AX;
1919 }
1920 } else if (band == band_6) {
1921 if (strstr(buf, "ax") != NULL) {
1922 strcat(output_string, "ax");
1923 *pureMode |= WIFI_MODE_AX;
1924 }
1925 }
1926
1927 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1928 return RETURN_OK;
1929}
1930
1931// Set the radio operating mode, and pure mode flag.
1932INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1933{
1934 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1935 if (strcmp (channelMode,"11A") == 0)
1936 {
1937 writeBandWidth(radioIndex,"20MHz");
1938 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1939 printf("\nChannel Mode is 802.11a (5GHz)\n");
1940 }
1941 else if (strcmp (channelMode,"11NAHT20") == 0)
1942 {
1943 writeBandWidth(radioIndex,"20MHz");
1944 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1945 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1946 }
1947 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1948 {
1949 writeBandWidth(radioIndex,"40MHz");
1950 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1951 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1952 }
1953 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1954 {
1955 writeBandWidth(radioIndex,"40MHz");
1956 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1957 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1958 }
1959 else if (strcmp (channelMode,"11ACVHT20") == 0)
1960 {
1961 writeBandWidth(radioIndex,"20MHz");
1962 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1963 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1964 }
1965 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1966 {
1967 writeBandWidth(radioIndex,"40MHz");
1968 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1969 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1970 }
1971 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1972 {
1973 writeBandWidth(radioIndex,"40MHz");
1974 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1975 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1976 }
1977 else if (strcmp (channelMode,"11ACVHT80") == 0)
1978 {
1979 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1980 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1981 }
1982 else if (strcmp (channelMode,"11ACVHT160") == 0)
1983 {
1984 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1985 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1986 }
1987 else if (strcmp (channelMode,"11B") == 0)
1988 {
1989 writeBandWidth(radioIndex,"20MHz");
1990 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1991 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1992 }
1993 else if (strcmp (channelMode,"11G") == 0)
1994 {
1995 writeBandWidth(radioIndex,"20MHz");
1996 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1997 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1998 }
1999 else if (strcmp (channelMode,"11NGHT20") == 0)
2000 {
2001 writeBandWidth(radioIndex,"20MHz");
2002 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2003 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2004 }
2005 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2006 {
2007 writeBandWidth(radioIndex,"40MHz");
2008 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2009 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2010 }
2011 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2012 {
2013 writeBandWidth(radioIndex,"40MHz");
2014 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2015 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2016 }
2017 else
2018 {
2019 return RETURN_ERR;
2020 }
2021 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2022
2023 return RETURN_OK;
2024}
2025
2026// Set the radio operating mode, and pure mode flag.
2027INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2028{
2029 int num_hostapd_support_mode = 3; // n, ac, ax
2030 struct params list[num_hostapd_support_mode];
2031 char config_file[64] = {0};
2032 char bandwidth[16] = {0};
2033 int mode_check_bit = 1 << 3; // n mode
2034
2035
2036 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2037 // Set radio mode
2038 list[0].name = "ieee80211n";
2039 list[1].name = "ieee80211ac";
2040 list[2].name = "ieee80211ax";
2041 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2042
2043 // check the bit map from n to ax, and set hostapd config
2044 if (pureMode & WIFI_MODE_N)
2045 list[0].value = "1";
2046 else
2047 list[0].value = "0";
2048 if (pureMode & WIFI_MODE_AC)
2049 list[1].value = "1";
2050 else
2051 list[1].value = "0";
2052 if (pureMode & WIFI_MODE_AX)
2053 list[2].value = "1";
2054 else
2055 list[2].value = "0";
2056 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2057
2058 if (channelMode == NULL || strlen(channelMode) == 0)
2059 return RETURN_OK;
2060 // Set bandwidth
2061 if (strstr(channelMode, "40") != NULL)
2062 strcpy(bandwidth, "40MHz");
2063 else if (strstr(channelMode, "80") != NULL)
2064 strcpy(bandwidth, "80MHz");
2065 else if (strstr(channelMode, "160") != NULL)
2066 strcpy(bandwidth, "160MHz");
2067 else // 11A, 11B, 11G....
2068 strcpy(bandwidth, "20MHz");
2069
2070 writeBandWidth(radioIndex, bandwidth);
2071 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2072
2073 wifi_reloadAp(radioIndex);
2074 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2075
2076 return RETURN_OK;
2077}
2078
2079INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2080
2081 char config_file[64] = {0};
2082 char buf[64] = {0};
2083 struct params params = {0};
2084 wifi_band band = band_invalid;
2085
2086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2087
2088 band = wifi_index_to_band(radioIndex);
2089
2090 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
2091 return RETURN_ERR;
2092 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2093 return RETURN_ERR;
2094 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2095 return RETURN_ERR;
2096
2097 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2098 params.name = "hw_mode";
2099 params.value = hw_mode;
2100 wifi_hostapdWrite(config_file, &params, 1);
2101 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2102
2103 if (band == band_2_4) {
2104 if (strncmp(hw_mode, "b", 1) == 0) {
2105 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2106 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2107 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2108 snprintf(buf, sizeof(buf), "%s", "1,2");
2109 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2110 } else {
2111 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2112
2113 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2114 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2115 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2116 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2117 }
2118 }
2119
2120 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2121 return RETURN_OK;
2122}
2123
2124INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2125{
2126 char config_file[64] = {0};
2127 struct params params = {0};
2128 wifi_band band = band_invalid;
2129
2130 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2131
2132 band = wifi_index_to_band(radioIndex);
2133 if (band != band_2_4)
2134 return RETURN_OK;
2135
2136 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2137 params.name = "noscan";
2138 params.value = noscan;
2139 wifi_hostapdWrite(config_file, &params, 1);
2140 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2141
2142 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2143 return RETURN_OK;
2144}
2145
2146//Get the list of supported channel. eg: "1-11"
2147//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.
2148INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2149{
2150 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2151 if (NULL == output_string)
2152 return RETURN_ERR;
2153 char cmd[256] = {0};
2154 char buf[128] = {0};
2155 BOOL dfs_enable = false;
2156 int phyId = 0;
2157
2158 // Parse possible channel number and separate them with commas.
2159 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2160 phyId = radio_index_to_phy(radioIndex);
2161 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
2162 if (dfs_enable)
2163 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);
2164 else
2165 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);
2166
2167 _syscmd(cmd,buf,sizeof(buf));
2168 strncpy(output_string, buf, sizeof(buf));
2169
2170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2171 return RETURN_OK;
2172}
2173
2174//Get the list for used channel. eg: "1,6,9,11"
2175//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.
2176INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2177{
2178 char interface_name[16] = {0};
2179 char cmd[128] = {0};
2180 char buf[128] = {0};
2181 char config_file[64] = {0};
2182 int channel = 0;
2183 int freq = 0;
2184 int bandwidth = 0;
2185 int center_freq = 0;
2186 int center_channel = 0;
2187 int channel_delta = 0;
2188 wifi_band band = band_invalid;
2189
2190 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2191
2192 if (NULL == output_string)
2193 return RETURN_ERR;
2194
2195 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2196 return RETURN_ERR;
2197 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
2198 _syscmd(cmd, buf, sizeof(buf));
2199 if (strlen(buf) == 0) {
2200 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2201 return RETURN_ERR;
2202 }
2203 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2204
2205 if (bandwidth == 20) {
2206 snprintf(output_string, 256, "%d", channel);
2207 return RETURN_OK;
2208 }
2209
2210 center_channel = ieee80211_frequency_to_channel(center_freq);
2211
2212 band = wifi_index_to_band(radioIndex);
2213 if (band == band_2_4 && bandwidth == 40) {
2214 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2215 memset(buf, 0, sizeof(buf));
2216 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2217
2218 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
2219 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2220 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
2221 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2222 } else {
2223 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2224 return RETURN_ERR;
2225 }
2226 } else if (band == band_5 || band == band_6){
2227 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2228 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2229 channel_delta = (bandwidth-20)/10;
2230 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2231 } else
2232 return RETURN_ERR;
2233
2234 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2235 return RETURN_OK;
2236}
2237
2238//Get the running channel number
2239INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2240{
2241 char channel_str[16] = {0};
2242 char config_file[128] = {0};
2243
2244 if (output_ulong == NULL)
2245 return RETURN_ERR;
2246
2247 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2248 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
2249
2250 *output_ulong = strtoul(channel_str, NULL, 10);
2251
2252 return RETURN_OK;
2253}
2254
2255
2256INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2257{
2258 char cmd[1024] = {0}, buf[5] = {0};
2259 char interface_name[16] = {0};
2260
2261 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2262 if (NULL == output_ulong)
2263 return RETURN_ERR;
2264
2265 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2266 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2267 return RETURN_ERR;
2268 _syscmd(cmd,buf,sizeof(buf));
2269 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2270 if (*output_ulong == 0) {
2271 return RETURN_ERR;
2272 }
2273
2274 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2275 return RETURN_OK;
2276}
2277
2278//Storing the previous channel value
2279INT wifi_storeprevchanval(INT radioIndex)
2280{
2281 char buf[256] = {0};
2282 char output[4]={'\0'};
2283 char config_file[MAX_BUF_SIZE] = {0};
2284 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2285 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2286 if(radioIndex == 0)
2287 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2288 else if(radioIndex == 1)
2289 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2290 system(buf);
2291 Radio_flag = FALSE;
2292 return RETURN_OK;
2293}
2294
2295//Set the running channel number
2296INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2297{
2298 // We only write hostapd config here
2299 char str_channel[8]={0};
2300 char *list_channel;
2301 char config_file[128] = {0};
2302 char possible_channels[256] = {0};
2303 int max_radio_num = 0;
2304 struct params list = {0};
2305
2306 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2307
2308 // Check valid
2309 sprintf(str_channel, "%lu", channel);
2310
2311 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2312 list_channel = strtok(possible_channels, ",");
2313 while(true)
2314 {
2315 if(list_channel == NULL) { // input not in the list
2316 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2317 return RETURN_ERR;
2318 }
2319 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2320 break;
2321 list_channel = strtok(NULL, ",");
2322 }
2323
2324 list.name = "channel";
2325 list.value = str_channel;
2326 wifi_getMaxRadioNumber(&max_radio_num);
2327 for(int i=0; i<=MAX_APS/max_radio_num;i++)
2328 {
2329 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2330 wifi_hostapdWrite(config_file, &list, 1);
2331 }
2332
2333 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2334 return RETURN_OK;
2335}
2336
2337INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2338{
2339 struct params list[2];
2340 char str_idx[16];
2341 char config_file[64];
2342 int max_num_radios = 0;
2343 wifi_band band = band_invalid;
2344
2345 band = wifi_index_to_band(radioIndex);
2346 if (band == band_2_4)
2347 return RETURN_OK;
2348
2349 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
2350 list[0].name = "vht_oper_centr_freq_seg0_idx";
2351 list[0].value = str_idx;
2352 list[1].name = "he_oper_centr_freq_seg0_idx";
2353 list[1].value = str_idx;
2354
2355 wifi_getMaxRadioNumber(&max_num_radios);
2356 for(int i=0; i<=MAX_APS/max_num_radios; i++)
2357 {
2358 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2359 if (band == band_6)
2360 wifi_hostapdWrite(config_file, &list[1], 1);
2361 else
2362 wifi_hostapdWrite(config_file, list, 2);
2363 }
2364
2365 return RETURN_OK;
2366}
2367
2368//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2369//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2370INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2371{
2372 //Set to wifi config only. Wait for wifi reset to apply.
2373 char buf[256] = {0};
2374 char str_channel[256] = {0};
2375 int count = 0;
2376 ULONG Value = 0;
2377 FILE *fp = NULL;
2378 if(enable == TRUE)
2379 {
2380 wifi_setRadioChannel(radioIndex,Value);
2381 }
2382 return RETURN_OK;
2383}
2384
2385INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2386{
2387 if (output_bool == NULL)
2388 return RETURN_ERR;
2389
2390 *output_bool = TRUE;
2391
2392 return RETURN_OK;
2393}
2394
2395INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2396{
2397 if (NULL == output_bool)
2398 return RETURN_ERR;
2399 *output_bool=FALSE;
2400 return RETURN_OK;
2401}
2402
2403INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2404{
2405 if (NULL == output_bool)
2406 return RETURN_ERR;
2407 *output_bool=FALSE;
2408 return RETURN_OK;
2409}
2410
2411INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2412{
2413 //Set to wifi config only. Wait for wifi reset to apply.
2414 return RETURN_OK;
2415}
2416
2417INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2418{
2419 return RETURN_OK;
2420}
2421
2422INT wifi_factoryResetAP(int apIndex)
2423{
2424 char ap_config_file[64] = {0};
2425 char cmd[128] = {0};
2426
2427 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2428
2429 wifi_setApEnable(apIndex, FALSE);
2430 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2431 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2432 wifi_setApEnable(apIndex, TRUE);
2433
2434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2435
2436 return RETURN_OK;
2437}
2438
2439//To set Band Steering AP group
2440//To-do
2441INT wifi_setBandSteeringApGroup(char *ApGroup)
2442{
2443 return RETURN_OK;
2444}
2445
2446INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2447{
2448 char config_file[128] = {'\0'};
2449 char buf[128] = {'\0'};
2450
2451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2452 if (dtimInterval == NULL)
2453 return RETURN_ERR;
2454
2455 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2456 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2457
2458 if (strlen(buf) == 0) {
2459 *dtimInterval = 2;
2460 } else {
2461 *dtimInterval = strtoul(buf, NULL, 10);
2462 }
2463
2464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2465 return RETURN_OK;
2466}
2467
2468INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2469{
2470 struct params params={0};
2471 char config_file[MAX_BUF_SIZE] = {'\0'};
2472 char buf[MAX_BUF_SIZE] = {'\0'};
2473
2474 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2475 if (dtimInterval < 1 || dtimInterval > 255) {
2476 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2477 return RETURN_ERR;
2478 }
2479
2480 params.name = "dtim_period";
2481 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2482 params.value = buf;
2483
2484 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2485 wifi_hostapdWrite(config_file, &params, 1);
2486 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2487
2488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2489 return RETURN_OK;
2490}
2491
2492//Check if the driver support the Dfs
2493INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2494{
2495 wifi_band band = band_invalid;
2496 if (NULL == output_bool)
2497 return RETURN_ERR;
2498 *output_bool=FALSE;
2499
2500 band = wifi_index_to_band(radioIndex);
2501 if (band == band_5)
2502 *output_bool = TRUE;
2503 return RETURN_OK;
2504}
2505
2506//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.
2507//The value of this parameter is a comma seperated list of channel number
2508INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2509{
2510 if (NULL == output_pool)
2511 return RETURN_ERR;
2512 if (radioIndex==1)
2513 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2514 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2515
2516 return RETURN_OK;
2517}
2518
2519INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2520{
2521 //Set to wifi config. And apply instantly.
2522 return RETURN_OK;
2523}
2524
2525INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2526{
2527 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2528 return RETURN_ERR;
2529 *output_interval_seconds=1800;
2530 *output_dwell_milliseconds=40;
2531
2532 return RETURN_OK;
2533}
2534
2535INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2536{
2537 //Set to wifi config. And apply instantly.
2538 return RETURN_OK;
2539}
2540
2541INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2542{
2543 if (output_bool == NULL)
2544 return RETURN_ERR;
2545 *output_bool = true;
2546 return RETURN_OK;
2547}
2548
2549INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2550{
2551 return RETURN_OK;
2552}
2553
2554//Get the Dfs enable status
2555INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2556{
2557 char buf[16] = {0};
2558 FILE *f = NULL;
2559
2560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2561
2562 if (output_bool == NULL)
2563 return RETURN_ERR;
2564
2565 *output_bool = TRUE; // default
2566 f = fopen(DFS_ENABLE_FILE, "r");
2567 if (f != NULL) {
2568 fgets(buf, 2, f);
2569 if (strncmp(buf, "0", 1) == 0)
2570 *output_bool = FALSE;
2571 fclose(f);
2572 }
2573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2574 return RETURN_OK;
2575}
2576
2577//Set the Dfs enable status
2578INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2579{
2580 char config_file[128] = {0};
2581 FILE *f = NULL;
2582 struct params params={0};
2583
2584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2585
2586 f = fopen(DFS_ENABLE_FILE, "w");
2587 if (f == NULL)
2588 return RETURN_ERR;
2589 fprintf(f, "%d", enable);
2590 fclose(f);
2591
2592 params.name = "acs_exclude_dfs";
2593 params.value = enable?"0":"1";
2594 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2595 wifi_hostapdWrite(config_file, &params, 1);
2596 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2597
2598 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2599
2600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2601 return RETURN_OK;
2602}
2603
2604//Check if the driver support the AutoChannelRefreshPeriod
2605INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2606{
2607 if (NULL == output_bool)
2608 return RETURN_ERR;
2609 *output_bool=FALSE; //not support
2610
2611 return RETURN_OK;
2612}
2613
2614//Get the ACS refresh period in seconds
2615INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2616{
2617 if (NULL == output_ulong)
2618 return RETURN_ERR;
2619 *output_ulong=300;
2620
2621 return RETURN_OK;
2622}
2623
2624//Set the ACS refresh period in seconds
2625INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2626{
2627 return RETURN_ERR;
2628}
2629
2630//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2631//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.
2632INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2633{
2634 char cmd[128] = {0}, buf[64] = {0};
2635 char extchannel[128] = {0};
2636 char interface_name[64] = {0};
2637 int ret = 0, len=0;
2638 BOOL radio_enable = FALSE;
2639 wifi_band band;
2640
2641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2642
2643 if (NULL == output_string)
2644 return RETURN_ERR;
2645
2646 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2647 return RETURN_ERR;
2648
2649 if (radio_enable != TRUE)
2650 return RETURN_OK;
2651
2652 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2653 return RETURN_ERR;
2654 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
2655 ret = _syscmd(cmd, buf, sizeof(buf));
2656 len = strlen(buf);
2657 if((ret != 0) || (len == 0))
2658 {
2659 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2660 return RETURN_ERR;
2661 }
2662
2663 band = wifi_index_to_band(radioIndex);
2664 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
2665 wifi_getRadioExtChannel(radioIndex, extchannel);
2666 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
2667 snprintf(buf, sizeof(buf), "40");
2668 }
2669 snprintf(output_string, 64, "%sMHz", buf);
2670 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2671
2672 return RETURN_OK;
2673}
2674
2675//Set the Operating Channel Bandwidth.
2676INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
2677{
2678 char config_file[128];
2679 char set_value[16];
2680 struct params params[2];
2681 int max_radio_num = 0;
2682
2683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2684
2685 if(NULL == bandwidth)
2686 return RETURN_ERR;
2687
2688 if(strstr(bandwidth,"160") != NULL)
2689 strcpy(set_value, "2");
2690 else if(strstr(bandwidth,"80") != NULL)
2691 strcpy(set_value, "1");
2692 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2693 strcpy(set_value, "0");
2694 else
2695 {
2696 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
2697 return RETURN_ERR;
2698 }
2699
2700 params[0].name = "vht_oper_chwidth";
2701 params[0].value = set_value;
2702 params[1].name = "he_oper_chwidth";
2703 params[1].value = set_value;
2704
2705 wifi_getMaxRadioNumber(&max_radio_num);
2706 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2707 {
2708 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2709 wifi_hostapdWrite(config_file, params, 2);
2710 }
2711
2712 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2713 return RETURN_OK;
2714}
2715
2716//Getting current radio extension channel
2717INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2718{
2719 CHAR buf[150] = {0};
2720 CHAR cmd[150] = {0};
2721 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2722 _syscmd(cmd, buf, sizeof(buf));
2723 if(NULL != strstr(buf,"HT40+"))
2724 strcpy(Value,"AboveControlChannel");
2725 else if(NULL != strstr(buf,"HT40-"))
2726 strcpy(Value,"BelowControlChannel");
2727 return RETURN_OK;
2728}
2729
2730//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2731//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.
2732INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2733{
2734 char config_file[64] = {0};
2735 char mode_str[16] = {0};
2736 char buf[64] = {0};
2737 wifi_band band;
2738 int channel = 0, centr_channel = 0;
2739 UINT mode_map = 0;
2740
2741 if (output_string == NULL)
2742 return RETURN_ERR;
2743
2744 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
2745
2746 band = wifi_index_to_band(radioIndex);
2747 if (band == band_invalid)
2748 return RETURN_ERR;
2749
2750 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2751
2752 snprintf(output_string, 64, "Auto");
2753 if (band == band_2_4 || (!mode_map&WIFI_MODE_AC && !mode_map&WIFI_MODE_AX)) {
2754 // 2G band or ac and ax mode is disable, we will check ht_capab
2755 wifi_halgetRadioExtChannel(config_file, output_string);
2756 if (!mode_map&WIFI_MODE_N)
2757 snprintf(output_string, 64, "Auto");
2758 } else {
2759 // 5G and 6G band with ac or ax mode.
2760 wifi_getRadioChannel(radioIndex, &channel);
2761 if (mode_map&WIFI_MODE_AX)
2762 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2763 else
2764 wifi_hostapdRead(config_file, "vht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2765 centr_channel = strtol(buf, NULL, 10);
2766 if (centr_channel > channel)
2767 snprintf(output_string, 64, "AboveControlChannel");
2768 else
2769 snprintf(output_string, 64, "BelowControlChannel");
2770 }
2771
2772 return RETURN_OK;
2773}
2774
2775//Set the extension channel.
2776INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2777{
2778 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2779 struct params params={0};
2780 char config_file[64] = {0};
2781 char ext_channel[128]={0};
2782 char buf[128] = {0};
2783 char cmd[128] = {0};
2784 int max_radio_num =0, ret = 0, bandwidth = 0;
2785 unsigned long channel = 0, centr_channel = 0;
2786 bool stbcEnable = FALSE;
2787 params.name = "ht_capab";
2788 wifi_band band;
2789
2790 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2791 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2792 _syscmd(cmd, buf, sizeof(buf));
2793 if (strlen(buf) != 0)
2794 stbcEnable = TRUE;
2795 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2796 return RETURN_ERR;
2797 bandwidth = strtol(buf, NULL, 10);
2798 // TDK expected to get error with 20MHz
2799 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
2800 return RETURN_ERR;
2801
2802 band = wifi_index_to_band(radioIndex);
2803 if (band == band_invalid)
2804 return RETURN_ERR;
2805
2806 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
2807 return RETURN_ERR;
2808
2809 if (band == band_5) {
2810 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
2811 centr_channel = util_unii_5g_centerfreq(buf, channel);
2812 if (centr_channel == 0)
2813 return RETURN_ERR;
2814 }
2815
2816 if(NULL!= strstr(string,"Above")) {
2817 if ((band == band_2_4 && channel > 9) || (band == band_5 && channel > centr_channel))
2818 return RETURN_ERR;
2819 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
2820 } else if(NULL!= strstr(string,"Below")) {
2821 if ((band == band_2_4 && channel < 5) || (band == band_5 && channel < centr_channel))
2822 return RETURN_ERR;
2823 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
2824 } else {
2825 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
2826 }
2827
2828 params.value = ext_channel;
2829
2830 wifi_getMaxRadioNumber(&max_radio_num);
2831 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2832 {
2833 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
2834 wifi_hostapdWrite(config_file, &params, 1);
2835 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
2836 }
2837
2838 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2839 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2840 return RETURN_OK;
2841}
2842
2843//Get the guard interval value. eg "400nsec" or "800nsec"
2844//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.
2845INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2846{
2847 wifi_guard_interval_t GI;
2848
2849 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2850
2851 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
2852 return RETURN_ERR;
2853
2854 if (GI == wifi_guard_interval_400)
2855 strcpy(output_string, "400nsec");
2856 else if (GI == wifi_guard_interval_800)
2857 strcpy(output_string, "800nsec");
2858 else if (GI == wifi_guard_interval_1600)
2859 strcpy(output_string, "1600nsec");
2860 else if (GI == wifi_guard_interval_3200)
2861 strcpy(output_string, "3200nsec");
2862 else
2863 strcpy(output_string, "Auto");
2864
2865 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2866 return RETURN_OK;
2867}
2868
2869//Set the guard interval value.
2870INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2871{
2872 wifi_guard_interval_t GI;
2873 int ret = 0;
2874
2875 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2876
2877 if (strcmp(string, "400nsec") == 0)
2878 GI = wifi_guard_interval_400;
2879 else if (strcmp(string , "800nsec") == 0)
2880 GI = wifi_guard_interval_800;
2881 else if (strcmp(string , "1600nsec") == 0)
2882 GI = wifi_guard_interval_1600;
2883 else if (strcmp(string , "3200nsec") == 0)
2884 GI = wifi_guard_interval_3200;
2885 else
2886 GI = wifi_guard_interval_auto;
2887
2888 ret = wifi_setGuardInterval(radioIndex, GI);
2889
2890 if (ret == RETURN_ERR) {
2891 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2892 return RETURN_ERR;
2893 }
2894
2895 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2896 return RETURN_OK;
2897}
2898
2899//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2900INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2901{
2902 char buf[32]={0};
2903 char mcs_file[64] = {0};
2904 char cmd[64] = {0};
2905 int mode_bitmap = 0;
2906
2907 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2908 if(output_int == NULL)
2909 return RETURN_ERR;
2910 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2911
2912 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2913 _syscmd(cmd, buf, sizeof(buf));
2914 if (strlen(buf) > 0)
2915 *output_int = strtol(buf, NULL, 10);
2916 else {
2917 // output the max MCS for the current radio mode
2918 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2919 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2920 return RETURN_ERR;
2921 }
2922 if (mode_bitmap & WIFI_MODE_AX) {
2923 *output_int = 11;
2924 } else if (mode_bitmap & WIFI_MODE_AC) {
2925 *output_int = 9;
2926 } else if (mode_bitmap & WIFI_MODE_N) {
2927 *output_int = 7;
2928 }
2929 }
2930 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2931
2932 return RETURN_OK;
2933}
2934
2935//Set the Modulation Coding Scheme index
2936INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2937{
2938 // 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).
2939 char config_file[64] = {0};
2940 char set_value[16] = {0};
2941 char mcs_file[32] = {0};
2942 wifi_band band = band_invalid;
2943 struct params set_config = {0};
2944 FILE *f = NULL;
2945
2946 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2947
2948 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2949
2950 // -1 means auto
2951 if (MCS > 15 || MCS < -1) {
2952 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2953 return RETURN_ERR;
2954 }
2955
2956 if (MCS > 9 || MCS == -1)
2957 strcpy(set_value, "2");
2958 else if (MCS > 7)
2959 strcpy(set_value, "1");
2960 else
2961 strcpy(set_value, "0");
2962
2963 set_config.name = "he_basic_mcs_nss_set";
2964 set_config.value = set_value;
2965
2966 wifi_hostapdWrite(config_file, &set_config, 1);
2967 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2968
2969 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2970 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2971 f = fopen(mcs_file, "w");
2972 if (f == NULL) {
2973 fprintf(stderr, "%s: fopen failed\n", __func__);
2974 return RETURN_ERR;
2975 }
2976 fprintf(f, "%d", MCS);
2977 fclose(f);
2978
2979 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2980 return RETURN_OK;
2981}
2982
2983//Get supported Transmit Power list, eg : "0,25,50,75,100"
2984//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.
2985INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2986{
2987 if (NULL == output_list)
2988 return RETURN_ERR;
2989 snprintf(output_list, 64,"0,25,50,75,100");
2990 return RETURN_OK;
2991}
2992
2993//Get current Transmit Power in dBm units.
2994//The transmite power level is in units of full power for this radio.
2995INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2996{
2997 char interface_name[16] = {0};
2998 char cmd[128]={0};
2999 char buf[16]={0};
3000 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3001
3002 if(output_ulong == NULL)
3003 return RETURN_ERR;
3004
3005 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3006 return RETURN_ERR;
3007 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
3008 _syscmd(cmd, buf, sizeof(buf));
3009
3010 *output_ulong = strtol(buf, NULL, 10);
3011
3012 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3013 return RETURN_OK;
3014}
3015
3016//Set Transmit Power
3017//The transmite power level is in units of full power for this radio.
3018INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3019{
3020 char interface_name[16] = {0};
3021 char *support;
3022 char cmd[128]={0};
3023 char buf[128]={0};
3024 char txpower_str[64] = {0};
3025 int txpower = 0;
3026 int maximum_tx = 0;
3027 int phyId = 0;
3028
3029 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3030
3031 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3032 return RETURN_ERR;
3033 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
3034 _syscmd(cmd, buf, sizeof(buf));
3035 maximum_tx = strtol(buf, NULL, 10);
3036
3037 // Get the Tx power supported list and check that is the input in the list
3038 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3039 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3040 support = strtok(buf, ",");
3041 while(true)
3042 {
3043 if(support == NULL) { // input not in the list
3044 wifi_dbg_printf("Input value is invalid.\n");
3045 return RETURN_ERR;
3046 }
3047 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3048 break;
3049 }
3050 support = strtok(NULL, ",");
3051 }
3052 txpower = TransmitPower*maximum_tx/100;
3053 phyId = radio_index_to_phy(radioIndex);
3054 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
3055 _syscmd(cmd, buf, sizeof(buf));
3056 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3057
3058 return RETURN_OK;
3059}
3060
3061//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3062INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3063{
3064 if (NULL == Supported)
3065 return RETURN_ERR;
3066 *Supported = TRUE;
3067
3068 return RETURN_OK;
3069}
3070
3071//Get 80211h feature enable
3072INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3073{
3074 char buf[64]={'\0'};
3075 char config_file[64] = {'\0'};
3076
3077 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3078 if(enable == NULL)
3079 return RETURN_ERR;
3080
3081 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3082 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
3083
3084 if (strncmp(buf, "1", 1) == 0)
3085 *enable = TRUE;
3086 else
3087 *enable = FALSE;
3088
3089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3090 return RETURN_OK;
3091}
3092
3093//Set 80211h feature enable
3094INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3095{
3096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3097 struct params params={'\0'};
3098 char config_file[MAX_BUF_SIZE] = {0};
3099
3100 params.name = "ieee80211h";
3101
3102 if (enable) {
3103 params.value = "1";
3104 } else {
3105 params.value = "0";
3106 }
3107
3108 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3109 wifi_hostapdWrite(config_file, &params, 1);
3110
3111 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3112 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3113 return RETURN_OK;
3114}
3115
3116//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.
3117INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3118{
3119 if (NULL == output)
3120 return RETURN_ERR;
3121 *output=100;
3122
3123 return RETURN_OK;
3124}
3125
3126//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.
3127INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3128{
3129 if (NULL == output)
3130 return RETURN_ERR;
3131 *output = -99;
3132
3133 return RETURN_OK;
3134}
3135
3136INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3137{
3138 return RETURN_ERR;
3139}
3140
3141
3142//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3143INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3144{
3145 char interface_name[16] = {0};
3146 char cmd[MAX_BUF_SIZE]={'\0'};
3147 char buf[MAX_CMD_SIZE]={'\0'};
3148
3149 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3150 if(output == NULL)
3151 return RETURN_ERR;
3152
3153 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3154 return RETURN_ERR;
3155 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
3156 _syscmd(cmd, buf, sizeof(buf));
3157 *output = atoi(buf);
3158
3159 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3160 return RETURN_OK;
3161}
3162
3163INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3164{
3165 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3166 struct params params={'\0'};
3167 char buf[MAX_BUF_SIZE] = {'\0'};
3168 char config_file[MAX_BUF_SIZE] = {'\0'};
3169
3170 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3171 return RETURN_ERR;
3172
3173 params.name = "beacon_int";
3174 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3175 params.value = buf;
3176
3177 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3178 wifi_hostapdWrite(config_file, &params, 1);
3179
3180 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3181 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3182 return RETURN_OK;
3183}
3184
3185//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.
3186INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3187{
3188 //TODO: need to revisit below implementation
3189 char *temp;
3190 char temp_output[128] = {0};
3191 char temp_TransmitRates[64] = {0};
3192 char config_file[64] = {0};
3193
3194 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3195 if (NULL == output)
3196 return RETURN_ERR;
3197 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3198 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3199
3200 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3201 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3202 } else {
3203 temp = strtok(temp_TransmitRates," ");
3204 while(temp!=NULL)
3205 {
3206 // Convert 100 kbps to Mbps
3207 temp[strlen(temp)-1]=0;
3208 if((temp[0]=='5') && (temp[1]=='\0'))
3209 {
3210 temp="5.5";
3211 }
3212 strcat(temp_output,temp);
3213 temp = strtok(NULL," ");
3214 if(temp!=NULL)
3215 {
3216 strcat(temp_output,",");
3217 }
3218 }
3219 strcpy(output,temp_output);
3220 }
3221 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3222 return RETURN_OK;
3223}
3224
3225INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3226{
3227 char *temp;
3228 char temp1[128];
3229 char temp_output[128];
3230 char temp_TransmitRates[128];
3231 char set[128];
3232 char sub_set[128];
3233 int set_count=0,subset_count=0;
3234 int set_index=0,subset_index=0;
3235 char *token;
3236 int flag=0, i=0;
3237 struct params params={'\0'};
3238 char config_file[MAX_BUF_SIZE] = {0};
3239 wifi_band band = wifi_index_to_band(radioIndex);
3240
3241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3242 if(NULL == TransmitRates)
3243 return RETURN_ERR;
3244 strcpy(sub_set,TransmitRates);
3245
3246 //Allow only supported Data transmit rate to be set
3247 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3248 token = strtok(sub_set,",");
3249 while( token != NULL ) /* split the basic rate to be set, by comma */
3250 {
3251 sub_set[subset_count]=atoi(token);
3252 subset_count++;
3253 token=strtok(NULL,",");
3254 }
3255 token=strtok(set,",");
3256 while(token!=NULL) /* split the supported rate by comma */
3257 {
3258 set[set_count]=atoi(token);
3259 set_count++;
3260 token=strtok(NULL,",");
3261 }
3262 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3263 {
3264 for(set_index=0;set_index < set_count;set_index++)
3265 {
3266 flag=0;
3267 if(sub_set[subset_index]==set[set_index])
3268 break;
3269 else
3270 flag=1; /* No match found */
3271 }
3272 if(flag==1)
3273 return RETURN_ERR; //If value not found return Error
3274 }
3275 strcpy(temp_TransmitRates,TransmitRates);
3276
3277 for(i=0;i<strlen(temp_TransmitRates);i++)
3278 {
3279 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3280 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
3281 {
3282 continue;
3283 }
3284 else
3285 {
3286 return RETURN_ERR;
3287 }
3288 }
3289 strcpy(temp_output,"");
3290 temp = strtok(temp_TransmitRates,",");
3291 while(temp!=NULL)
3292 {
3293 strcpy(temp1,temp);
3294 if(band == band_5)
3295 {
3296 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
3297 {
3298 return RETURN_ERR;
3299 }
3300 }
3301
3302 if(strcmp(temp,"5.5")==0)
3303 {
3304 strcpy(temp1,"55");
3305 }
3306 else
3307 {
3308 strcat(temp1,"0");
3309 }
3310 strcat(temp_output,temp1);
3311 temp = strtok(NULL,",");
3312 if(temp!=NULL)
3313 {
3314 strcat(temp_output," ");
3315 }
3316 }
3317 strcpy(TransmitRates,temp_output);
3318
3319 params.name= "basic_rates";
3320 params.value =TransmitRates;
3321
3322 wifi_dbg_printf("\n%s:",__func__);
3323 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3324 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3325 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3326 wifi_hostapdWrite(config_file,&params,1);
3327 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3328 return RETURN_OK;
3329}
3330
3331//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3332INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3333{
3334 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3335 FILE *fp = NULL;
3336 char path[256] = {0}, output_string[256] = {0};
3337 int count = 0;
3338 char *interface = NULL;
3339
3340 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3341 if (fp == NULL)
3342 {
3343 printf("Failed to run command in Function %s\n", __FUNCTION__);
3344 return RETURN_ERR;
3345 }
3346 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3347 {
3348 interface = strchr(path, '=');
3349
3350 if (interface != NULL)
3351 {
3352 strcpy(output_string, interface + 1);
3353 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3354 interface_name[count] = output_string[count];
3355
3356 interface_name[count] = '\0';
3357 }
3358 }
3359 pclose(fp);
3360 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3361 return RETURN_OK;
3362}
3363
3364INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3365{
3366 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3367 output_struct->radio_BytesSent = 0;
3368 output_struct->radio_BytesReceived = 0;
3369 output_struct->radio_PacketsSent = 0;
3370 output_struct->radio_PacketsReceived = 0;
3371 output_struct->radio_ErrorsSent = 0;
3372 output_struct->radio_ErrorsReceived = 0;
3373 output_struct->radio_DiscardPacketsSent = 0;
3374 output_struct->radio_DiscardPacketsReceived = 0;
3375 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3376 return RETURN_OK;
3377}
3378
3379
3380INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3381{
3382 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3383 CHAR buf[MAX_CMD_SIZE] = {0};
3384 CHAR Value[MAX_BUF_SIZE] = {0};
3385 FILE *fp = NULL;
3386
3387 if (ifname == NULL || strlen(ifname) <= 1)
3388 return RETURN_OK;
3389
3390 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3391 system(buf);
3392
3393 fp = fopen("/tmp/Radio_Stats.txt", "r");
3394 if(fp == NULL)
3395 {
3396 printf("/tmp/Radio_Stats.txt not exists \n");
3397 return RETURN_ERR;
3398 }
3399 fclose(fp);
3400
3401 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3402 File_Reading(buf, Value);
3403 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3404
3405 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3406 File_Reading(buf, Value);
3407 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3408
3409 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3410 File_Reading(buf, Value);
3411 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3412
3413 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3414 File_Reading(buf, Value);
3415 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3416
3417 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3418 File_Reading(buf, Value);
3419 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3420
3421 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3422 File_Reading(buf, Value);
3423 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3424
3425 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3426 File_Reading(buf, Value);
3427 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3428
3429 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3430 File_Reading(buf, Value);
3431 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3432
3433 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3434 return RETURN_OK;
3435}
3436
3437INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3438{
3439 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3440 CHAR buf[MAX_CMD_SIZE] = {0};
3441 FILE *fp = NULL;
3442 INT count = 0;
3443
3444 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3445 {
3446 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3447 File_Reading(buf, status);
3448 }
3449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3450 return RETURN_OK;
3451}
3452
3453//Get detail radio traffic static info
3454INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3455{
3456
3457#if 0
3458 //ifconfig radio_x
3459 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3460 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3461 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3462 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3463
3464 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3465 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3466 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.
3467 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.
3468
3469 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3470 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].
3471 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3472 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.
3473 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
3474 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
3475 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
3476 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
3477 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
3478
3479 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
3480 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
3481 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
3482 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.
3483
3484 return RETURN_OK;
3485#endif
3486
3487 CHAR interface_name[64] = {0};
3488 BOOL iface_status = FALSE;
3489 wifi_radioTrafficStats2_t radioTrafficStats = {0};
3490
3491 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3492 if (NULL == output_struct)
3493 return RETURN_ERR;
3494
3495 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3496 return RETURN_ERR;
3497
3498 wifi_getApEnable(radioIndex, &iface_status);
3499
3500 if (iface_status == TRUE)
3501 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3502 else
3503 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
3504
3505 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3506 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3507 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3508 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3509 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3510 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3511 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3512 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
3513
3514 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3515 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].
3516 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3517 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.
3518 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
3519 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
3520 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
3521 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
3522 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
3523
3524 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
3525 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
3526 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
3527 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.
3528
3529 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3530
3531 return RETURN_OK;
3532}
3533
3534//Set radio traffic static Measureing rules
3535INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3536{
3537 //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
3538 // Else, save the MeasuringRate and MeasuringInterval for future usage
3539
3540 return RETURN_OK;
3541}
3542
3543//To start or stop RadioTrafficStats
3544INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3545{
3546 //zqiu: If the RadioTrafficStats process running
3547 // if(enable)
3548 // return RETURN_OK.
3549 // else
3550 // Stop RadioTrafficStats process
3551 // Else
3552 // if(enable)
3553 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3554 // else
3555 // return RETURN_OK.
3556
3557 return RETURN_OK;
3558}
3559
3560//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
3561INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3562{
3563 //zqiu: Please ignor signalIndex.
3564 if (NULL == SignalLevel)
3565 return RETURN_ERR;
3566 *SignalLevel=(radioIndex==0)?-19:-19;
3567
3568 return RETURN_OK;
3569}
3570
3571//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3572INT wifi_applyRadioSettings(INT radioIndex)
3573{
3574 return RETURN_OK;
3575}
3576
3577//Get the radio index assocated with this SSID entry
3578INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3579{
3580 if(NULL == radioIndex)
3581 return RETURN_ERR;
3582 int max_radio_num = 0;
3583 wifi_getMaxRadioNumber(&max_radio_num);
3584 *radioIndex = ssidIndex%max_radio_num;
3585 return RETURN_OK;
3586}
3587
3588//Device.WiFi.SSID.{i}.Enable
3589//Get SSID enable configuration parameters (not the SSID enable status)
3590INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3591{
3592 if (NULL == output_bool)
3593 return RETURN_ERR;
3594
3595 return wifi_getApEnable(ssidIndex, output_bool);
3596}
3597
3598//Device.WiFi.SSID.{i}.Enable
3599//Set SSID enable configuration parameters
3600INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3601{
3602 return wifi_setApEnable(ssidIndex, enable);
3603}
3604
3605//Device.WiFi.SSID.{i}.Status
3606//Get the SSID enable status
3607INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3608{
3609 char cmd[MAX_CMD_SIZE]={0};
3610 char buf[MAX_BUF_SIZE]={0};
3611 BOOL output_bool;
3612
3613 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3614 if (NULL == output_string)
3615 return RETURN_ERR;
3616
3617 wifi_getApEnable(ssidIndex,&output_bool);
3618 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3619
3620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3621 return RETURN_OK;
3622}
3623
3624// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3625INT wifi_getSSIDName(INT apIndex, CHAR *output)
3626{
3627 char config_file[MAX_BUF_SIZE] = {0};
3628
3629 if (NULL == output)
3630 return RETURN_ERR;
3631
3632 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3633 wifi_hostapdRead(config_file,"ssid",output,32);
3634
3635 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3636 return RETURN_OK;
3637}
3638
3639// Set a max 32 byte string and sets an internal variable to the SSID name
3640INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3641{
3642 char str[MAX_BUF_SIZE]={'\0'};
3643 char cmd[MAX_CMD_SIZE]={'\0'};
3644 struct params params;
3645 char config_file[MAX_BUF_SIZE] = {0};
3646
3647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3648 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3649 return RETURN_ERR;
3650
3651 params.name = "ssid";
3652 params.value = ssid_string;
3653 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3654 wifi_hostapdWrite(config_file, &params, 1);
3655 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3657
3658 return RETURN_OK;
3659}
3660
3661//Get the BSSID
3662INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3663{
3664 char cmd[MAX_CMD_SIZE]="";
3665
3666 if (NULL == output_string)
3667 return RETURN_ERR;
3668
3669 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3670 {
3671 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep bssid | cut -d '=' -f2 | tr -d '\n'", CONFIG_PREFIX, ssidIndex);
3672 _syscmd(cmd, output_string, 64);
3673 return RETURN_OK;
3674 }
3675 strncpy(output_string, "\0", 1);
3676
3677 return RETURN_ERR;
3678}
3679
3680//Get the MAC address associated with this Wifi SSID
3681INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3682{
3683 wifi_getBaseBSSID(ssidIndex,output_string);
3684 return RETURN_OK;
3685}
3686
3687//Get the basic SSID traffic static info
3688//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3689//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3690INT wifi_applySSIDSettings(INT ssidIndex)
3691{
3692 char interface_name[16] = {0};
3693 BOOL status = false;
3694 char cmd[MAX_CMD_SIZE] = {0};
3695 char buf[MAX_CMD_SIZE] = {0};
3696 int apIndex, ret;
3697 int max_radio_num = 0;
3698 int radioIndex = 0;
3699
3700 wifi_getMaxRadioNumber(&max_radio_num);
3701
3702 radioIndex = ssidIndex % max_radio_num;
3703
3704 wifi_getApEnable(ssidIndex,&status);
3705 // Do not apply when ssid index is disabled
3706 if (status == false)
3707 return RETURN_OK;
3708
3709 /* Doing full remove and add for ssid Index
3710 * Not all hostapd options are supported with reload
3711 * for example macaddr_acl
3712 */
3713 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3714 return RETURN_ERR;
3715
3716 ret = wifi_setApEnable(ssidIndex,true);
3717
3718 /* Workaround for hostapd issue with multiple bss definitions
3719 * when first created interface will be removed
3720 * then all vaps other vaps on same phy are removed
3721 * after calling setApEnable to false readd all enabled vaps */
3722 for(int i=0; i < MAX_APS/max_radio_num; i++) {
3723 apIndex = max_radio_num*i+radioIndex;
3724 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
3725 return RETURN_ERR;
3726 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
3727 _syscmd(cmd, buf, sizeof(buf));
3728 if(*buf == '1')
3729 wifi_setApEnable(apIndex, true);
3730 }
3731
3732 return ret;
3733}
3734
3735struct channels_noise {
3736 int channel;
3737 int noise;
3738};
3739
3740// Return noise array for each channel
3741int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3742{
3743 char interface_name[16] = {0};
3744 FILE *f = NULL;
3745 char cmd[128] = {0};
3746 char line[256] = {0};
3747 size_t len = 0;
3748 ssize_t read = 0;
3749 int tmp = 0, arr_index = -1;
3750
3751 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3752 return RETURN_ERR;
3753 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
3754
3755 if ((f = popen(cmd, "r")) == NULL) {
3756 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3757 return RETURN_ERR;
3758 }
3759
3760 while(fgets(line, sizeof(line), f) != NULL) {
3761 if(arr_index < channels_num){
3762 sscanf(line, "%d", &tmp);
3763 if (tmp > 0) { // channel frequency, the first line must be frequency
3764 arr_index++;
3765 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3766 } else { // noise
3767 channels_noise_arr[arr_index].noise = tmp;
3768 }
3769 }else{
3770 break;
3771 }
3772 }
3773 pclose(f);
3774 return RETURN_OK;
3775}
3776
3777//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3778//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3779INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3780{
3781 int index = -1;
3782 wifi_neighbor_ap2_t *scan_array = NULL;
3783 char cmd[256]={0};
3784 char buf[128]={0};
3785 char file_name[32] = {0};
3786 char filter_SSID[32] = {0};
3787 char line[256] = {0};
3788 char interface_name[16] = {0};
3789 char *ret = NULL;
3790 int freq=0;
3791 FILE *f = NULL;
3792 size_t len=0;
3793 int channels_num = 0;
3794 int vht_channel_width = 0;
3795 int get_noise_ret = RETURN_ERR;
3796 bool filter_enable = false;
3797 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
3798 int phyId = 0;
3799
3800 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
3801
3802 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3803 return RETURN_ERR;
3804
3805 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3806 f = fopen(file_name, "r");
3807 if (f != NULL) {
3808 fgets(filter_SSID, sizeof(file_name), f);
3809 if (strlen(filter_SSID) != 0)
3810 filter_enable = true;
3811 fclose(f);
3812 }
3813
3814 phyId = radio_index_to_phy(radioIndex);
3815 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
3816 _syscmd(cmd, buf, sizeof(buf));
3817 channels_num = strtol(buf, NULL, 10);
3818
3819
3820
3821 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3822 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
3823 fprintf(stderr, "cmd: %s\n", cmd);
3824 if ((f = popen(cmd, "r")) == NULL) {
3825 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3826 return RETURN_ERR;
3827 }
3828
3829 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3830 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3831
3832 ret = fgets(line, sizeof(line), f);
3833 while (ret != NULL) {
3834 if(strstr(line, "BSS") != NULL) { // new neighbor info
3835 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3836 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3837 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
3838
3839 if (!filter_BSS) {
3840 index++;
3841 wifi_neighbor_ap2_t *tmp;
3842 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3843 if (tmp == NULL) { // no more memory to use
3844 index--;
3845 wifi_dbg_printf("%s: realloc failed\n", __func__);
3846 break;
3847 }
3848 scan_array = tmp;
3849 }
3850 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3851
3852 filter_BSS = false;
3853 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3854 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3855 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3856 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3857 } else if (strstr(line, "freq") != NULL) {
3858 sscanf(line," freq: %d", &freq);
3859 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3860
3861 if (freq >= 2412 && freq <= 2484) {
3862 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3863 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3864 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3865 }
3866 else if (freq >= 5160 && freq <= 5805) {
3867 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3868 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3869 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3870 }
3871
3872 scan_array[index].ap_Noise = 0;
3873 if (get_noise_ret == RETURN_OK) {
3874 for (int i = 0; i < channels_num; i++) {
3875 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3876 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3877 break;
3878 }
3879 }
3880 }
3881 } else if (strstr(line, "beacon interval") != NULL) {
3882 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3883 } else if (strstr(line, "signal") != NULL) {
3884 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3885 } else if (strstr(line,"SSID") != NULL) {
3886 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3887 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3888 filter_BSS = true;
3889 }
3890 } else if (strstr(line, "Supported rates") != NULL) {
3891 char SRate[80] = {0}, *tmp = NULL;
3892 memset(buf, 0, sizeof(buf));
3893 strcpy(SRate, line);
3894 tmp = strtok(SRate, ":");
3895 tmp = strtok(NULL, ":");
3896 strcpy(buf, tmp);
3897 memset(SRate, 0, sizeof(SRate));
3898
3899 tmp = strtok(buf, " \n");
3900 while (tmp != NULL) {
3901 strcat(SRate, tmp);
3902 if (SRate[strlen(SRate) - 1] == '*') {
3903 SRate[strlen(SRate) - 1] = '\0';
3904 }
3905 strcat(SRate, ",");
3906
3907 tmp = strtok(NULL, " \n");
3908 }
3909 SRate[strlen(SRate) - 1] = '\0';
3910 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3911 } else if (strstr(line, "DTIM") != NULL) {
3912 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3913 } else if (strstr(line, "VHT capabilities") != NULL) {
3914 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3915 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3916 } else if (strstr(line, "HT capabilities") != NULL) {
3917 strcat(scan_array[index].ap_SupportedStandards, ",n");
3918 strcpy(scan_array[index].ap_OperatingStandards, "n");
3919 } else if (strstr(line, "VHT operation") != NULL) {
3920 ret = fgets(line, sizeof(line), f);
3921 sscanf(line," * channel width: %d", &vht_channel_width);
3922 if(vht_channel_width == 1) {
3923 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3924 } else {
3925 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3926 }
3927 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3928 continue;
3929 } else if (strstr(line, "HT operation") != NULL) {
3930 ret = fgets(line, sizeof(line), f);
3931 sscanf(line," * secondary channel offset: %s", &buf);
3932 if (!strcmp(buf, "above")) {
3933 //40Mhz +
3934 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3935 }
3936 else if (!strcmp(buf, "below")) {
3937 //40Mhz -
3938 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3939 } else {
3940 //20Mhz
3941 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3942 }
3943 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3944 continue;
3945 } else if (strstr(line, "HE capabilities") != NULL) {
3946 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3947 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3948 ret = fgets(line, sizeof(line), f);
3949 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3950 if (strstr(line, "HE40/2.4GHz") != NULL)
3951 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
3952 else
3953 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
3954 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
3955 if (strstr(line, "HE80/5GHz") != NULL) {
3956 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3957 ret = fgets(line, sizeof(line), f);
3958 } else
3959 continue;
3960 if (strstr(line, "HE160/5GHz") != NULL)
3961 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
3962 }
3963 continue;
3964 } else if (strstr(line, "WPA") != NULL) {
3965 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3966 } else if (strstr(line, "RSN") != NULL) {
3967 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3968 } else if (strstr(line, "Group cipher") != NULL) {
3969 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3970 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3971 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3972 }
3973 }
3974 ret = fgets(line, sizeof(line), f);
3975 }
3976
3977 if (!filter_BSS) {
3978 *output_array_size = index + 1;
3979 } else {
3980 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3981 *output_array_size = index;
3982 }
3983 *neighbor_ap_array = scan_array;
3984 pclose(f);
3985 free(channels_noise_arr);
3986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3987 return RETURN_OK;
3988}
3989
3990//>> Deprecated: used for old RDKB code.
3991INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3992{
3993 INT status = RETURN_ERR;
3994
3995 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3996 output_struct->wifi_PLCPErrorCount = 0;
3997 output_struct->wifi_FCSErrorCount = 0;
3998 output_struct->wifi_InvalidMACCount = 0;
3999 output_struct->wifi_PacketsOtherReceived = 0;
4000 output_struct->wifi_Noise = 0;
4001 status = RETURN_OK;
4002 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4003 return status;
4004}
4005
4006INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4007{
4008 char interface_name[16] = {0};
4009 char cmd[128] = {0};
4010 char buf[1280] = {0};
4011 char *pos = NULL;
4012
4013 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4014 if (NULL == output_struct)
4015 return RETURN_ERR;
4016
4017 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4018 return RETURN_ERR;
4019
4020 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4021
4022 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
4023 _syscmd(cmd, buf, sizeof(buf));
4024
4025 pos = buf;
4026 if ((pos = strstr(pos, "RX packets:")) == NULL)
4027 return RETURN_ERR;
4028 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4029
4030 if ((pos = strstr(pos, "TX packets:")) == NULL)
4031 return RETURN_ERR;
4032 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4033
4034 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4035 return RETURN_ERR;
4036 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4037
4038 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4039 return RETURN_ERR;
4040 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4041
4042 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
4043 _syscmd(cmd, buf, sizeof(buf));
4044 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4045
4046#if 0
4047 //TODO: need to revisit below implementation
4048 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4049 char interface_name[MAX_BUF_SIZE] = {0};
4050 char interface_status[MAX_BUF_SIZE] = {0};
4051 char Value[MAX_BUF_SIZE] = {0};
4052 char buf[MAX_CMD_SIZE] = {0};
4053 char cmd[MAX_CMD_SIZE] = {0};
4054 FILE *fp = NULL;
4055
4056 if (NULL == output_struct) {
4057 return RETURN_ERR;
4058 }
4059
4060 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4061
4062 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4063 {
4064 if(apIndex == 0) //private_wifi for 2.4G
4065 {
4066 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4067 }
4068 else if(apIndex == 1) //private_wifi for 5G
4069 {
4070 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4071 }
4072 else if(apIndex == 4) //public_wifi for 2.4G
4073 {
4074 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4075 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4076 {
4077 return RETURN_ERR;
4078 }
4079 if(buf[0] == '#')//tp-link
4080 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4081 else//tenda
4082 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
4083 }
4084 else if(apIndex == 5) //public_wifi for 5G
4085 {
4086 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4087 }
4088
4089 GetIfacestatus(interface_name, interface_status);
4090
4091 if(0 != strcmp(interface_status, "1"))
4092 return RETURN_ERR;
4093
4094 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4095 system(cmd);
4096
4097 fp = fopen("/tmp/SSID_Stats.txt", "r");
4098 if(fp == NULL)
4099 {
4100 printf("/tmp/SSID_Stats.txt not exists \n");
4101 return RETURN_ERR;
4102 }
4103 fclose(fp);
4104
4105 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4106 File_Reading(buf, Value);
4107 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4108
4109 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4110 File_Reading(buf, Value);
4111 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4112
4113 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4114 File_Reading(buf, Value);
4115 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4116
4117 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4118 File_Reading(buf, Value);
4119 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4120
4121 /* There is no specific parameter from caller to associate the value wifi_Associations */
4122 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4123 //_syscmd(cmd, buf, sizeof(buf));
4124 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4125 }
4126#endif
4127 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4128 return RETURN_OK;
4129}
4130
4131INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4132{
4133 char interface_name[MAX_BUF_SIZE] = {0};
4134 char interface_status[MAX_BUF_SIZE] = {0};
4135 char Value[MAX_BUF_SIZE] = {0};
4136 char buf[MAX_CMD_SIZE] = {0};
4137 char cmd[MAX_CMD_SIZE] = {0};
4138 FILE *fp = NULL;
4139
4140 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4141 if (NULL == output_struct)
4142 return RETURN_ERR;
4143
4144 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4145
4146 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
4147 return RETURN_ERR;
4148 GetIfacestatus(interface_name, interface_status);
4149
4150 if(0 != strcmp(interface_status, "1"))
4151 return RETURN_ERR;
4152
4153 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4154 system(cmd);
4155
4156 fp = fopen("/tmp/SSID_Stats.txt", "r");
4157 if(fp == NULL)
4158 {
4159 printf("/tmp/SSID_Stats.txt not exists \n");
4160 return RETURN_ERR;
4161 }
4162 fclose(fp);
4163
4164 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4165 File_Reading(buf, Value);
4166 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4167
4168 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4169 File_Reading(buf, Value);
4170 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4171
4172 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4173 File_Reading(buf, Value);
4174 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4175
4176 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4177 File_Reading(buf, Value);
4178 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4179
4180 output_struct->wifi_UnicastPacketsSent = 0;
4181 output_struct->wifi_UnicastPacketsReceived = 0;
4182 output_struct->wifi_MulticastPacketsSent = 0;
4183 output_struct->wifi_MulticastPacketsReceived = 0;
4184 output_struct->wifi_BroadcastPacketsSent = 0;
4185 output_struct->wifi_BroadcastPacketsRecevied = 0;
4186 output_struct->wifi_UnknownPacketsReceived = 0;
4187
4188 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4189 return RETURN_OK;
4190}
4191
4192INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4193{
4194 INT status = RETURN_ERR;
4195
4196 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4197 //Below values should get updated from hal
4198 output_struct->wifi_RetransCount=0;
4199 output_struct->wifi_FailedRetransCount=0;
4200 output_struct->wifi_RetryCount=0;
4201 output_struct->wifi_MultipleRetryCount=0;
4202 output_struct->wifi_ACKFailureCount=0;
4203 output_struct->wifi_AggregatedPacketCount=0;
4204
4205 status = RETURN_OK;
4206 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4207
4208 return status;
4209}
4210
4211INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4212{
4213 INT status = RETURN_ERR;
4214 UINT index;
4215 wifi_neighbor_ap_t *pt=NULL;
4216
4217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4218 *output_array_size=2;
4219 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4220 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4221 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4222 strcpy(pt->ap_Radio,"");
4223 strcpy(pt->ap_SSID,"");
4224 strcpy(pt->ap_BSSID,"");
4225 strcpy(pt->ap_Mode,"");
4226 pt->ap_Channel=1;
4227 pt->ap_SignalStrength=0;
4228 strcpy(pt->ap_SecurityModeEnabled,"");
4229 strcpy(pt->ap_EncryptionMode,"");
4230 strcpy(pt->ap_OperatingFrequencyBand,"");
4231 strcpy(pt->ap_SupportedStandards,"");
4232 strcpy(pt->ap_OperatingStandards,"");
4233 strcpy(pt->ap_OperatingChannelBandwidth,"");
4234 pt->ap_BeaconPeriod=1;
4235 pt->ap_Noise=0;
4236 strcpy(pt->ap_BasicDataTransferRates,"");
4237 strcpy(pt->ap_SupportedDataTransferRates,"");
4238 pt->ap_DTIMPeriod=1;
4239 pt->ap_ChannelUtilization = 1;
4240 }
4241
4242 status = RETURN_OK;
4243 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4244
4245 return status;
4246}
4247
4248//----------------- AP HAL -------------------------------
4249
4250//>> Deprecated: used for old RDKB code.
4251INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4252{
4253 if (NULL == output_ulong || NULL == output_struct)
4254 return RETURN_ERR;
4255 *output_ulong = 0;
4256 *output_struct = NULL;
4257 return RETURN_OK;
4258}
4259
4260#ifdef HAL_NETLINK_IMPL
4261static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4262 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4263 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4264 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4265 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4266 char mac_addr[20];
4267 static int count=0;
4268 int rate=0;
4269
4270 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4271
4272 nla_parse(tb,
4273 NL80211_ATTR_MAX,
4274 genlmsg_attrdata(gnlh, 0),
4275 genlmsg_attrlen(gnlh, 0),
4276 NULL);
4277
4278 if(!tb[NL80211_ATTR_STA_INFO]) {
4279 fprintf(stderr, "sta stats missing!\n");
4280 return NL_SKIP;
4281 }
4282
4283
4284 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4285 fprintf(stderr, "failed to parse nested attributes!\n");
4286 return NL_SKIP;
4287 }
4288
4289 //devIndex starts from 1
4290 if( ++count == out->wifi_devIndex )
4291 {
4292 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4293 //Getting the mac addrress
4294 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4295
4296 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4297 fprintf(stderr, "failed to parse nested rate attributes!");
4298 return NL_SKIP;
4299 }
4300
4301 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4302 if(rinfo[NL80211_RATE_INFO_BITRATE])
4303 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4304 out->wifi_devTxRate = rate/10;
4305 }
4306
4307 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4308 fprintf(stderr, "failed to parse nested rate attributes!");
4309 return NL_SKIP;
4310 }
4311
4312 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4313 if(rinfo[NL80211_RATE_INFO_BITRATE])
4314 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4315 out->wifi_devRxRate = rate/10;
4316 }
4317 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4318 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4319
4320 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4321 count = 0; //starts the count for next cycle
4322 return NL_STOP;
4323 }
4324
4325 return NL_SKIP;
4326
4327}
4328#endif
4329
4330INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4331{
4332#ifdef HAL_NETLINK_IMPL
4333 Netlink nl = {0};
4334 char if_name[10] = {0};
4335 char interface_name[16] = {0};
4336
4337 wifi_device_info_t info = {0};
4338 info.wifi_devIndex = devIndex;
4339
4340 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4341 return RETURN_ERR;
4342
4343 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4344
4345 nl.id = initSock80211(&nl);
4346
4347 if (nl.id < 0) {
4348 fprintf(stderr, "Error initializing netlink \n");
4349 return -1;
4350 }
4351
4352 struct nl_msg* msg = nlmsg_alloc();
4353
4354 if (!msg) {
4355 fprintf(stderr, "Failed to allocate netlink message.\n");
4356 nlfree(&nl);
4357 return -2;
4358 }
4359
4360 genlmsg_put(msg,
4361 NL_AUTO_PORT,
4362 NL_AUTO_SEQ,
4363 nl.id,
4364 0,
4365 NLM_F_DUMP,
4366 NL80211_CMD_GET_STATION,
4367 0);
4368
4369 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4370 nl_send_auto(nl.socket, msg);
4371 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4372 nl_recvmsgs(nl.socket, nl.cb);
4373 nlmsg_free(msg);
4374 nlfree(&nl);
4375
4376 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4377 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4378 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4379 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4380 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4381 return RETURN_OK;
4382#else
4383 //iw utility to retrieve station information
4384#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4385#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4386#define MACFILE "/tmp/wifi_AssoMac.txt"
4387#define TXRATEFILE "/tmp/wifi_txrate.txt"
4388#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4389 FILE *file = NULL;
4390 char if_name[10] = {'\0'};
4391 char pipeCmd[256] = {'\0'};
4392 char line[256] = {0};
4393 char interface_name[16] = {0};
4394 int count = 0, device = 0;
4395
4396 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4397 return RETURN_ERR;
4398
4399 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4400
4401 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4402 file = popen(pipeCmd, "r");
4403
4404 if(file == NULL)
4405 return RETURN_ERR; //popen failed
4406
4407 fgets(line, sizeof line, file);
4408 device = atoi(line);
4409 pclose(file);
4410
4411 if(device == 0)
4412 return RETURN_ERR; //No devices are connected
4413
4414 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4415 system(pipeCmd);
4416
4417 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4418
4419 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4420
4421 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4422
4423 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4424
4425 //devIndex starts from 1, ++count
4426 if((file = fopen(SIGNALFILE, "r")) != NULL )
4427 {
4428 for(count =0;fgets(line, sizeof line, file) != NULL;)
4429 {
4430 if (++count == devIndex)
4431 {
4432 output_struct->wifi_devSignalStrength = atoi(line);
4433 break;
4434 }
4435 }
4436 fclose(file);
4437 }
4438 else
4439 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4440
4441 if((file = fopen(MACFILE, "r")) != NULL )
4442 {
4443 for(count =0;fgets(line, sizeof line, file) != NULL;)
4444 {
4445 if (++count == devIndex)
4446 {
4447 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]);
4448 break;
4449 }
4450 }
4451 fclose(file);
4452 }
4453 else
4454 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4455
4456 if((file = fopen(TXRATEFILE, "r")) != NULL )
4457 {
4458 for(count =0;fgets(line, sizeof line, file) != NULL;)
4459 {
4460 if (++count == devIndex)
4461 {
4462 output_struct->wifi_devTxRate = atoi(line);
4463 break;
4464 }
4465 }
4466 fclose(file);
4467 }
4468 else
4469 fprintf(stderr,"fopen wifi_txrate.txt failed");
4470
4471 if((file = fopen(RXRATEFILE, "r")) != NULL)
4472 {
4473 for(count =0;fgets(line, sizeof line, file) != NULL;)
4474 {
4475 if (++count == devIndex)
4476 {
4477 output_struct->wifi_devRxRate = atoi(line);
4478 break;
4479 }
4480 }
4481 fclose(file);
4482 }
4483 else
4484 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4485
4486 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4487
4488 return RETURN_OK;
4489#endif
4490}
4491
4492INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4493{
4494 if (NULL == device)
4495 return RETURN_ERR;
4496 return RETURN_OK;
4497}
4498//<<
4499
4500
4501//--------------wifi_ap_hal-----------------------------
4502//enables CTS protection for the radio used by this AP
4503INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4504{
4505 //save config and Apply instantly
4506 return RETURN_ERR;
4507}
4508
4509// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4510INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4511{
4512 char config_file[64] = {'\0'};
4513 char buf[64] = {'\0'};
4514 struct params list;
4515
4516 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4517 list.name = "ht_coex";
4518 snprintf(buf, sizeof(buf), "%d", enable);
4519 list.value = buf;
4520
4521 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4522 wifi_hostapdWrite(config_file, &list, 1);
4523 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4524
4525 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4526
4527 return RETURN_OK;
4528}
4529
4530//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4531INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4532{
4533 char config_file[MAX_BUF_SIZE] = {'\0'};
4534 char buf[MAX_BUF_SIZE] = {'\0'};
4535 struct params list;
4536
4537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4538 if (threshold < 256 || threshold > 2346 )
4539 return RETURN_ERR;
4540 list.name = "fragm_threshold";
4541 snprintf(buf, sizeof(buf), "%d", threshold);
4542 list.value = buf;
4543
4544 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4545 wifi_hostapdWrite(config_file, &list, 1);
4546 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4547
4548 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4549
4550 return RETURN_OK;
4551}
4552
4553// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4554INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4555{
4556 char config_file[64] = {'\0'};
4557 char cmd[512] = {'\0'};
4558 char buf[512] = {'\0'};
4559 char stbc_config[16] = {'\0'};
4560 wifi_band band;
4561 int iterator = 0;
4562 BOOL current_stbc = FALSE;
4563 int ant_count = 0;
4564 int ant_bitmap = 0;
4565 struct params list;
4566
4567 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4568
4569 band = wifi_index_to_band(radioIndex);
4570 if (band == band_invalid)
4571 return RETURN_ERR;
4572
4573 if (band == band_2_4)
4574 iterator = 1;
4575 else if (band == band_5)
4576 iterator = 2;
4577 else
4578 return RETURN_OK;
4579
4580 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4581 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4582 ant_count += ant_bitmap & 1;
4583
4584 if (ant_count == 1 && STBC_Enable == TRUE) {
4585 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4586 return RETURN_OK;
4587 }
4588
4589 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4590
4591 // set ht and vht config
4592 for (int i = 0; i < iterator; i++) {
4593 memset(stbc_config, 0, sizeof(stbc_config));
4594 memset(cmd, 0, sizeof(cmd));
4595 memset(buf, 0, sizeof(buf));
4596 list.name = (i == 0)?"ht_capab":"vht_capab";
4597 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
4598 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4599 _syscmd(cmd, buf, sizeof(buf));
4600 if (strlen(buf) != 0)
4601 current_stbc = TRUE;
4602 if (current_stbc == STBC_Enable)
4603 continue;
4604
4605 if (STBC_Enable == TRUE) {
4606 // Append the STBC flags in capab config
4607 memset(cmd, 0, sizeof(cmd));
4608 if (i == 0)
4609 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4610 else
4611 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4612 _syscmd(cmd, buf, sizeof(buf));
4613 } else if (STBC_Enable == FALSE) {
4614 // Remove the STBC flags and remain other flags in capab
4615 memset(cmd, 0, sizeof(cmd));
4616 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4617 _syscmd(cmd, buf, sizeof(buf));
4618 memset(cmd, 0, sizeof(cmd));
4619 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4620 _syscmd(cmd, buf, sizeof(buf));
4621 }
4622 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4623 list.value = buf;
4624 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4625 }
4626
4627 wifi_reloadAp(radioIndex);
4628
4629 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4630 return RETURN_OK;
4631}
4632
4633// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4634INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4635{
4636 char cmd[128] = {0};
4637 char buf[128] = {0};
4638 char interface_name[16] = {0};
4639
4640 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4641
4642 if(output_bool == NULL)
4643 return RETURN_ERR;
4644
4645 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4646 return RETURN_ERR;
4647
4648 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4649 _syscmd(cmd, buf, sizeof(buf));
4650
4651 if (strncmp(buf, "1", 1) == 0)
4652 *output_bool = TRUE;
4653 else
4654 *output_bool = FALSE;
4655
4656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4657 return RETURN_OK;
4658}
4659
4660// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4661INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4662{
4663 char config_file[128] = {0};
4664 struct params list = {0};
4665 BOOL enable;
4666
4667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4668
4669 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
4670 return RETURN_ERR;
4671
4672 if (amsduEnable == enable)
4673 return RETURN_OK;
4674
4675 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4676 list.name = "amsdu";
4677 list.value = amsduEnable? "1":"0";
4678 wifi_hostapdWrite(config_file, &list, 1);
4679 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4680 wifi_reloadAp(radioIndex);
4681
4682 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4683 return RETURN_OK;
4684}
4685
4686//P2 // outputs the number of Tx streams
4687INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4688{
4689 char buf[8] = {0};
4690 char cmd[128] = {0};
4691 int phyId = 0;
4692
4693 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4694
4695 phyId = radio_index_to_phy(radioIndex);
4696 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
4697 _syscmd(cmd, buf, sizeof(buf));
4698
4699 *output_int = (INT)strtol(buf, NULL, 16);
4700
4701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4702
4703 return RETURN_OK;
4704}
4705
4706INT fitChainMask(INT radioIndex, int antcount)
4707{
4708 char buf[128] = {0};
4709 char cmd[128] = {0};
4710 char config_file[64] = {0};
4711 wifi_band band;
4712 struct params list[2] = {0};
4713
4714 band = wifi_index_to_band(radioIndex);
4715 if (band == band_invalid)
4716 return RETURN_ERR;
4717
4718 list[0].name = "he_mu_beamformer";
4719 list[1].name = "he_su_beamformer";
4720
4721 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4722 if (antcount == 1) {
4723 // remove config about multiple antennas
4724 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4725 _syscmd(cmd, buf, sizeof(buf));
4726
4727 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4728 _syscmd(cmd, buf, sizeof(buf));
4729
4730 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4731 _syscmd(cmd, buf, sizeof(buf));
4732
4733 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4734 _syscmd(cmd, buf, sizeof(buf));
4735
4736 list[0].value = "0";
4737 list[1].value = "0";
4738 } else {
4739 // If we only set RX STBC means STBC is enable and TX STBC is disable when last time set one antenna. so we need to add it back.
4740 if (band == band_2_4 || band == band_5) {
4741 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4742 _syscmd(cmd, buf, sizeof(buf));
4743 if (strlen(buf) > 0) {
4744 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4745 _syscmd(cmd, buf, sizeof(buf));
4746 }
4747 }
4748 if (band == band_5) {
4749 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4750 _syscmd(cmd, buf, sizeof(buf));
4751 if (strlen(buf) > 0) {
4752 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4753 _syscmd(cmd, buf, sizeof(buf));
4754 }
4755 }
4756
4757 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4758 _syscmd(cmd, buf, sizeof(buf));
4759 if (strlen(buf) == 0) {
4760 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4761 _syscmd(cmd, buf, sizeof(buf));
4762 }
4763
4764 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4765 _syscmd(cmd, buf, sizeof(buf));
4766 if (strlen(buf) == 0) {
4767 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4768 _syscmd(cmd, buf, sizeof(buf));
4769 }
4770
4771 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4772 _syscmd(cmd, buf, sizeof(buf));
4773 if (strlen(buf) == 0) {
4774 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4775 } else {
4776 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4777 }
4778 _syscmd(cmd, buf, sizeof(buf));
4779
4780 list[0].value = "1";
4781 list[1].value = "1";
4782 }
4783 wifi_hostapdWrite(config_file, list, 2);
4784}
4785
4786//P2 // sets the number of Tx streams to an enviornment variable
4787INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4788{
4789 char cmd[128] = {0};
4790 char buf[128] = {0};
4791 int phyId = 0;
4792 int cur_mask = 0;
4793 int antcount = 0;
4794 wifi_band band;
4795
4796 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4797
4798 if (numStreams <= 0) {
4799 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
4800 return RETURN_ERR;
4801 }
4802
4803 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
4804 if (cur_mask == numStreams)
4805 return RETURN_OK;
4806
4807 wifi_setRadioEnable(radioIndex, FALSE);
4808
4809 phyId = radio_index_to_phy(radioIndex);
4810 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
4811 _syscmd(cmd, buf, sizeof(buf));
4812
4813 if (strlen(buf) > 0) {
4814 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4815 return RETURN_ERR;
4816 }
4817
4818 // if chain mask changed, we need to make the hostapd config valid.
4819 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
4820 antcount += cur_mask & 1;
4821 }
4822 fitChainMask(radioIndex, antcount);
4823
4824 wifi_setRadioEnable(radioIndex, TRUE);
4825
4826 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4827 return RETURN_OK;
4828}
4829
4830//P2 // outputs the number of Rx streams
4831INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4832{
4833 char buf[8] = {0};
4834 char cmd[128] = {0};
4835 int phyId = 0;
4836
4837 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4838
4839 phyId = radio_index_to_phy(radioIndex);
4840 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
4841 _syscmd(cmd, buf, sizeof(buf));
4842
4843 *output_int = (INT)strtol(buf, NULL, 16);
4844
4845 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4846
4847 return RETURN_OK;
4848}
4849
4850//P2 // sets the number of Rx streams to an enviornment variable
4851INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4852{
4853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4854 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4855 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4856 return RETURN_ERR;
4857 }
4858 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4859 return RETURN_ERR;
4860}
4861
4862//Get radio RDG enable setting
4863INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4864{
4865 if (NULL == output_bool)
4866 return RETURN_ERR;
4867 *output_bool = TRUE;
4868 return RETURN_OK;
4869}
4870
4871//Get radio RDG enable setting
4872INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4873{
4874 if (NULL == output_bool)
4875 return RETURN_ERR;
4876 *output_bool = TRUE;
4877 return RETURN_OK;
4878}
4879
4880//Set radio RDG enable setting
4881INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4882{
4883 return RETURN_ERR;
4884}
4885
4886//Get radio ADDBA enable setting
4887INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4888{
4889 if (NULL == output_bool)
4890 return RETURN_ERR;
4891 *output_bool = TRUE;
4892 return RETURN_OK;
4893}
4894
4895//Set radio ADDBA enable setting
4896INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4897{
4898 return RETURN_ERR;
4899}
4900
4901//Get radio auto block ack enable setting
4902INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4903{
4904 if (NULL == output_bool)
4905 return RETURN_ERR;
4906 *output_bool = TRUE;
4907 return RETURN_OK;
4908}
4909
4910//Set radio auto block ack enable setting
4911INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4912{
4913 return RETURN_ERR;
4914}
4915
4916//Get radio 11n pure mode enable support
4917INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4918{
4919 if (NULL == output_bool)
4920 return RETURN_ERR;
4921 *output_bool = TRUE;
4922 return RETURN_OK;
4923}
4924
4925//Get radio 11n pure mode enable setting
4926INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4927{
4928 if (NULL == output_bool)
4929 return RETURN_ERR;
4930 *output_bool = TRUE;
4931 return RETURN_OK;
4932}
4933
4934//Set radio 11n pure mode enable setting
4935INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4936{
4937 return RETURN_ERR;
4938}
4939
4940//Get radio IGMP snooping enable setting
4941INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4942{
4943 char interface_name[16] = {0};
4944 char cmd[128]={0};
4945 char buf[4]={0};
4946 bool bridge = FALSE, mac80211 = FALSE;
4947 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4948
4949 if(output_bool == NULL)
4950 return RETURN_ERR;
4951
4952 *output_bool = FALSE;
4953
4954 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4955 _syscmd(cmd, buf, sizeof(buf));
4956 if (strncmp(buf, "1", 1) == 0)
4957 bridge = TRUE;
4958
4959 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4960 return RETURN_ERR;
4961 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
4962 _syscmd(cmd, buf, sizeof(buf));
4963 if (strncmp(buf, "1", 1) == 0)
4964 mac80211 = TRUE;
4965
4966 if (bridge && mac80211)
4967 *output_bool = TRUE;
4968
4969 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4970 return RETURN_OK;
4971}
4972
4973//Set radio IGMP snooping enable setting
4974INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4975{
4976 char interface_name[16] = {0};
4977 char cmd[128]={0};
4978 char buf[4]={0};
4979 int max_num_radios =0;
4980 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4981
4982 // bridge
4983 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4984 _syscmd(cmd, buf, sizeof(buf));
4985
4986 wifi_getMaxRadioNumber(&max_num_radios);
4987 // mac80211
4988 for (int i = 0; i < max_num_radios; i++) {
4989 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
4990 return RETURN_ERR;
4991 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
4992 _syscmd(cmd, buf, sizeof(buf));
4993 }
4994 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4995 return RETURN_OK;
4996}
4997
4998//Get the Reset count of radio
4999INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5000{
5001 if (NULL == output_int)
5002 return RETURN_ERR;
5003 *output_int = (radioIndex==0)? 1: 3;
5004
5005 return RETURN_OK;
5006}
5007
5008
5009//---------------------------------------------------------------------------------------------------
5010//
5011// Additional Wifi AP level APIs used for Access Point devices
5012//
5013//---------------------------------------------------------------------------------------------------
5014
5015// creates a new ap and pushes these parameters to the hardware
5016INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5017{
5018 // Deprecated when use hal version 3, use wifi_createVap() instead.
5019 return RETURN_OK;
5020}
5021
5022// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5023INT wifi_deleteAp(INT apIndex)
5024{
5025 char interface_name[16] = {0};
5026 char buf[1024];
5027 char cmd[128];
5028
5029 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5030 return RETURN_ERR;
5031 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
5032 _syscmd(cmd, buf, sizeof(buf));
5033
5034 wifi_removeApSecVaribles(apIndex);
5035
5036 return RETURN_OK;
5037}
5038
5039// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5040INT wifi_getApName(INT apIndex, CHAR *output_string)
5041{
5042 char interface_name[16] = {0};
5043 if(NULL == output_string)
5044 return RETURN_ERR;
5045
5046 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5047 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
5048 else
5049 snprintf(output_string, 16, "%s", interface_name);
5050 return RETURN_OK;
5051}
5052
5053// Outputs the index number in that corresponds to the SSID string
5054INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5055{
5056 char cmd [128] = {0};
5057 char buf[32] = {0};
5058 char *apIndex_str = NULL;
5059 bool enable = FALSE;
5060
5061 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5062 _syscmd(cmd, buf, sizeof(buf));
5063
5064 if (strlen(buf) != 0) {
5065 apIndex_str = strtok(buf, "\n");
5066 *output_int = strtoul(apIndex_str, NULL, 10);
5067 return RETURN_OK;
5068 }
5069
5070 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5071 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5072 if (apIndex_str) {
5073 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5074 return RETURN_OK;
5075 }
5076 *output_int = -1;
5077 return RETURN_OK;
5078}
5079
5080INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5081{
5082 return wifi_getIndexFromName(inputSsidString, output_int);
5083}
5084
5085// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5086INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5087{
5088 char buf[MAX_BUF_SIZE] = {0};
5089 char cmd[MAX_CMD_SIZE] = {0};
5090 char config_file[MAX_BUF_SIZE] = {0};
5091
5092 if(NULL == output_string)
5093 return RETURN_ERR;
5094
5095 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5096 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5097 if((strcmp(buf,"3")==0))
5098 snprintf(output_string, 32, "WPAand11i");
5099 else if((strcmp(buf,"2")==0))
5100 snprintf(output_string, 32, "11i");
5101 else if((strcmp(buf,"1")==0))
5102 snprintf(output_string, 32, "WPA");
5103 else
5104 snprintf(output_string, 32, "None");
5105
5106 return RETURN_OK;
5107}
5108
5109// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5110INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5111{
5112 char config_file[MAX_BUF_SIZE] = {0};
5113 struct params list;
5114
5115 if (NULL == beaconTypeString)
5116 return RETURN_ERR;
5117 list.name = "wpa";
5118 list.value = "0";
5119
5120 if((strcmp(beaconTypeString,"WPAand11i")==0))
5121 list.value="3";
5122 else if((strcmp(beaconTypeString,"11i")==0))
5123 list.value="2";
5124 else if((strcmp(beaconTypeString,"WPA")==0))
5125 list.value="1";
5126
5127 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5128 wifi_hostapdWrite(config_file, &list, 1);
5129 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5130 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5131 return RETURN_OK;
5132}
5133
5134// sets the beacon interval on the hardware for this AP
5135INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5136{
5137 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5138 struct params params={'\0'};
5139 char buf[MAX_BUF_SIZE] = {'\0'};
5140 char config_file[MAX_BUF_SIZE] = {'\0'};
5141
5142 params.name = "beacon_int";
5143 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5144 params.value = buf;
5145
5146 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5147 wifi_hostapdWrite(config_file, &params, 1);
5148
5149 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5150 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5151 return RETURN_OK;
5152}
5153
5154INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5155{
5156 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5157 return RETURN_ERR;
5158 return RETURN_OK;
5159}
5160
5161// Get the packet size threshold supported.
5162INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5163{
5164 //save config and apply instantly
5165 if (NULL == output_bool)
5166 return RETURN_ERR;
5167 *output_bool = TRUE;
5168 return RETURN_OK;
5169}
5170
5171// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5172INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5173{
5174 char interface_name[16] = {0};
5175 char buf[16] = {0};
5176 char config_file[128] = {0};
5177 struct params param = {0};
5178
5179 if (threshold > 65535) {
5180 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5181 return RETURN_ERR;
5182 }
5183
5184 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5185 return RETURN_ERR;
5186 snprintf(config_file, sizeof(config_file), "%s.conf", interface_name);
5187 snprintf(buf, sizeof(buf), "%u", threshold);
5188 param.name = "rts_threshold";
5189 param.value = buf;
5190 wifi_hostapdWrite(config_file, &param, 1);
5191 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5192 wifi_reloadAp(apIndex);
5193
5194 return RETURN_OK;
5195}
5196
5197// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5198INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5199{
5200 if (NULL == output_string)
5201 return RETURN_ERR;
5202 snprintf(output_string, 32, "TKIPandAESEncryption");
5203 return RETURN_OK;
5204
5205}
5206
5207// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5208INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5209{
5210 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5211 char *param_name = NULL;
5212 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
5213
5214 if(NULL == output_string)
5215 return RETURN_ERR;
5216
5217 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5218 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5219
5220 if(strcmp(buf,"0")==0)
5221 {
5222 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5223 snprintf(output_string, 32, "None");
5224 return RETURN_OK;
5225 }
5226 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5227 param_name = "rsn_pairwise";
5228 else if((strcmp(buf,"1")==0))
5229 param_name = "wpa_pairwise";
5230 else
5231 return RETURN_ERR;
5232 memset(output_string,'\0',32);
5233 wifi_hostapdRead(config_file,param_name,output_string,32);
5234 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5235 param_name = "wpa_pairwise";
5236 memset(output_string, '\0', 32);
5237 wifi_hostapdRead(config_file, param_name, output_string, 32);
5238 }
5239 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5240
5241 if(strcmp(output_string,"TKIP") == 0)
5242 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5243 else if(strcmp(output_string,"CCMP") == 0)
5244 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5245 else if(strcmp(output_string,"TKIP CCMP") == 0)
5246 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5247
5248 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5249 return RETURN_OK;
5250}
5251
5252// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5253INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5254{
5255 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5256 struct params params={'\0'};
5257 char output_string[32];
5258 char config_file[MAX_BUF_SIZE] = {0};
5259
5260 memset(output_string,'\0',32);
5261 wifi_getApWpaEncryptionMode(apIndex,output_string);
5262
5263 if(strcmp(encMode, "TKIPEncryption") == 0)
5264 params.value = "TKIP";
5265 else if(strcmp(encMode,"AESEncryption") == 0)
5266 params.value = "CCMP";
5267 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5268 params.value = "TKIP CCMP";
5269
5270 if((strcmp(output_string,"WPAand11i")==0))
5271 {
5272 params.name = "wpa_pairwise";
5273 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5274 wifi_hostapdWrite(config_file, &params, 1);
5275 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5276
5277 params.name = "rsn_pairwise";
5278 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5279 wifi_hostapdWrite(config_file, &params, 1);
5280 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5281
5282 return RETURN_OK;
5283 }
5284 else if((strcmp(output_string,"11i")==0))
5285 {
5286 params.name = "rsn_pairwise";
5287 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5288 wifi_hostapdWrite(config_file, &params, 1);
5289 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5290 return RETURN_OK;
5291 }
5292 else if((strcmp(output_string,"WPA")==0))
5293 {
5294 params.name = "wpa_pairwise";
5295 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5296 wifi_hostapdWrite(config_file, &params, 1);
5297 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5298 return RETURN_OK;
5299 }
5300
5301 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5302 return RETURN_OK;
5303}
5304
5305// deletes internal security varable settings for this ap
5306INT wifi_removeApSecVaribles(INT apIndex)
5307{
5308 //TODO: remove the entry in hostapd config file
5309 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
5310 //_syscmd(cmd, buf, sizeof(buf));
5311
5312 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
5313 //_syscmd(cmd, buf, sizeof(buf));
5314 return RETURN_ERR;
5315}
5316
5317// changes the hardware settings to disable encryption on this ap
5318INT wifi_disableApEncryption(INT apIndex)
5319{
5320 //Apply instantly
5321 return RETURN_ERR;
5322}
5323
5324// set the authorization mode on this ap
5325// mode mapping as: 1: open, 2: shared, 4:auto
5326INT wifi_setApAuthMode(INT apIndex, INT mode)
5327{
5328 struct params params={0};
5329 char config_file[64] = {0};
5330 int ret;
5331
5332 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5333
5334 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5335 params.name = "auth_algs";
5336
5337 if (mode & 1 && mode & 2)
5338 params.value = "3";
5339 else if (mode & 2)
5340 params.value = "2";
5341 else if (mode & 1)
5342 params.value = "1";
5343 else
5344 params.value = "0";
5345
5346 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5347 wifi_hostapdWrite(config_file, &params, 1);
5348 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5349 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5350
5351 return RETURN_OK;
5352}
5353
5354// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5355INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5356{
5357 //save to wifi config, and wait for wifi restart to apply
5358 struct params params={'\0'};
5359 char config_file[MAX_BUF_SIZE] = {0};
5360 int ret;
5361
5362 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5363 if(authMode == NULL)
5364 return RETURN_ERR;
5365
5366 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5367 params.name = "wpa_key_mgmt";
5368
5369 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5370 params.value = "WPA-PSK";
5371 else if(strcmp(authMode,"EAPAuthentication") == 0)
5372 params.value = "WPA-EAP";
5373 else if (strcmp(authMode, "SAEAuthentication") == 0)
5374 params.value = "SAE";
5375 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5376 params.value = "WPA-EAP-SUITE-B-192";
5377 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5378 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
5379 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5380 return RETURN_OK; //This is taken careof in beaconType
5381
5382 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5383 ret=wifi_hostapdWrite(config_file,&params,1);
5384 if(!ret)
5385 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5386 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5387
5388 return ret;
5389}
5390
5391// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5392INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5393{
5394 //save to wifi config, and wait for wifi restart to apply
5395 char BeaconType[50] = {0};
5396 char config_file[MAX_BUF_SIZE] = {0};
5397
5398 *authMode = 0;
5399 wifi_getApBeaconType(apIndex,BeaconType);
5400 printf("%s____%s \n",__FUNCTION__,BeaconType);
5401
5402 if(strcmp(BeaconType,"None") == 0)
5403 strcpy(authMode,"None");
5404 else
5405 {
5406 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5407 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5408 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5409 if(strcmp(authMode,"WPA-PSK") == 0)
5410 strcpy(authMode,"SharedAuthentication");
5411 else if(strcmp(authMode,"WPA-EAP") == 0)
5412 strcpy(authMode,"EAPAuthentication");
5413 }
5414
5415 return RETURN_OK;
5416}
5417
5418// Outputs the number of stations associated per AP
5419INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5420{
5421 char interface_name[16] = {0};
5422 char cmd[128]={0};
5423 char buf[128]={0};
5424 BOOL status = false;
5425
5426 if(apIndex > MAX_APS)
5427 return RETURN_ERR;
5428
5429 wifi_getApEnable(apIndex,&status);
5430 if (!status)
5431 return RETURN_OK;
5432
5433 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
5434 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5435 return RETURN_ERR;
5436 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
5437 _syscmd(cmd, buf, sizeof(buf));
5438 sscanf(buf,"%lu", output_ulong);
5439
5440 return RETURN_OK;
5441}
5442
5443// manually removes any active wi-fi association with the device specified on this ap
5444INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5445{
5446 char interface_name[16] = {0};
5447 char buf[126]={'\0'};
5448
5449 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5450 return RETURN_ERR;
5451 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
5452 system(buf);
5453
5454 return RETURN_OK;
5455}
5456
5457// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5458INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5459{
5460 if(NULL == output_int)
5461 return RETURN_ERR;
5462 int max_radio_num = 0;
5463 wifi_getMaxRadioNumber(&max_radio_num);
5464 *output_int = apIndex%max_radio_num;
5465 return RETURN_OK;
5466}
5467
5468// sets the radio index for the specific ap
5469INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5470{
5471 //set to config only and wait for wifi reset to apply settings
5472 return RETURN_ERR;
5473}
5474
5475// Get the ACL MAC list per AP
5476INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5477{
5478 char interface_name[16] = {0};
5479 char cmd[MAX_CMD_SIZE]={'\0'};
5480 int ret = 0;
5481
5482 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5483 return RETURN_ERR;
5484 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
5485 ret = _syscmd(cmd,macArray,buf_size);
5486 if (ret != 0)
5487 return RETURN_ERR;
5488
5489 return RETURN_OK;
5490}
5491
5492INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5493{
5494 char interface_name[16] = {0};
5495 char cmd[MAX_CMD_SIZE]={'\0'};
5496 int ret = 0;
5497
5498 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5499 return RETURN_ERR;
5500 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
5501 ret = _syscmd(cmd,macArray,buf_size);
5502 if (ret != 0)
5503 return RETURN_ERR;
5504
5505 return RETURN_OK;
5506}
5507
5508
5509// Get the list of stations associated per AP
5510INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5511{
5512 char interface_name[16] = {0};
5513 char cmd[128];
5514
5515 if(apIndex > 3) //Currently supporting apIndex upto 3
5516 return RETURN_ERR;
5517 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5518 return RETURN_ERR;
5519 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5520 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
5521 _syscmd(cmd, macArray, buf_size);
5522
5523 return RETURN_OK;
5524}
5525
5526// adds the mac address to the filter list
5527//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5528INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5529{
5530 char cmd[MAX_CMD_SIZE]={'\0'};
5531 char buf[MAX_BUF_SIZE]={'\0'};
5532
5533#if 0
5534 sprintf(cmd, "hostapd_cli -i %s accept_acl ADD_MAC %s", interface_name,DeviceMacAddress);
5535 if(_syscmd(cmd,buf,sizeof(buf)))
5536 return RETURN_ERR;
5537#endif
5538 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5539 if(_syscmd(cmd,buf,sizeof(buf)))
5540 return RETURN_ERR;
5541
5542 return RETURN_OK;
5543}
5544
5545// deletes the mac address from the filter list
5546//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5547INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5548{
5549 char cmd[MAX_CMD_SIZE]={'\0'};
5550 char buf[MAX_BUF_SIZE]={'\0'};
5551
5552#if 0
5553 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
5554 if(_syscmd(cmd,buf,sizeof(buf)))
5555 return RETURN_ERR;
5556
5557#endif
5558 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5559 if(_syscmd(cmd,buf,sizeof(buf)))
5560 return RETURN_ERR;
5561
5562 return RETURN_OK;
5563}
5564
5565// outputs the number of devices in the filter list
5566INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5567{
5568 char cmd[MAX_BUF_SIZE]={0};
5569 char buf[MAX_CMD_SIZE]={0};
5570
5571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5572 if(output_uint == NULL)
5573 return RETURN_ERR;
5574
5575 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5576 _syscmd(cmd, buf, sizeof(buf));
5577
5578 *output_uint = atoi(buf);
5579
5580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5581 return RETURN_OK;
5582}
5583
5584INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5585{
5586 char cmd[128]={'\0'};
5587 char buf[128]={'\0'};
5588
5589 if(strcmp(action,"DENY")==0)
5590 {
5591 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5592 system(buf);
5593 return RETURN_OK;
5594 }
5595
5596 if(strcmp(action,"ALLOW")==0)
5597 {
5598 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5599 system(buf);
5600 return RETURN_OK;
5601 }
5602
5603 return RETURN_ERR;
5604
5605}
5606
5607// enable kick for devices on acl black list
5608INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5609{
5610 char aclArray[512] = {0}, *acl = NULL;
5611 char assocArray[512] = {0}, *asso = NULL;
5612
5613 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
5614 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5615
5616 // if there are no devices connected there is nothing to do
5617 if (strlen(assocArray) < 17)
5618 return RETURN_OK;
5619
5620 if (enable == TRUE)
5621 {
5622 //kick off the MAC which is in ACL array (deny list)
5623 acl = strtok(aclArray, "\r\n");
5624 while (acl != NULL) {
5625 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5626 wifi_kickApAssociatedDevice(apIndex, acl);
5627
5628 acl = strtok(NULL, "\r\n");
5629 }
5630 wifi_setApMacAddressControlMode(apIndex, 2);
5631 }
5632 else
5633 {
5634 wifi_setApMacAddressControlMode(apIndex, 0);
5635 }
5636
5637#if 0
5638 //TODO: need to revisit below implementation
5639 char aclArray[512]={0}, *acl=NULL;
5640 char assocArray[512]={0}, *asso=NULL;
5641 char buf[256]={'\0'};
5642 char action[10]={'\0'};
5643 FILE *fr=NULL;
5644 char interface[10]={'\0'};
5645 char config_file[MAX_BUF_SIZE] = {0};
5646
5647 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5648 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5649 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5650 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5651
5652 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5653 system(buf);
5654 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5655 system(buf);
5656 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5657 system(buf);
5658 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5659 system(buf);
5660 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5661 system(buf);
5662
5663 if ( enable == TRUE )
5664 {
5665 int device_count=0;
5666 strcpy(action,"DENY");
5667 //kick off the MAC which is in ACL array (deny list)
5668 acl = strtok (aclArray,",");
5669 while (acl != NULL) {
5670 if(strlen(acl)>=17)
5671 {
5672 apply_rules(apIndex, acl,action,interface);
5673 device_count++;
5674 //Register mac to be blocked ,in syscfg.db persistent storage
5675 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5676 system(buf);
5677 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5678 system(buf);
5679 system("syscfg commit");
5680
5681 wifi_kickApAssociatedDevice(apIndex, acl);
5682 }
5683 acl = strtok (NULL, ",");
5684 }
5685 }
5686 else
5687 {
5688 int device_count=0;
5689 char cmdmac[20]={'\0'};
5690 strcpy(action,"ALLOW");
5691 //kick off the MAC which is not in ACL array (allow list)
5692 acl = strtok (aclArray,",");
5693 while (acl != NULL) {
5694 if(strlen(acl)>=17)
5695 {
5696 apply_rules(apIndex, acl,action,interface);
5697 device_count++;
5698 //Register mac to be Allowed ,in syscfg.db persistent storage
5699 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5700 system(buf);
5701 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5702 system(buf);
5703 sprintf(cmdmac,"%s",acl);
5704 }
5705 acl = strtok (NULL, ",");
5706 }
5707 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5708 system(buf);
5709
5710 //Disconnect the mac which is not in ACL
5711 asso = strtok (assocArray,",");
5712 while (asso != NULL) {
5713 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5714 wifi_kickApAssociatedDevice(apIndex, asso);
5715 asso = strtok (NULL, ",");
5716 }
5717 }
5718#endif
5719 return RETURN_OK;
5720}
5721
5722INT wifi_setPreferPrivateConnection(BOOL enable)
5723{
5724 return RETURN_OK;
5725}
5726
5727// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5728INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5729{
5730 char interface_name[16] = {0};
5731 int items = 1;
5732 struct params list[2];
5733 char buf[MAX_BUF_SIZE] = {0};
5734 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
5735 char deny_file[MAX_BUF_SIZE] = {0};
5736
5737 list[0].name = "macaddr_acl";
5738
5739 if (filterMode == 0) {
5740 sprintf(buf, "%d", 0);
5741 list[0].value = buf;
5742
5743 char cmd[128], rtn[128];
5744 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5745 return RETURN_ERR;
5746 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR", interface_name);
5747 _syscmd(cmd, rtn, sizeof(rtn));
5748 memset(cmd,0,sizeof(cmd));
5749 // Delete deny_mac_file in hostapd configuration
5750 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5751 _syscmd(cmd, rtn, sizeof(rtn));
5752 }
5753 else if (filterMode == 1) {
5754 sprintf(buf, "%d", filterMode);
5755 list[0].value = buf;
5756 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5757 list[1].name = "accept_mac_file";
5758 list[1].value = acl_file;
5759 items = 2;
5760 } else if (filterMode == 2) {
5761 //TODO: deny_mac_file
5762 sprintf(buf, "%d", 0);
5763 list[0].value = buf;
5764 list[1].name = "deny_mac_file";
5765 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5766 list[1].value = deny_file;
5767 items = 2;
5768 } else {
5769 return RETURN_ERR;
5770 }
5771
5772 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5773 wifi_hostapdWrite(config_file, list, items);
5774
5775 return RETURN_OK;
5776
5777#if 0
5778 if(apIndex==0 || apIndex==1)
5779 {
5780 //set the filtermode
5781 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5782 system(buf);
5783 system("syscfg commit");
5784
5785 if(filterMode==0)
5786 {
5787 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5788 system(buf);
5789 return RETURN_OK;
5790 }
5791 }
5792 return RETURN_OK;
5793#endif
5794}
5795
5796// 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.
5797INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5798{
5799 return RETURN_ERR;
5800}
5801
5802// gets the vlan ID for this ap from an internal enviornment variable
5803INT wifi_getApVlanID(INT apIndex, INT *output_int)
5804{
5805 if(apIndex==0)
5806 {
5807 *output_int=100;
5808 return RETURN_OK;
5809 }
5810
5811 return RETURN_ERR;
5812}
5813
5814// sets the vlan ID for this ap to an internal enviornment variable
5815INT wifi_setApVlanID(INT apIndex, INT vlanId)
5816{
5817 //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)
5818 return RETURN_ERR;
5819}
5820
5821// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5822INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5823{
5824 snprintf(bridgeName, 32, "brlan0");
5825 snprintf(IP, 32, "10.0.0.1");
5826 snprintf(subnet, 32, "255.255.255.0");
5827
5828 return RETURN_OK;
5829}
5830
5831//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5832INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5833{
5834 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5835 return RETURN_ERR;
5836}
5837
5838// reset the vlan configuration for this ap
5839INT wifi_resetApVlanCfg(INT apIndex)
5840{
5841 char original_config_file[64] = {0};
5842 char current_config_file[64] = {0};
5843 char buf[64] = {0};
5844 char cmd[64] = {0};
5845 char vlan_file[64] = {0};
5846 char vlan_tagged_interface[16] = {0};
5847 char vlan_bridge[16] = {0};
5848 char vlan_naming[16] = {0};
5849 struct params list[4] = {0};
5850 wifi_band band;
5851
5852 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5853
5854 band = wifi_index_to_band(apIndex);
5855 if (band == band_2_4)
5856 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5857 else if (band == band_5)
5858 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5859 else if (band == band_6)
5860 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5861
5862 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5863
5864 if (strlen(vlan_file) == 0)
5865 strcpy(vlan_file, VLAN_FILE);
5866
5867 // The file should exist or this vap would not work.
5868 if (access(vlan_file, F_OK) != 0) {
5869 sprintf(cmd, "touch %s", vlan_file);
5870 _syscmd(cmd, buf, sizeof(buf));
5871 }
5872 list[0].name = "vlan_file";
5873 list[0].value = vlan_file;
5874
5875 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5876 list[1].name = "vlan_tagged_interface";
5877 list[1].value = vlan_tagged_interface;
5878
5879 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5880 list[2].name = "vlan_bridge";
5881 list[2].value = vlan_bridge;
5882
5883 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5884 list[3].name = "vlan_naming";
5885 list[3].value = vlan_naming;
5886
5887 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5888 wifi_hostapdWrite(current_config_file, list, 4);
5889 //Reapply vlan settings
5890 // wifi_pushBridgeInfo(apIndex);
5891
5892 // restart this ap
5893 wifi_setApEnable(apIndex, FALSE);
5894 wifi_setApEnable(apIndex, TRUE);
5895
5896 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5897
5898 return RETURN_OK;
5899}
5900
5901// 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.
5902INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5903{
5904 return RETURN_ERR;
5905}
5906
5907// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5908INT wifi_startHostApd()
5909{
5910 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5911 system("systemctl start hostapd.service");
5912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5913 return RETURN_OK;
5914 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5915}
5916
5917// stops hostapd
5918INT wifi_stopHostApd()
5919{
5920 char cmd[128] = {0};
5921 char buf[128] = {0};
5922
5923 sprintf(cmd,"systemctl stop hostapd");
5924 _syscmd(cmd, buf, sizeof(buf));
5925
5926 return RETURN_OK;
5927}
5928
5929// restart hostapd dummy function
5930INT wifi_restartHostApd()
5931{
5932 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5933 system("systemctl restart hostapd-global");
5934 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5935
5936 return RETURN_OK;
5937}
5938
5939static int align_hostapd_config(int index)
5940{
5941 ULONG lval;
5942 wifi_getRadioChannel(index%2, &lval);
5943 wifi_setRadioChannel(index%2, lval);
5944 return RETURN_OK;
5945}
5946
5947// sets the AP enable status variable for the specified ap.
5948INT wifi_setApEnable(INT apIndex, BOOL enable)
5949{
5950 char interface_name[16] = {0};
5951 char config_file[MAX_BUF_SIZE] = {0};
5952 char cmd[MAX_CMD_SIZE] = {0};
5953 char buf[MAX_BUF_SIZE] = {0};
5954 BOOL status;
5955 int max_radio_num = 0;
5956 int phyId = 0;
5957
5958 wifi_getApEnable(apIndex,&status);
5959
5960 wifi_getMaxRadioNumber(&max_radio_num);
5961 if (enable == status)
5962 return RETURN_OK;
5963
5964 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5965 return RETURN_ERR;
5966
5967 if (enable == TRUE) {
5968 int radioIndex = apIndex % max_radio_num;
5969 phyId = radio_index_to_phy(radioIndex);
5970 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5971 //Hostapd will bring up this interface
5972 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
5973 _syscmd(cmd, buf, sizeof(buf));
5974 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
5975 _syscmd(cmd, buf, sizeof(buf));
5976 }
5977 else {
5978 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
5979 _syscmd(cmd, buf, sizeof(buf));
5980 sprintf(cmd, "ip link set %s down", interface_name);
5981 _syscmd(cmd, buf, sizeof(buf));
5982 }
5983 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
5984 interface_name, interface_name, enable, VAP_STATUS_FILE);
5985 _syscmd(cmd, buf, sizeof(buf));
5986 //Wait for wifi up/down to apply
5987 return RETURN_OK;
5988}
5989
5990// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5991INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5992{
5993 char interface_name[16] = {0};
5994 char cmd[MAX_CMD_SIZE] = {'\0'};
5995 char buf[MAX_BUF_SIZE] = {'\0'};
5996
5997 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5998 return RETURN_ERR;
5999
6000 *output_bool = 0;
6001
6002 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6003 {
6004 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
6005 *output_bool = FALSE;
6006 return RETURN_OK;
6007 }
6008 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
6009 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6010 }
6011
6012 return RETURN_OK;
6013}
6014
6015// Outputs the AP "Enabled" "Disabled" status from driver
6016INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6017{
6018 char cmd[128] = {0};
6019 char buf[128] = {0};
6020 BOOL output_bool;
6021
6022 if ( NULL == output_string)
6023 return RETURN_ERR;
6024 wifi_getApEnable(apIndex,&output_bool);
6025
6026 if(output_bool == 1)
6027 snprintf(output_string, 32, "Up");
6028 else
6029 snprintf(output_string, 32, "Disable");
6030
6031 return RETURN_OK;
6032}
6033
6034//Indicates whether or not beacons include the SSID name.
6035// outputs a 1 if SSID on the AP is enabled, else outputs 0
6036INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6037{
6038 //get the running status
6039 char config_file[MAX_BUF_SIZE] = {0};
6040 char buf[16] = {0};
6041
6042 if (!output)
6043 return RETURN_ERR;
6044
6045 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6046 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6047 // default is enable
6048 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6049 *output = TRUE;
6050
6051 return RETURN_OK;
6052}
6053
6054// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6055INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6056{
6057 //store the config, apply instantly
6058 char config_file[MAX_BUF_SIZE] = {0};
6059 struct params list;
6060
6061 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6062 list.name = "ignore_broadcast_ssid";
6063 list.value = enable?"0":"1";
6064
6065 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6066 wifi_hostapdWrite(config_file, &list, 1);
6067 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6068 //TODO: call hostapd_cli for dynamic_config_control
6069 wifi_reloadAp(apIndex);
6070 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6071
6072 return RETURN_OK;
6073}
6074
6075//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6076INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6077{
6078 //get the running status
6079 if(!output_uint)
6080 return RETURN_ERR;
6081 *output_uint=16;
6082 return RETURN_OK;
6083}
6084
6085INT wifi_setApRetryLimit(INT apIndex, UINT number)
6086{
6087 //apply instantly
6088 return RETURN_ERR;
6089}
6090
6091//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6092INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6093{
6094 if(!output)
6095 return RETURN_ERR;
6096 *output=TRUE;
6097 return RETURN_OK;
6098}
6099
6100//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6101INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6102{
6103 //get the running status from driver
6104 char cmd[128] = {0};
6105 char buf[128] = {0};
6106 int max_radio_num = 0, radioIndex = 0;
6107 int phyId = 0;
6108
6109 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6110
6111 wifi_getMaxRadioNumber(&max_radio_num);
6112 radioIndex = apIndex % max_radio_num;
6113 phyId = radio_index_to_phy(radioIndex);
6114 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
6115 _syscmd(cmd,buf, sizeof(buf));
6116
6117 if (strlen(buf) > 0)
6118 *output = true;
6119
6120 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6121
6122 return RETURN_OK;
6123}
6124
6125//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6126INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6127{
6128 //get the running status from driver
6129 if(!output)
6130 return RETURN_ERR;
6131
6132 char config_file[MAX_BUF_SIZE] = {0};
6133 char buf[16] = {0};
6134
6135 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6136 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
6137 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6138 *output = TRUE;
6139 else
6140 *output = FALSE;
6141
6142 return RETURN_OK;
6143}
6144
6145// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6146INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6147{
6148 //Save config and apply instantly.
6149 char config_file[MAX_BUF_SIZE] = {0};
6150 struct params list;
6151
6152 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6153 list.name = "wmm_enabled";
6154 list.value = enable?"1":"0";
6155
6156 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6157 wifi_hostapdWrite(config_file, &list, 1);
6158 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6159 wifi_reloadAp(apIndex);
6160 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6161
6162 return RETURN_OK;
6163}
6164
6165//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.
6166INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6167{
6168 //get the running status from driver
6169 if(!output)
6170 return RETURN_ERR;
6171
6172 char config_file[128] = {0};
6173 char buf[16] = {0};
6174
6175 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6176 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6177 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6178 *output = TRUE;
6179 else
6180 *output = FALSE;
6181
6182 return RETURN_OK;
6183}
6184
6185// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6186INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6187{
6188 //save config and apply instantly.
6189 char config_file[MAX_BUF_SIZE] = {0};
6190 struct params list;
6191
6192 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6193 list.name = "uapsd_advertisement_enabled";
6194 list.value = enable?"1":"0";
6195
6196 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6197 wifi_hostapdWrite(config_file, &list, 1);
6198 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6199 wifi_reloadAp(apIndex);
6200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6201
6202 return RETURN_OK;
6203}
6204
6205// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
6206INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6207{
6208 char interface_name[16] = {0};
6209 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6210 char cmd[128] = {0};
6211 char buf[128] = {0};
6212 char ack_filepath[128] = {0};
6213 uint16_t bitmap = 0;
6214 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6215 FILE *f = NULL;
6216
6217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6218
6219 // Get current setting
6220 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6221 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6222 _syscmd(cmd, buf, sizeof(buf));
6223 if (strlen(buf) > 0)
6224 bitmap = strtoul(buf, NULL, 10);
6225
6226 bitmap = strtoul(buf, NULL, 10);
6227
6228 if (ackPolicy == TRUE) { // True, unset this class
6229 bitmap &= ~class_map[class];
6230 } else { // False, set this class
6231 bitmap |= class_map[class];
6232 }
6233
6234 f = fopen(ack_filepath, "w");
6235 if (f == NULL) {
6236 fprintf(stderr, "%s: fopen failed\n", __func__);
6237 return RETURN_ERR;
6238 }
6239 fprintf(f, "%hu", bitmap);
6240 fclose(f);
6241
6242 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6243 return RETURN_ERR;
6244 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
6245 _syscmd(cmd, buf, sizeof(buf));
6246
6247 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6248 return RETURN_OK;
6249}
6250
6251//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.
6252INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6253{
6254 //get the running status from driver
6255 if(!output_uint)
6256 return RETURN_ERR;
6257
6258 char output[16]={'\0'};
6259 char config_file[MAX_BUF_SIZE] = {0};
6260
6261 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6262 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6263 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6264 else {
6265 int device_num = atoi(output);
6266 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6267 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6268 return RETURN_ERR;
6269 }
6270 else {
6271 *output_uint = device_num;
6272 }
6273 }
6274
6275 return RETURN_OK;
6276}
6277
6278INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6279{
6280 //store to wifi config, apply instantly
6281 char str[MAX_BUF_SIZE]={'\0'};
6282 char cmd[MAX_CMD_SIZE]={'\0'};
6283 struct params params;
6284 char config_file[MAX_BUF_SIZE] = {0};
6285
6286 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6287 if (number > MAX_ASSOCIATED_STA_NUM) {
6288 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6289 return RETURN_ERR;
6290 }
6291 sprintf(str, "%d", number);
6292 params.name = "max_num_sta";
6293 params.value = str;
6294
6295 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6296 int ret = wifi_hostapdWrite(config_file, &params, 1);
6297 if (ret) {
6298 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6299 ,__func__, ret);
6300 }
6301
6302 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6303 if (ret) {
6304 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6305 ,__func__, ret);
6306 }
6307 wifi_reloadAp(apIndex);
6308 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6309
6310 return RETURN_OK;
6311}
6312
6313//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.
6314INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6315{
6316 //get the current threshold
6317 if(!output_uint)
6318 return RETURN_ERR;
6319 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6320 if (*output_uint == 0)
6321 *output_uint = 50;
6322 return RETURN_OK;
6323}
6324
6325INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6326{
6327 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
6328 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6329 return RETURN_OK;
6330 return RETURN_ERR;
6331}
6332
6333//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.
6334INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6335{
6336 if(!output_uint)
6337 return RETURN_ERR;
6338 *output_uint = 3;
6339 return RETURN_OK;
6340}
6341
6342//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6343INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6344{
6345 if(!output_uint)
6346 return RETURN_ERR;
6347 *output_uint = 3;
6348 return RETURN_OK;
6349}
6350
6351//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.
6352INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6353{
6354 if(!output_in_seconds)
6355 return RETURN_ERR;
6356 *output_in_seconds = 0;
6357 return RETURN_OK;
6358}
6359
6360//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
6361INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6362{
6363 if(!output || apIndex>=MAX_APS)
6364 return RETURN_ERR;
6365 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
6366 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
6367 return RETURN_OK;
6368}
6369
6370//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6371INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6372{
6373 char config_file[128] = {0};
6374 char wpa[16] = {0};
6375 char key_mgmt[64] = {0};
6376 char buf[16] = {0};
6377 if (!output)
6378 return RETURN_ERR;
6379
6380 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6381 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6382
6383 strcpy(output, "None");//Copying "None" to output string for default case
6384 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6385 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
6386 if (!strcmp(wpa, "1"))
6387 snprintf(output, 32, "WPA-Personal");
6388 else if (!strcmp(wpa, "2"))
6389 snprintf(output, 32, "WPA2-Personal");
6390 else if (!strcmp(wpa, "3"))
6391 snprintf(output, 32, "WPA-WPA2-Personal");
6392
6393 } else if (strstr(key_mgmt, "WPA-EAP")) {
6394 if (!strcmp(wpa, "1"))
6395 snprintf(output, 32, "WPA-Enterprise");
6396 else if (!strcmp(wpa, "2"))
6397 snprintf(output, 32, "WPA2-Enterprise");
6398 else if (!strcmp(wpa, "3"))
6399 snprintf(output, 32, "WPA-WPA2-Enterprise");
6400 } else if (strstr(key_mgmt, "SAE")) {
6401 if (strstr(key_mgmt, "WPA-PSK") == NULL)
6402 snprintf(output, 32, "WPA3-Personal");
6403 else
6404 snprintf(output, 32, "WPA3-Personal-Transition");
6405 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6406 snprintf(output, 32, "WPA3-Enterprise");
6407 }
6408
6409 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6410 return RETURN_OK;
6411#if 0
6412 //TODO: need to revisit below implementation
6413 char securityType[32], authMode[32];
6414 int enterpriseMode=0;
6415
6416 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6417 if(!output)
6418 return RETURN_ERR;
6419
6420 wifi_getApBeaconType(apIndex, securityType);
6421 strcpy(output,"None");//By default, copying "None" to output string
6422 if (strncmp(securityType,"None", strlen("None")) == 0)
6423 return RETURN_OK;
6424
6425 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6426 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6427
6428 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6429 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6430 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6431 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6432 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6433 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6435
6436 return RETURN_OK;
6437#endif
6438}
6439
6440INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6441{
6442 char securityType[32];
6443 char authMode[32];
6444
6445 //store settings and wait for wifi up to apply
6446 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6447 if(!encMode)
6448 return RETURN_ERR;
6449
6450 if (strcmp(encMode, "None")==0)
6451 {
6452 strcpy(securityType,"None");
6453 strcpy(authMode,"None");
6454 }
6455 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6456 {
6457 strcpy(securityType,"WPAand11i");
6458 strcpy(authMode,"PSKAuthentication");
6459 }
6460 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6461 {
6462 strcpy(securityType,"WPAand11i");
6463 strcpy(authMode,"EAPAuthentication");
6464 }
6465 else if (strcmp(encMode, "WPA-Personal")==0)
6466 {
6467 strcpy(securityType,"WPA");
6468 strcpy(authMode,"PSKAuthentication");
6469 }
6470 else if (strcmp(encMode, "WPA-Enterprise")==0)
6471 {
6472 strcpy(securityType,"WPA");
6473 strcpy(authMode,"EAPAuthentication");
6474 }
6475 else if (strcmp(encMode, "WPA2-Personal")==0)
6476 {
6477 strcpy(securityType,"11i");
6478 strcpy(authMode,"PSKAuthentication");
6479 }
6480 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6481 {
6482 strcpy(securityType,"11i");
6483 strcpy(authMode,"EAPAuthentication");
6484 }
6485 else if (strcmp(encMode, "WPA3-Personal") == 0)
6486 {
6487 strcpy(securityType,"11i");
6488 strcpy(authMode,"SAEAuthentication");
6489 }
6490 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
6491 {
6492 strcpy(securityType, "11i");
6493 strcpy(authMode, "PSK-SAEAuthentication");
6494 }
6495 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6496 {
6497 strcpy(securityType,"11i");
6498 strcpy(authMode,"EAP_192-bit_Authentication");
6499 }
6500 else
6501 {
6502 strcpy(securityType,"None");
6503 strcpy(authMode,"None");
6504 }
6505 wifi_setApBeaconType(apIndex, securityType);
6506 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6507 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6508
6509 return RETURN_OK;
6510}
6511
6512
6513//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6514// output_string must be pre-allocated as 64 character string by caller
6515// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6516INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6517{
6518 char buf[16] = {0};
6519 char config_file[MAX_BUF_SIZE] = {0};
6520
6521 if(output_string==NULL)
6522 return RETURN_ERR;
6523
6524 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6525 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6526
6527 if(strcmp(buf,"0")==0)
6528 {
6529 printf("wpa_mode is %s ......... \n",buf);
6530 return RETURN_ERR;
6531 }
6532
6533 wifi_dbg_printf("\nFunc=%s\n",__func__);
6534 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6535 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6536 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6537
6538 return RETURN_OK;
6539}
6540
6541// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6542// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6543INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6544{
6545 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6546 struct params params={'\0'};
6547 int ret;
6548 char config_file[MAX_BUF_SIZE] = {0};
6549
6550 if(NULL == preSharedKey)
6551 return RETURN_ERR;
6552
6553 params.name = "wpa_passphrase";
6554
6555 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6556 {
6557 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6558 return RETURN_ERR;
6559 }
6560 params.value = preSharedKey;
6561 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6562 ret = wifi_hostapdWrite(config_file, &params, 1);
6563 if(!ret)
6564 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6565 return ret;
6566 //TODO: call hostapd_cli for dynamic_config_control
6567}
6568
6569//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6570// outputs the passphrase, maximum 63 characters
6571INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6572{
6573 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6574
6575 wifi_dbg_printf("\nFunc=%s\n",__func__);
6576 if (NULL == output_string)
6577 return RETURN_ERR;
6578
6579 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6580 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6581 if(strcmp(buf,"0")==0)
6582 {
6583 printf("wpa_mode is %s ......... \n",buf);
6584 return RETURN_ERR;
6585 }
6586
6587 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6588 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6589
6590 return RETURN_OK;
6591}
6592
6593// sets the passphrase enviornment variable, max 63 characters
6594INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6595{
6596 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6597 struct params params={'\0'};
6598 char config_file[MAX_BUF_SIZE] = {0};
6599 int ret;
6600
6601 if(NULL == passPhrase)
6602 return RETURN_ERR;
6603
6604 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6605 {
6606 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6607 return RETURN_ERR;
6608 }
6609 params.name = "wpa_passphrase";
6610 params.value = passPhrase;
6611 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6612 ret=wifi_hostapdWrite(config_file,&params,1);
6613 if(!ret)
6614 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6615
6616 return ret;
6617}
6618
6619//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.
6620INT wifi_setApSecurityReset(INT apIndex)
6621{
6622 char original_config_file[64] = {0};
6623 char current_config_file[64] = {0};
6624 char buf[64] = {0};
6625 char cmd[64] = {0};
6626 char wpa[4] = {0};
6627 char wpa_psk[64] = {0};
6628 char wpa_passphrase[64] = {0};
6629 char wpa_psk_file[128] = {0};
6630 char wpa_key_mgmt[64] = {0};
6631 char wpa_pairwise[32] = {0};
6632 wifi_band band;
6633 struct params list[6];
6634
6635 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6636
6637 band = wifi_index_to_band(apIndex);
6638 if (band == band_2_4)
6639 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6640 else if (band == band_5)
6641 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6642 else if (band == band_6)
6643 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6644 else
6645 return RETURN_ERR;
6646
6647 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6648 list[0].name = "wpa";
6649 list[0].value = wpa;
6650
6651 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6652 list[1].name = "wpa_psk";
6653 list[1].value = wpa_psk;
6654
6655 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6656 list[2].name = "wpa_passphrase";
6657 list[2].value = wpa_passphrase;
6658
6659 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6660
6661 if (strlen(wpa_psk_file) == 0)
6662 strcpy(wpa_psk_file, PSK_FILE);
6663
6664 if (access(wpa_psk_file, F_OK) != 0) {
6665 sprintf(cmd, "touch %s", wpa_psk_file);
6666 _syscmd(cmd, buf, sizeof(buf));
6667 }
6668 list[3].name = "wpa_psk_file";
6669 list[3].value = wpa_psk_file;
6670
6671 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6672 list[4].name = "wpa_key_mgmt";
6673 list[4].value = wpa_key_mgmt;
6674
6675 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6676 list[5].name = "wpa_pairwise";
6677 list[5].value = wpa_pairwise;
6678
6679 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6680 wifi_hostapdWrite(current_config_file, list, 6);
6681
6682 wifi_setApEnable(apIndex, FALSE);
6683 wifi_setApEnable(apIndex, TRUE);
6684
6685 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6686 return RETURN_OK;
6687}
6688
6689//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).
6690INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6691{
6692 char config_file[64] = {0};
6693 char buf[64] = {0};
6694 char cmd[256] = {0};
6695
6696 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6697
6698 if(!IP_output || !Port_output || !RadiusSecret_output)
6699 return RETURN_ERR;
6700
6701 // Read the first matched config
6702 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6703 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6704 _syscmd(cmd, buf, sizeof(buf));
6705 strncpy(IP_output, buf, 64);
6706
6707 memset(buf, 0, sizeof(buf));
6708 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6709 _syscmd(cmd, buf, sizeof(buf));
6710 *Port_output = atoi(buf);
6711
6712 memset(buf, 0, sizeof(buf));
6713 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6714 _syscmd(cmd, buf, sizeof(buf));
6715 strncpy(RadiusSecret_output, buf, 64);
6716
6717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6718 return RETURN_OK;
6719}
6720
6721INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6722{
6723 char config_file[64] = {0};
6724 char port_str[8] = {0};
6725 char cmd[256] = {0};
6726 char buf[128] = {0};
6727
6728 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6729
6730 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6731
6732 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6733 _syscmd(cmd, buf, sizeof(buf));
6734 memset(cmd, 0, sizeof(cmd));
6735
6736 snprintf(port_str, sizeof(port_str), "%d", port);
6737 if (strlen(buf) == 0)
6738 // Append
6739 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6740 "auth_server_addr=%s\\n"
6741 "auth_server_port=%s\\n"
6742 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6743 else {
6744 // Delete the three lines setting after the "# radius 1" comment
6745 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6746 _syscmd(cmd, buf, sizeof(buf));
6747 memset(cmd, 0, sizeof(cmd));
6748 // Use "# radius 1" comment to find the location to insert the radius setting
6749 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6750 "# radius 1\\n"
6751 "auth_server_addr=%s\\n"
6752 "auth_server_port=%s\\n"
6753 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6754 }
6755 if(_syscmd(cmd, buf, sizeof(buf))) {
6756 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6757 return RETURN_ERR;
6758 }
6759
6760 wifi_reloadAp(apIndex);
6761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6762 return RETURN_OK;
6763}
6764
6765INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6766{
6767 char config_file[64] = {0};
6768 char buf[64] = {0};
6769 char cmd[256] = {0};
6770
6771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6772
6773 if(!IP_output || !Port_output || !RadiusSecret_output)
6774 return RETURN_ERR;
6775
6776 // Read the second matched config
6777 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6778 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6779 _syscmd(cmd, buf, sizeof(buf));
6780 strncpy(IP_output, buf, 64);
6781
6782 memset(buf, 0, sizeof(buf));
6783 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6784 _syscmd(cmd, buf, sizeof(buf));
6785 *Port_output = atoi(buf);
6786
6787 memset(buf, 0, sizeof(buf));
6788 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6789 _syscmd(cmd, buf, sizeof(buf));
6790 strncpy(RadiusSecret_output, buf, 64);
6791
6792 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6793 return RETURN_OK;
6794}
6795
6796INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6797{
6798 char config_file[64] = {0};
6799 char port_str[8] = {0};
6800 char cmd[256] = {0};
6801 char buf[128] = {0};
6802
6803 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6804
6805 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6806
6807 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6808 _syscmd(cmd, buf, sizeof(buf));
6809 memset(cmd, 0, sizeof(cmd));
6810
6811 snprintf(port_str, sizeof(port_str), "%d", port);
6812 if (strlen(buf) == 0)
6813 // Append
6814 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6815 "auth_server_addr=%s\\n"
6816 "auth_server_port=%s\\n"
6817 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6818 else {
6819 // Delete the three lines setting after the "# radius 2" comment
6820 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6821 _syscmd(cmd, buf, sizeof(buf));
6822 memset(cmd, 0, sizeof(cmd));
6823 // Use "# radius 2" comment to find the location to insert the radius setting
6824 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6825 "# radius 2\\n"
6826 "auth_server_addr=%s\\n"
6827 "auth_server_port=%s\\n"
6828 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6829 }
6830 if(_syscmd(cmd, buf, sizeof(buf))) {
6831 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6832 return RETURN_ERR;
6833 }
6834
6835 wifi_reloadAp(apIndex);
6836 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6837 return RETURN_OK;
6838}
6839
6840//RadiusSettings
6841INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6842{
6843 if(!output)
6844 return RETURN_ERR;
6845
6846 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6847 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6848 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6849 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6850 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6851 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.
6852 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6853 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6854 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6855 //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.
6856
6857 return RETURN_OK;
6858}
6859
6860INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6861{
6862 //store the paramters, and apply instantly
6863 return RETURN_ERR;
6864}
6865
6866//Device.WiFi.AccessPoint.{i}.WPS.Enable
6867//Enables or disables WPS functionality for this access point.
6868// outputs the WPS enable state of this ap in output_bool
6869INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6870{
6871 char interface_name[16] = {0};
6872 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6873 if(!output_bool)
6874 return RETURN_ERR;
6875 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6876 return RETURN_ERR;
6877 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
6878 _syscmd(cmd, buf, sizeof(buf));
6879 if(strstr(buf, "configured"))
6880 *output_bool=TRUE;
6881 else
6882 *output_bool=FALSE;
6883
6884 return RETURN_OK;
6885}
6886
6887//Device.WiFi.AccessPoint.{i}.WPS.Enable
6888// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6889INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6890{
6891 char config_file[MAX_BUF_SIZE] = {0};
6892 struct params params;
6893
6894 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6895 //store the paramters, and wait for wifi up to apply
6896 params.name = "wps_state";
6897 params.value = enable ? "2":"0";
6898
6899 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6900 wifi_hostapdWrite(config_file, &params, 1);
6901 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6902 wifi_reloadAp(apIndex);
6903
6904 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6905 return RETURN_OK;
6906}
6907
6908//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
6909INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6910{
6911 if(!output)
6912 return RETURN_ERR;
6913 snprintf(output, 128, "PushButton,PIN");
6914 return RETURN_OK;
6915}
6916
6917//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6918//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.
6919// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6920INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6921{
6922 if(!output)
6923 return RETURN_ERR;
6924 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6925
6926 return RETURN_OK;
6927}
6928
6929//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6930// 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
6931INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6932{
6933 //apply instantly. No setting need to be stored.
6934 char methods[MAX_BUF_SIZE], *token, *next_token;
6935 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6936 struct params params;
6937
6938 if(!methodString)
6939 return RETURN_ERR;
6940 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6941 //store the paramters, and wait for wifi up to apply
6942
6943 snprintf(methods, sizeof(methods), "%s", methodString);
6944 for(token=methods; *token; token=next_token)
6945 {
6946 strtok_r(token, ",", &next_token);
6947 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6948 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6949 else if(*token=='E')
6950 {
6951 if(!strcmp(methods, "Ethernet"))
6952 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6953 else if(!strcmp(methods, "ExternalNFCToken"))
6954 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6955 else
6956 printf("%s: Unknown WpsConfigMethod\n", __func__);
6957 }
6958 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6959 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6960 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6961 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6962 else if(*token=='P' )
6963 {
6964 if(!strcmp(token, "PushButton"))
6965 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6966 else if(!strcmp(token, "PIN"))
6967 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6968 else
6969 printf("%s: Unknown WpsConfigMethod\n", __func__);
6970 }
6971 else
6972 printf("%s: Unknown WpsConfigMethod\n", __func__);
6973 }
6974 params.name = "config_methods";
6975 params.value = config_methods;
6976 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6977 wifi_hostapdWrite(config_file, &params, 1);
6978 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6979 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6980
6981 return RETURN_OK;
6982}
6983
6984// outputs the pin value, ulong_pin must be allocated by the caller
6985INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6986{
6987 char buf[MAX_BUF_SIZE] = {0};
6988 char cmd[MAX_CMD_SIZE] = {0};
6989
6990 if(!output_ulong)
6991 return RETURN_ERR;
6992 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6993 _syscmd(cmd, buf, sizeof(buf));
6994 if(strlen(buf) > 0)
6995 *output_ulong=strtoul(buf, NULL, 10);
6996
6997 return RETURN_OK;
6998}
6999
7000// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7001INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7002{
7003 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7004 char ap_pin[16] = {0};
7005 char buf[MAX_BUF_SIZE] = {0};
7006 char config_file[MAX_BUF_SIZE] = {0};
7007 ULONG prev_pin = 0;
7008 struct params params;
7009
7010 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7011 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7012 params.name = "ap_pin";
7013 params.value = ap_pin;
7014 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7015 wifi_hostapdWrite(config_file, &params, 1);
7016 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7017 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7018
7019 return RETURN_OK;
7020}
7021
7022// Output string is either Not configured or Configured, max 32 characters
7023INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7024{
7025 char interface_name[16] = {0};
7026 char cmd[MAX_CMD_SIZE];
7027 char buf[MAX_BUF_SIZE]={0};
7028
7029 if(!output_string)
7030 return RETURN_ERR;
7031 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7032 snprintf(output_string, 32, "Not configured");
7033 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7034 return RETURN_ERR;
7035 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
7036 _syscmd(cmd, buf, sizeof(buf));
7037
7038 if(!strncmp(buf, "configured", 10))
7039 snprintf(output_string, 32, "Configured");
7040 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7041
7042 return RETURN_OK;
7043}
7044
7045// sets the WPS pin for this AP
7046INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7047{
7048 char interface_name[16] = {0};
7049 char cmd[MAX_CMD_SIZE];
7050 char buf[MAX_BUF_SIZE]={0};
7051 BOOL enable;
7052
7053 wifi_getApEnable(apIndex, &enable);
7054 if (!enable)
7055 return RETURN_ERR;
7056 wifi_getApWpsEnable(apIndex, &enable);
7057 if (!enable)
7058 return RETURN_ERR;
7059
7060 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7061 return RETURN_ERR;
7062 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
7063 _syscmd(cmd, buf, sizeof(buf));
7064 if((strstr(buf, "OK"))!=NULL)
7065 return RETURN_OK;
7066
7067 return RETURN_ERR;
7068}
7069
7070// This function is called when the WPS push button has been pressed for this AP
7071INT wifi_setApWpsButtonPush(INT apIndex)
7072{
7073 char cmd[MAX_CMD_SIZE];
7074 char buf[MAX_BUF_SIZE]={0};
7075 char interface_name[16] = {0};
7076 BOOL enable=FALSE;
7077
7078 wifi_getApEnable(apIndex, &enable);
7079 if (!enable)
7080 return RETURN_ERR;
7081
7082 wifi_getApWpsEnable(apIndex, &enable);
7083 if (!enable)
7084 return RETURN_ERR;
7085
7086 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7087 return RETURN_ERR;
7088
7089 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
7090 _syscmd(cmd, buf, sizeof(buf));
7091
7092 if((strstr(buf, "OK"))!=NULL)
7093 return RETURN_OK;
7094 return RETURN_ERR;
7095}
7096
7097// cancels WPS mode for this AP
7098INT wifi_cancelApWPS(INT apIndex)
7099{
7100 char interface_name[16] = {0};
7101 char cmd[MAX_CMD_SIZE];
7102 char buf[MAX_BUF_SIZE]={0};
7103
7104 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7105 return RETURN_ERR;
7106 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
7107 _syscmd(cmd,buf, sizeof(buf));
7108
7109 if((strstr(buf, "OK"))!=NULL)
7110 return RETURN_OK;
7111 return RETURN_ERR;
7112}
7113
7114//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7115//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7116INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7117{
7118 char interface_name[16] = {0};
7119 FILE *f = NULL;
7120 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7121 char cmd[256] = {0}, buf[2048] = {0};
7122 char *param = NULL, *value = NULL, *line=NULL;
7123 size_t len = 0;
7124 ssize_t nread = 0;
7125 wifi_associated_dev_t *dev=NULL;
7126
7127 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7128 *associated_dev_array = NULL;
7129 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7130 return RETURN_ERR;
7131 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
7132 _syscmd(cmd,buf,sizeof(buf));
7133 *output_array_size = atoi(buf);
7134
7135 if (*output_array_size <= 0)
7136 return RETURN_OK;
7137
7138 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7139 *associated_dev_array = dev;
7140 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
7141 _syscmd(cmd,buf,sizeof(buf));
7142 f = fopen("/tmp/connected_devices.txt", "r");
7143 if (f==NULL)
7144 {
7145 *output_array_size=0;
7146 return RETURN_ERR;
7147 }
7148 while ((getline(&line, &len, f)) != -1)
7149 {
7150 param = strtok(line,"=");
7151 value = strtok(NULL,"=");
7152
7153 if( strcmp("flags",param) == 0 )
7154 {
7155 value[strlen(value)-1]='\0';
7156 if(strstr (value,"AUTHORIZED") != NULL )
7157 {
7158 dev[auth_temp].cli_AuthenticationState = 1;
7159 dev[auth_temp].cli_Active = 1;
7160 auth_temp++;
7161 read_flag=1;
7162 }
7163 }
7164 if(read_flag==1)
7165 {
7166 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7167 {
7168 value[strlen(value)-1]='\0';
7169 sscanf(value, "%x:%x:%x:%x:%x:%x",
7170 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7171 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7172 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7173 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7174 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7175 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7176 mac_temp++;
7177 read_flag=0;
7178 }
7179 }
7180 }
7181 *output_array_size = auth_temp;
7182 auth_temp=0;
7183 mac_temp=0;
7184 free(line);
7185 fclose(f);
7186 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7187 return RETURN_OK;
7188}
7189
7190#define MACADDRESS_SIZE 6
7191
7192INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7193{
7194 FILE *fp = NULL;
7195 char str[MAX_BUF_SIZE] = {0};
7196 int wificlientindex = 0 ;
7197 int count = 0;
7198 int signalstrength = 0;
7199 int arr[MACADDRESS_SIZE] = {0};
7200 unsigned char mac[MACADDRESS_SIZE] = {0};
7201 UINT wifi_count = 0;
7202 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7203 char pipeCmd[MAX_CMD_SIZE] = {0};
7204
7205 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7206 *output_array_size = 0;
7207 *associated_dev_array = NULL;
7208
7209 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7210 fp = popen(pipeCmd, "r");
7211 if (fp == NULL)
7212 {
7213 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7214 return RETURN_ERR;
7215 }
7216
7217 /* Read the output a line at a time - output it. */
7218 fgets(str, sizeof(str)-1, fp);
7219 wifi_count = (unsigned int) atoi ( str );
7220 *output_array_size = wifi_count;
7221 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7222 pclose(fp);
7223
7224 if(wifi_count == 0)
7225 {
7226 return RETURN_OK;
7227 }
7228 else
7229 {
7230 wifi_associated_dev3_t* temp = NULL;
7231 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7232 if(temp == NULL)
7233 {
7234 printf("Error Statement. Insufficient memory \n");
7235 return RETURN_ERR;
7236 }
7237
7238 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7239 system(pipeCmd);
7240 memset(pipeCmd,0,sizeof(pipeCmd));
7241 if(apIndex == 0)
7242 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7243 else if(apIndex == 1)
7244 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7245 system(pipeCmd);
7246
7247 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7248 if(fp == NULL)
7249 {
7250 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7251 free(temp);
7252 return RETURN_ERR;
7253 }
7254 fclose(fp);
7255
7256 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
7257 fp = popen(pipeCmd, "r");
7258 if(fp)
7259 {
7260 for(count =0 ; count < wifi_count; count++)
7261 {
7262 fgets(str, MAX_BUF_SIZE, fp);
7263 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7264 {
7265 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7266 {
7267 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7268
7269 }
7270 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7271 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]);
7272 }
7273 temp[count].cli_AuthenticationState = 1; //TODO
7274 temp[count].cli_Active = 1; //TODO
7275 }
7276 pclose(fp);
7277 }
7278
7279 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
7280 fp = popen(pipeCmd, "r");
7281 if(fp)
7282 {
7283 pclose(fp);
7284 }
7285 fp = popen("cat /tmp/wifi_signalstrength.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 signalstrength = atoi(str);
7292 temp[count].cli_SignalStrength = signalstrength;
7293 temp[count].cli_RSSI = signalstrength;
7294 temp[count].cli_SNR = signalstrength + 95;
7295 }
7296 pclose(fp);
7297 }
7298
7299
7300 if((apIndex == 0) || (apIndex == 4))
7301 {
7302 for(count =0 ; count < wifi_count ;count++)
7303 {
7304 strcpy(temp[count].cli_OperatingStandard,"g");
7305 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7306 }
7307
7308 //BytesSent
7309 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
7310 fp = popen(pipeCmd, "r");
7311 if(fp)
7312 {
7313 pclose(fp);
7314 }
7315 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7316 if(fp)
7317 {
7318 for (count = 0; count < wifi_count; count++)
7319 {
7320 fgets(str, MAX_BUF_SIZE, fp);
7321 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7322 }
7323 pclose(fp);
7324 }
7325
7326 //BytesReceived
7327 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
7328 fp = popen(pipeCmd, "r");
7329 if (fp)
7330 {
7331 pclose(fp);
7332 }
7333 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7334 if (fp)
7335 {
7336 for (count = 0; count < wifi_count; count++)
7337 {
7338 fgets(str, MAX_BUF_SIZE, fp);
7339 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7340 }
7341 pclose(fp);
7342 }
7343
7344 //PacketsSent
7345 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
7346 fp = popen(pipeCmd, "r");
7347 if (fp)
7348 {
7349 pclose(fp);
7350 }
7351
7352 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7353 if (fp)
7354 {
7355 for (count = 0; count < wifi_count; count++)
7356 {
7357 fgets(str, MAX_BUF_SIZE, fp);
7358 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7359 }
7360 pclose(fp);
7361 }
7362
7363 //PacketsReceived
7364 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
7365 fp = popen(pipeCmd, "r");
7366 if (fp)
7367 {
7368 pclose(fp);
7369 }
7370 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7371 if (fp)
7372 {
7373 for (count = 0; count < wifi_count; count++)
7374 {
7375 fgets(str, MAX_BUF_SIZE, fp);
7376 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7377 }
7378 pclose(fp);
7379 }
7380
7381 //ErrorsSent
7382 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7383 fp = popen(pipeCmd, "r");
7384 if (fp)
7385 {
7386 pclose(fp);
7387 }
7388 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7389 if (fp)
7390 {
7391 for (count = 0; count < wifi_count; count++)
7392 {
7393 fgets(str, MAX_BUF_SIZE, fp);
7394 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7395 }
7396 pclose(fp);
7397 }
7398
7399 //ErrorsSent
7400 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7401 fp = popen(pipeCmd, "r");
7402 if (fp)
7403 {
7404 pclose(fp);
7405 }
7406 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7407 if (fp)
7408 {
7409 for (count = 0; count < wifi_count; count++)
7410 {
7411 fgets(str, MAX_BUF_SIZE, fp);
7412 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7413 }
7414 pclose(fp);
7415 }
7416
7417 //LastDataDownlinkRate
7418 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
7419 fp = popen(pipeCmd, "r");
7420 if (fp)
7421 {
7422 pclose(fp);
7423 }
7424 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7425 if (fp)
7426 {
7427 for (count = 0; count < wifi_count; count++)
7428 {
7429 fgets(str, MAX_BUF_SIZE, fp);
7430 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7431 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7432 }
7433 pclose(fp);
7434 }
7435
7436 //LastDataUplinkRate
7437 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
7438 fp = popen(pipeCmd, "r");
7439 if (fp)
7440 {
7441 pclose(fp);
7442 }
7443 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7444 if (fp)
7445 {
7446 for (count = 0; count < wifi_count; count++)
7447 {
7448 fgets(str, MAX_BUF_SIZE, fp);
7449 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7450 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7451 }
7452 pclose(fp);
7453 }
7454
7455 }
7456 else if ((apIndex == 1) || (apIndex == 5))
7457 {
7458 for (count = 0; count < wifi_count; count++)
7459 {
7460 strcpy(temp[count].cli_OperatingStandard, "a");
7461 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7462 temp[count].cli_BytesSent = 0;
7463 temp[count].cli_BytesReceived = 0;
7464 temp[count].cli_LastDataUplinkRate = 0;
7465 temp[count].cli_LastDataDownlinkRate = 0;
7466 temp[count].cli_PacketsSent = 0;
7467 temp[count].cli_PacketsReceived = 0;
7468 temp[count].cli_ErrorsSent = 0;
7469 }
7470 }
7471
7472 for (count = 0; count < wifi_count; count++)
7473 {
7474 temp[count].cli_Retransmissions = 0;
7475 temp[count].cli_DataFramesSentAck = 0;
7476 temp[count].cli_DataFramesSentNoAck = 0;
7477 temp[count].cli_MinRSSI = 0;
7478 temp[count].cli_MaxRSSI = 0;
7479 strncpy(temp[count].cli_InterferenceSources, "", 64);
7480 memset(temp[count].cli_IPAddress, 0, 64);
7481 temp[count].cli_RetransCount = 0;
7482 temp[count].cli_FailedRetransCount = 0;
7483 temp[count].cli_RetryCount = 0;
7484 temp[count].cli_MultipleRetryCount = 0;
7485 }
7486 *associated_dev_array = temp;
7487 }
7488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7489 return RETURN_OK;
7490}
7491
7492int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7493{
7494 FILE *fp = NULL;
7495 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7496 char cmd[MAX_CMD_SIZE];
7497 int count = 0;
7498
7499 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7500 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7501 fp = popen(cmd,"r");
7502 if(fp == NULL)
7503 {
7504 printf("Failed to run command in Function %s\n",__FUNCTION__);
7505 return 0;
7506 }
7507 if(fgets(path, sizeof(path)-1, fp) != NULL)
7508 {
7509 for(count=0;path[count]!='\n';count++)
7510 status[count]=path[count];
7511 status[count]='\0';
7512 }
7513 strcpy(wifi_status,status);
7514 pclose(fp);
7515 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7516 return RETURN_OK;
7517}
7518
7519/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7520struct hostapd_sta_param {
7521 char key[50];
7522 char value[100];
7523}
7524
7525static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7526 int i = 0;
7527
7528 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7529 if (strncmp(params[i].key,key,50) == 0){
7530 return &params[i].value;
7531 }
7532 i++;
7533 }
7534 return NULL;
7535
7536} */
7537
7538static unsigned int count_occurences(const char *buf, const char *word)
7539{
7540 unsigned int n = 0;
7541 char *ptr = strstr(buf, word);
7542
7543 while (ptr++) {
7544 n++;
7545 ptr = strstr(ptr, word);
7546 }
7547
7548 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7549 return n;
7550}
7551
7552static const char *get_line_from_str_buf(const char *buf, char *line)
7553{
7554 int i;
7555 int n = strlen(buf);
7556
7557 for (i = 0; i < n; i++) {
7558 line[i] = buf[i];
7559 if (buf[i] == '\n') {
7560 line[i] = '\0';
7561 return &buf[i + 1];
7562 }
7563 }
7564
7565 return NULL;
7566}
7567
7568INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7569{
7570 unsigned int assoc_cnt = 0;
7571 char interface_name[50] = {0};
7572 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7573 char cmd[MAX_CMD_SIZE] = {'\0'};
7574 char line[256] = {'\0'};
7575 int i = 0;
7576 int ret = 0;
7577 const char *ptr = NULL;
7578 char *key = NULL;
7579 char *val = NULL;
7580 wifi_associated_dev3_t *temp = NULL;
7581 int rssi;
7582
7583 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7584
7585 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7586 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7587 return RETURN_ERR;
7588 }
7589
7590 // Example filtered output of 'iw dev' command:
7591 // Station 0a:69:72:10:d2:fa (on wifi0)
7592 // signal avg:-67 [-71, -71] dBm
7593 // Station 28:c2:1f:25:5f:99 (on wifi0)
7594 // signal avg:-67 [-71, -70] dBm
7595 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7596 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7597 return RETURN_ERR;
7598 }
7599
7600 ret = _syscmd(cmd, buf, sizeof(buf));
7601 if (ret == RETURN_ERR) {
7602 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7603 return RETURN_ERR;
7604 }
7605
7606 *output_array_size = count_occurences(buf, "Station");
7607 if (*output_array_size == 0) return RETURN_OK;
7608
7609 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7610 if (temp == NULL) {
7611 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7612 return RETURN_ERR;
7613 }
7614 *associated_dev_array = temp;
7615
7616 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7617 ptr = get_line_from_str_buf(buf, line);
7618 i = -1;
7619 while (ptr) {
7620 if (strstr(line, "Station")) {
7621 i++;
7622 key = strtok(line, " ");
7623 val = strtok(NULL, " ");
7624 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7625 &temp[i].cli_MACAddress[0],
7626 &temp[i].cli_MACAddress[1],
7627 &temp[i].cli_MACAddress[2],
7628 &temp[i].cli_MACAddress[3],
7629 &temp[i].cli_MACAddress[4],
7630 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7631 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7632 free(*associated_dev_array);
7633 return RETURN_ERR;
7634 }
7635 }
7636 else if (i < 0) {
7637 ptr = get_line_from_str_buf(ptr, line);
7638 continue; // We didn't detect 'station' entry yet
7639 }
7640 else if (strstr(line, "signal avg")) {
7641 key = strtok(line, ":");
7642 val = strtok(NULL, " ");
7643 if (sscanf(val, "%d", &rssi) <= 0 ) {
7644 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7645 free(*associated_dev_array);
7646 return RETURN_ERR;
7647 }
7648 temp[i].cli_RSSI = rssi;
7649 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7650 }
7651 // Here other fields can be parsed if added to filter of 'iw dev' command
7652
7653 ptr = get_line_from_str_buf(ptr, line);
7654 };
7655
7656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7657
7658 return RETURN_OK;
7659}
7660
7661#if 0
7662//To-do
7663INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7664{
7665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7666
7667 //Using different approach to get required WiFi Parameters from system available commands
7668#if 0
7669 FILE *f;
7670 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7671 char cmd[256], buf[2048];
7672 char *param , *value, *line=NULL;
7673 size_t len = 0;
7674 ssize_t nread;
7675 wifi_associated_dev3_t *dev=NULL;
7676 *associated_dev_array = NULL;
7677 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
7678 _syscmd(cmd,buf,sizeof(buf));
7679 *output_array_size = atoi(buf);
7680
7681 if (*output_array_size <= 0)
7682 return RETURN_OK;
7683
7684 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7685 *associated_dev_array = dev;
7686 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
7687 _syscmd(cmd,buf,sizeof(buf));
7688 f = fopen("/tmp/connected_devices.txt", "r");
7689 if (f==NULL)
7690 {
7691 *output_array_size=0;
7692 return RETURN_ERR;
7693 }
7694 while ((nread = getline(&line, &len, f)) != -1)
7695 {
7696 param = strtok(line,"=");
7697 value = strtok(NULL,"=");
7698
7699 if( strcmp("flags",param) == 0 )
7700 {
7701 value[strlen(value)-1]='\0';
7702 if(strstr (value,"AUTHORIZED") != NULL )
7703 {
7704 dev[auth_temp].cli_AuthenticationState = 1;
7705 dev[auth_temp].cli_Active = 1;
7706 auth_temp++;
7707 read_flag=1;
7708 }
7709 }
7710 if(read_flag==1)
7711 {
7712 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7713 {
7714 value[strlen(value)-1]='\0';
7715 sscanf(value, "%x:%x:%x:%x:%x:%x",
7716 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7717 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7718 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7719 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7720 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7721 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7722
7723 }
7724 else if( strcmp("rx_packets",param) == 0 )
7725 {
7726 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7727 }
7728
7729 else if( strcmp("tx_packets",param) == 0 )
7730 {
7731 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7732 }
7733
7734 else if( strcmp("rx_bytes",param) == 0 )
7735 {
7736 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7737 }
7738
7739 else if( strcmp("tx_bytes",param) == 0 )
7740 {
7741 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7742 mac_temp++;
7743 read_flag=0;
7744 }
7745 }
7746 }
7747
7748 *output_array_size = auth_temp;
7749 auth_temp=0;
7750 mac_temp=0;
7751 free(line);
7752 fclose(f);
7753#endif
7754 char interface_name[MAX_BUF_SIZE] = {0};
7755 char wifi_status[MAX_BUF_SIZE] = {0};
7756 char hostapdconf[MAX_BUF_SIZE] = {0};
7757
7758 wifi_associated_dev3_t *dev_array = NULL;
7759 ULONG wifi_count = 0;
7760
7761 *associated_dev_array = NULL;
7762 *output_array_size = 0;
7763
7764 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7765 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7766 {
7767 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7768
7769 wifi_GetInterfaceName(interface_name, hostapdconf);
7770
7771 if(strlen(interface_name) > 1)
7772 {
7773 wifihal_interfacestatus(wifi_status,interface_name);
7774 if(strcmp(wifi_status,"RUNNING") == 0)
7775 {
7776 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7777
7778 *associated_dev_array = dev_array;
7779 *output_array_size = wifi_count;
7780 }
7781 else
7782 {
7783 *associated_dev_array = NULL;
7784 }
7785 }
7786 }
7787
7788 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7789 return RETURN_OK;
7790}
7791#endif
7792
7793/* getIPAddress function */
7794/**
7795* @description Returning IpAddress of the Matched String
7796*
7797* @param
7798* @str Having MacAddress
7799* @ipaddr Having ipaddr
7800* @return The status of the operation
7801* @retval RETURN_OK if successful
7802* @retval RETURN_ERR if any error is detected
7803*
7804*/
7805
7806INT getIPAddress(char *str,char *ipaddr)
7807{
7808 FILE *fp = NULL;
7809 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7810 int LeaseTime = 0,ret = 0;
7811 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7812 {
7813 return RETURN_ERR;
7814 }
7815
7816 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7817 {
7818 /*
7819 Sample:sss
7820 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7821 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7822 */
7823 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7824 &(LeaseTime),
7825 phyAddr,
7826 ipAddr,
7827 hostName
7828 );
7829 if(ret != 4)
7830 continue;
7831 if(strcmp(str,phyAddr) == 0)
7832 strcpy(ipaddr,ipAddr);
7833 }
7834 fclose(fp);
7835 return RETURN_OK;
7836}
7837
7838/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7839/**
7840* @description Returning Inactive wireless connected clients informations
7841*
7842* @param
7843* @filename Holding private_wifi 2g/5g content files
7844* @associated_dev_array Having inactiv wireless clients informations
7845* @output_array_size Returning Inactive wireless counts
7846* @return The status of the operation
7847* @retval RETURN_OK if successful
7848* @retval RETURN_ERR if any error is detected
7849*
7850*/
7851
7852INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7853{
7854 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7855 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7856 FILE *fp = NULL;
7857 int arr[MACADDRESS_SIZE] = {0};
7858 unsigned char mac[MACADDRESS_SIZE] = {0};
7859 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7860 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7861 fp = popen(buf,"r");
7862 if(fp == NULL)
7863 return RETURN_ERR;
7864 else
7865 {
7866 fgets(path,sizeof(path),fp);
7867 maccount = atoi(path);
7868 }
7869 pclose(fp);
7870 *output_array_size = maccount;
7871 wifi_associated_dev3_t* temp = NULL;
7872 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7873 *associated_dev_array = temp;
7874 if(temp == NULL)
7875 {
7876 printf("Error Statement. Insufficient memory \n");
7877 return RETURN_ERR;
7878 }
7879 memset(buf,0,sizeof(buf));
7880 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7881 fp = popen(buf,"r");
7882 if (fp == NULL) {
7883 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
7884 return RETURN_ERR;
7885 }
7886 for(count = 0; count < maccount ; count++)
7887 {
7888 fgets(path,sizeof(path),fp);
7889 for(i = 0; path[i]!='\n';i++)
7890 str[i]=path[i];
7891 str[i]='\0';
7892 getIPAddress(str,ipaddr);
7893 memset(buf,0,sizeof(buf));
7894 if(strlen(ipaddr) > 0)
7895 {
7896 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7897 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7898 {
7899 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7900 {
7901 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7902 {
7903 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7904
7905 }
7906 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7907 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]);
7908 }
7909 temp[count].cli_AuthenticationState = 0; //TODO
7910 temp[count].cli_Active = 0; //TODO
7911 temp[count].cli_SignalStrength = 0;
7912 }
7913 else //Active wireless clients info
7914 {
7915 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7916 {
7917 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7918 {
7919 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7920
7921 }
7922 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7923 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]);
7924 }
7925 temp[count].cli_Active = 1;
7926 }
7927 }
7928 memset(ipaddr,0,sizeof(ipaddr));
7929 }
7930 pclose(fp);
7931 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7932 return RETURN_OK;
7933}
7934//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7935//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7936//To get Band Steering Capability
7937INT wifi_getBandSteeringCapability(BOOL *support)
7938{
7939 *support = FALSE;
7940 return RETURN_OK;
7941}
7942
7943
7944//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7945//To get Band Steering enable status
7946INT wifi_getBandSteeringEnable(BOOL *enable)
7947{
7948 *enable = FALSE;
7949 return RETURN_OK;
7950}
7951
7952//To turn on/off Band steering
7953INT wifi_setBandSteeringEnable(BOOL enable)
7954{
7955 return RETURN_OK;
7956}
7957
7958//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7959//To get Band Steering AP group
7960INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7961{
7962 if (NULL == output_ApGroup)
7963 return RETURN_ERR;
7964
7965 strcpy(output_ApGroup, "1,2");
7966 return RETURN_OK;
7967}
7968
7969//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7970//to set and read the band steering BandUtilizationThreshold parameters
7971INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7972{
7973 return RETURN_ERR;
7974}
7975
7976INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7977{
7978 return RETURN_ERR;
7979}
7980
7981//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7982//to set and read the band steering RSSIThreshold parameters
7983INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7984{
7985 return RETURN_ERR;
7986}
7987
7988INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7989{
7990 return RETURN_ERR;
7991}
7992
7993
7994//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7995//to set and read the band steering physical modulation rate threshold parameters
7996INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7997{
7998 //If chip is not support, return -1
7999 return RETURN_ERR;
8000}
8001
8002INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8003{
8004 //If chip is not support, return -1
8005 return RETURN_ERR;
8006}
8007
8008//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8009//to set and read the inactivity time (in seconds) for steering under overload condition
8010INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8011{
8012 return RETURN_ERR;
8013}
8014
8015INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8016{
8017 return RETURN_ERR;
8018}
8019
8020//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8021//to set and read the inactivity time (in seconds) for steering under Idle condition
8022INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8023{
8024 return RETURN_ERR;
8025}
8026
8027INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8028{
8029 return RETURN_ERR;
8030}
8031
8032//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8033//pClientMAC[64]
8034//pSourceSSIDIndex[64]
8035//pDestSSIDIndex[64]
8036//pSteeringReason[256]
8037INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8038{
8039 //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
8040 *pSteeringTime=time(NULL);
8041 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8042 return RETURN_OK;
8043}
8044
8045INT wifi_ifConfigDown(INT apIndex)
8046{
8047 INT status = RETURN_OK;
8048 char cmd[64];
8049
8050 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8051 printf("%s: %s\n", __func__, cmd);
8052 system(cmd);
8053
8054 return status;
8055}
8056
8057INT wifi_ifConfigUp(INT apIndex)
8058{
8059 char interface_name[16] = {0};
8060 char cmd[128];
8061 char buf[1024];
8062
8063 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8064 return RETURN_ERR;
8065 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
8066 _syscmd(cmd, buf, sizeof(buf));
8067 return 0;
8068}
8069
8070//>> Deprecated. Replace with wifi_applyRadioSettings
8071INT wifi_pushBridgeInfo(INT apIndex)
8072{
8073 char interface_name[16] = {0};
8074 char ip[32] = {0};
8075 char subnet[32] = {0};
8076 char bridge[32] = {0};
8077 int vlanId = 0;
8078 char cmd[128] = {0};
8079 char buf[1024] = {0};
8080
8081 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8082 wifi_getApVlanID(apIndex,&vlanId);
8083
8084 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8085 return RETURN_ERR;
8086 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
8087 _syscmd(cmd,buf, sizeof(buf));
8088
8089 return 0;
8090}
8091
8092INT wifi_pushChannel(INT radioIndex, UINT channel)
8093{
8094 char interface_name[16] = {0};
8095 char cmd[128];
8096 char buf[1024];
8097 int apIndex;
8098
8099 apIndex=(radioIndex==0)?0:1;
8100 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8101 return RETURN_ERR;
8102 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
8103 _syscmd(cmd,buf, sizeof(buf));
8104
8105 return 0;
8106}
8107
8108INT wifi_pushChannelMode(INT radioIndex)
8109{
8110 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8111 return RETURN_ERR;
8112}
8113
8114INT wifi_pushDefaultValues(INT radioIndex)
8115{
8116 //Apply Comcast specified default radio settings instantly
8117 //AMPDU=1
8118 //AMPDUFrames=32
8119 //AMPDULim=50000
8120 //txqueuelen=1000
8121
8122 return RETURN_ERR;
8123}
8124
8125INT wifi_pushTxChainMask(INT radioIndex)
8126{
8127 //Apply default TxChainMask instantly
8128 return RETURN_ERR;
8129}
8130
8131INT wifi_pushRxChainMask(INT radioIndex)
8132{
8133 //Apply default RxChainMask instantly
8134 return RETURN_ERR;
8135}
8136
8137INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8138{
8139 INT status;
8140
8141 status = wifi_setSSIDName(apIndex,ssid);
8142 wifi_setApEnable(apIndex,FALSE);
8143 wifi_setApEnable(apIndex,TRUE);
8144
8145 return status;
8146}
8147
8148INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8149{
8150 //Apply default Ssid Advertisement instantly
8151 return RETURN_ERR;
8152}
8153
8154INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8155{
8156 INT status = RETURN_ERR;
8157 *output = 0;
8158 return RETURN_ERR;
8159}
8160
8161INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8162{
8163 return RETURN_OK;
8164}
8165
8166INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8167{
8168 return RETURN_OK;
8169}
8170
8171//To-do
8172INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8173{
8174 char output[16]={'\0'};
8175 char config_file[MAX_BUF_SIZE] = {0};
8176
8177 if (!output_string)
8178 return RETURN_ERR;
8179
8180 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8181 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8182
8183 if (strlen(output) == 0)
8184 snprintf(output_string, 64, "Disabled");
8185 else if (strncmp(output, "0", 1) == 0)
8186 snprintf(output_string, 64, "Disabled");
8187 else if (strncmp(output, "1", 1) == 0)
8188 snprintf(output_string, 64, "Optional");
8189 else if (strncmp(output, "2", 1) == 0)
8190 snprintf(output_string, 64, "Required");
8191 else {
8192 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8193 return RETURN_ERR;
8194 }
8195
8196 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
8197 return RETURN_OK;
8198}
8199INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8200{
8201 char str[MAX_BUF_SIZE]={'\0'};
8202 char cmd[MAX_CMD_SIZE]={'\0'};
8203 struct params params;
8204 char config_file[MAX_BUF_SIZE] = {0};
8205
8206 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8207 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8208 return RETURN_ERR;
8209
8210 params.name = "ieee80211w";
8211 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8212 params.value = "0";
8213 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8214 params.value = "1";
8215 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8216 params.value = "2";
8217 else{
8218 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8219 return RETURN_ERR;
8220 }
8221 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8222 wifi_hostapdWrite(config_file, &params, 1);
8223 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
8224 return RETURN_OK;
8225}
8226INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8227{
8228 char output[16]={'\0'};
8229 char config_file[MAX_BUF_SIZE] = {0};
8230
8231 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8232 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8233 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8234
8235 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8236 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8237
8238 return RETURN_OK;
8239}
8240
8241INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8242{
8243 return RETURN_OK;
8244}
8245
8246INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8247{
8248 return RETURN_OK;
8249}
8250
8251INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8252{
8253 return RETURN_OK;
8254}
8255
8256INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8257{
8258 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8259 char config_file[MAX_BUF_SIZE] = {0};
8260
8261 if (NULL == output)
8262 return RETURN_ERR;
8263 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8264 wifi_hostapdRead(config_file,"hw_mode",output,64);
8265
8266 if(strcmp(output,"b")==0)
8267 sprintf(output, "%s", "1,2,5.5,11");
8268 else if (strcmp(output,"a")==0)
8269 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8270 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8271 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8272
8273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8274 return RETURN_OK;
8275}
8276
8277INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8278{
8279 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8280 char *temp;
8281 char temp_output[128];
8282 char temp_TransmitRates[128];
8283 char config_file[MAX_BUF_SIZE] = {0};
8284
8285 if (NULL == output)
8286 return RETURN_ERR;
8287
8288 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8289 wifi_hostapdRead(config_file,"supported_rates",output,64);
8290
8291 if (strlen(output) == 0) {
8292 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8293 return RETURN_OK;
8294 }
8295 strcpy(temp_TransmitRates,output);
8296 strcpy(temp_output,"");
8297 temp = strtok(temp_TransmitRates," ");
8298 while(temp!=NULL)
8299 {
8300 temp[strlen(temp)-1]=0;
8301 if((temp[0]=='5') && (temp[1]=='\0'))
8302 {
8303 temp="5.5";
8304 }
8305 strcat(temp_output,temp);
8306 temp = strtok(NULL," ");
8307 if(temp!=NULL)
8308 {
8309 strcat(temp_output,",");
8310 }
8311 }
8312 strcpy(output,temp_output);
8313 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8314
8315 return RETURN_OK;
8316}
8317
8318INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8319{
8320 return RETURN_OK;
8321}
8322
8323
8324INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8325{
8326 int i=0;
8327 char *temp;
8328 char temp1[128] = {0};
8329 char temp_output[128] = {0};
8330 char temp_TransmitRates[128] = {0};
8331 struct params params={'\0'};
8332 char config_file[MAX_BUF_SIZE] = {0};
8333 wifi_band band = wifi_index_to_band(wlanIndex);
8334
8335 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8336 if(NULL == output)
8337 return RETURN_ERR;
8338 strcpy(temp_TransmitRates,output);
8339
8340 for(i=0;i<strlen(temp_TransmitRates);i++)
8341 {
8342 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
8343 {
8344 continue;
8345 }
8346 else
8347 {
8348 return RETURN_ERR;
8349 }
8350 }
8351 strcpy(temp_output,"");
8352 temp = strtok(temp_TransmitRates,",");
8353 while(temp!=NULL)
8354 {
8355 strcpy(temp1,temp);
8356 if(band == band_5)
8357 {
8358 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
8359 {
8360 return RETURN_ERR;
8361 }
8362 }
8363
8364 if(strcmp(temp,"5.5")==0)
8365 {
8366 strcpy(temp1,"55");
8367 }
8368 else
8369 {
8370 strcat(temp1,"0");
8371 }
8372 strcat(temp_output,temp1);
8373 temp = strtok(NULL,",");
8374 if(temp!=NULL)
8375 {
8376 strcat(temp_output," ");
8377 }
8378 }
8379 strcpy(output,temp_output);
8380
8381 params.name = "supported_rates";
8382 params.value = output;
8383
8384 wifi_dbg_printf("\n%s:",__func__);
8385 wifi_dbg_printf("params.value=%s\n",params.value);
8386 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8387 wifi_hostapdWrite(config_file,&params,1);
8388 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8389
8390 return RETURN_OK;
8391}
8392
8393
8394static char *sncopy(char *dst, int dst_sz, const char *src)
8395{
8396 if (src && dst && dst_sz > 0) {
8397 strncpy(dst, src, dst_sz);
8398 dst[dst_sz - 1] = '\0';
8399 }
8400 return dst;
8401}
8402
8403static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8404{
8405 if (0 == strcmp(ht_mode, "HT40") ||
8406 0 == strcmp(ht_mode, "HT80") ||
8407 0 == strcmp(ht_mode, "HT160")) {
8408 switch (channel) {
8409 case 1 ... 7:
8410 case 36:
8411 case 44:
8412 case 52:
8413 case 60:
8414 case 100:
8415 case 108:
8416 case 116:
8417 case 124:
8418 case 132:
8419 case 140:
8420 case 149:
8421 case 157:
8422 return 1;
8423 case 8 ... 13:
8424 case 40:
8425 case 48:
8426 case 56:
8427 case 64:
8428 case 104:
8429 case 112:
8430 case 120:
8431 case 128:
8432 case 136:
8433 case 144:
8434 case 153:
8435 case 161:
8436 return -1;
8437 default:
8438 return -EINVAL;
8439 }
8440 }
8441
8442 return -EINVAL;
8443}
8444
8445static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8446{
8447 int idx = channel%8;
8448 if (0 == strcmp(ht_mode, "HT40") ||
8449 0 == strcmp(ht_mode, "HT80") ||
8450 0 == strcmp(ht_mode, "HT160")) {
8451 switch (idx) {
8452 case 1:
8453 return 1;
8454 case 5:
8455 return -1;
8456 default:
8457 return -EINVAL;
8458 }
8459 }
8460
8461 return -EINVAL;
8462}
8463static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8464{
8465 if (NULL == hw_mode) return;
8466
8467 if (0 == strcmp(hw_mode, "ac"))
8468 sncopy(bw_mode, bw_mode_len, "ht vht");
8469
8470 if (0 == strcmp(hw_mode, "n"))
8471 sncopy(bw_mode, bw_mode_len, "ht");
8472
8473 return;
8474}
8475
8476static int util_chan_to_freq(int chan)
8477{
8478 if (chan == 14)
8479 return 2484;
8480 else if (chan < 14)
8481 return 2407 + chan * 5;
8482 else if (chan >= 182 && chan <= 196)
8483 return 4000 + chan * 5;
8484 else
8485 return 5000 + chan * 5;
8486 return 0;
8487}
8488
8489static int util_6G_chan_to_freq(int chan)
8490{
8491 if (chan)
8492 return 5950 + chan * 5;
8493 else
8494 return 0;
8495
8496}
8497const int *util_unii_5g_chan2list(int chan, int width)
8498{
8499 static const int lists[] = {
8500 // <width>, <chan1>, <chan2>..., 0,
8501 20, 36, 0,
8502 20, 40, 0,
8503 20, 44, 0,
8504 20, 48, 0,
8505 20, 52, 0,
8506 20, 56, 0,
8507 20, 60, 0,
8508 20, 64, 0,
8509 20, 100, 0,
8510 20, 104, 0,
8511 20, 108, 0,
8512 20, 112, 0,
8513 20, 116, 0,
8514 20, 120, 0,
8515 20, 124, 0,
8516 20, 128, 0,
8517 20, 132, 0,
8518 20, 136, 0,
8519 20, 140, 0,
8520 20, 144, 0,
8521 20, 149, 0,
8522 20, 153, 0,
8523 20, 157, 0,
8524 20, 161, 0,
8525 20, 165, 0,
8526 40, 36, 40, 0,
8527 40, 44, 48, 0,
8528 40, 52, 56, 0,
8529 40, 60, 64, 0,
8530 40, 100, 104, 0,
8531 40, 108, 112, 0,
8532 40, 116, 120, 0,
8533 40, 124, 128, 0,
8534 40, 132, 136, 0,
8535 40, 140, 144, 0,
8536 40, 149, 153, 0,
8537 40, 157, 161, 0,
8538 80, 36, 40, 44, 48, 0,
8539 80, 52, 56, 60, 64, 0,
8540 80, 100, 104, 108, 112, 0,
8541 80, 116, 120, 124, 128, 0,
8542 80, 132, 136, 140, 144, 0,
8543 80, 149, 153, 157, 161, 0,
8544 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8545 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8546 -1 // final delimiter
8547 };
8548 const int *start;
8549 const int *p;
8550
8551 for (p = lists; *p != -1; p++) {
8552 if (*p == width) {
8553 for (start = ++p; *p != 0; p++) {
8554 if (*p == chan)
8555 return start;
8556 }
8557 }
8558 // move to the end of channel list of given width
8559 while (*p != 0) {
8560 p++;
8561 }
8562 }
8563
8564 return NULL;
8565}
8566
8567static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8568{
8569 if (NULL == ht_mode)
8570 return 0;
8571
8572 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8573 const int *chans = util_unii_5g_chan2list(channel, width);
8574 int sum = 0;
8575 int cnt = 0;
8576
8577 if (NULL == chans)
8578 return 0;
8579
8580 while (*chans) {
8581 sum += *chans;
8582 cnt++;
8583 chans++;
8584 }
8585 if (cnt == 0)
8586 return 0;
8587 return sum / cnt;
8588}
8589
8590static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8591{
8592 if (NULL == ht_mode)
8593 return 0;
8594
8595 int width = strtol((ht_mode + 2), NULL, 10);
8596
8597 int idx = 0 ;
8598 int centerchan = 0;
8599 int chan_ofs = 1;
8600
8601 if (width == 40){
8602 idx = ((channel/4) + chan_ofs)%2;
8603 switch (idx) {
8604 case 0:
8605 centerchan = (channel - 2);
8606 break;
8607 case 1:
8608 centerchan = (channel + 2);
8609 break;
8610 default:
8611 return -EINVAL;
8612 }
8613 }else if (width == 80){
8614 idx = ((channel/4) + chan_ofs)%4;
8615 switch (idx) {
8616 case 0:
8617 centerchan = (channel - 6);
8618 break;
8619 case 1:
8620 centerchan = (channel + 6);
8621 break;
8622 case 2:
8623 centerchan = (channel + 2);
8624 break;
8625 case 3:
8626 centerchan = (channel - 2);
8627 break;
8628 default:
8629 return -EINVAL;
8630 }
8631 }else if (width == 160){
8632 switch (channel) {
8633 case 1 ... 29:
8634 centerchan = 15;
8635 break;
8636 case 33 ... 61:
8637 centerchan = 47;
8638 break;
8639 case 65 ... 93:
8640 centerchan = 79;
8641 break;
8642 case 97 ... 125:
8643 centerchan = 111;
8644 break;
8645 case 129 ... 157:
8646 centerchan = 143;
8647 break;
8648 case 161 ... 189:
8649 centerchan = 175;
8650 break;
8651 case 193 ... 221:
8652 centerchan = 207;
8653 break;
8654 default:
8655 return -EINVAL;
8656 }
8657 }
8658 return centerchan;
8659}
8660static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8661{
8662 BOOL onlyG, onlyN, onlyA;
8663 CHAR tmp[64];
8664 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8665 if (ret == RETURN_OK) {
8666 sncopy(hw_mode, hw_mode_size, tmp);
8667 }
8668 return ret;
8669}
8670
8671INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8672{
8673 // Sample commands:
8674 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8675 // hostapd_cli -i wifi0 chan_switch 30 2437
8676 char cmd[MAX_CMD_SIZE] = {0};
8677 char buf[MAX_BUF_SIZE] = {0};
8678 int freq = 0, ret = 0;
8679 char center_freq1_str[32] = ""; // center_freq1=%d
8680 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8681 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8682 char hw_mode[16] = ""; // n|ac
8683 char bw_mode[16] = ""; // ht|ht vht
8684 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8685 char interface_name[16] = {0};
8686 int sec_chan_offset;
8687 int width;
8688 char config_file[64] = {0};
8689 BOOL stbcEnable = FALSE;
8690 char *ext_str = "None";
8691 wifi_band band = band_invalid;
8692 int center_chan = 0;
8693 int center_freq1 = 0;
8694
8695 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
8696
8697 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8698 return RETURN_ERR;
8699
8700 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8701
8702 band = wifi_index_to_band(radioIndex);
8703
8704 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
8705
8706 // Get radio mode HT20|HT40|HT80 etc.
8707 if (channel){
8708 if (band == band_6){
8709 freq = util_6G_chan_to_freq(channel);
8710 }else{
8711 freq = util_chan_to_freq(channel);
8712 }
8713 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8714
8715 // Provide bandwith if specified
8716 if (channel_width_MHz > 20) {
8717 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8718 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8719 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
8720
8721 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8722 }else if (channel_width_MHz == 20){
8723 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8724 }
8725
8726
8727 if (channel_width_MHz > 20) {
8728 if (band == band_6){
8729 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8730 if(center_chan){
8731 center_freq1 = util_6G_chan_to_freq(center_chan);
8732 }
8733 }else{
8734 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8735 if(center_chan){
8736 center_freq1 = util_chan_to_freq(center_chan);
8737 }
8738 }
8739
8740 if (center_freq1)
8741 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8742
8743 }
8744
8745 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8746 if (band == band_6){
8747 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8748 }else{
8749 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8750 }
8751 if (sec_chan_offset != -EINVAL)
8752 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
8753
8754 // Only the first AP, other are hanging on the same radio
8755 int apIndex = radioIndex;
8756 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
8757 interface_name, csa_beacon_count, freq,
8758 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8759 wifi_dbg_printf("execute: '%s'\n", cmd);
8760 ret = _syscmd(cmd, buf, sizeof(buf));
8761 wifi_reloadAp(radioIndex);
8762
8763 ret = wifi_setRadioChannel(radioIndex, channel);
8764 if (ret != RETURN_OK) {
8765 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8766 return RETURN_ERR;
8767 }
8768
8769 if (sec_chan_offset == 1) ext_str = "Above";
8770 else if (sec_chan_offset == -1) ext_str = "Below";
8771
8772 wifi_setRadioCenterChannel(radioIndex, center_chan);
8773
8774 } else {
8775 if (channel_width_MHz > 20)
8776 ext_str = "Above";
8777 }
8778
8779 wifi_setRadioExtChannel(radioIndex, ext_str);
8780
8781 char mhz_str[16];
8782 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8783 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8784
8785 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8786
8787 return RETURN_OK;
8788}
8789
8790INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8791{
8792 int index = -1;
8793 wifi_neighbor_ap2_t *scan_array = NULL;
8794 char cmd[256]={0};
8795 char buf[128]={0};
8796 char file_name[32] = {0};
8797 char filter_SSID[32] = {0};
8798 char line[256] = {0};
8799 char interface_name[16] = {0};
8800 char *ret = NULL;
8801 int freq=0;
8802 FILE *f = NULL;
8803 size_t len=0;
8804 int channels_num = 0;
8805 int vht_channel_width = 0;
8806 int get_noise_ret = RETURN_ERR;
8807 bool filter_enable = false;
8808 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
8809 int phyId = 0;
8810
8811 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
8812
8813 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8814 f = fopen(file_name, "r");
8815 if (f != NULL) {
8816 fgets(filter_SSID, sizeof(file_name), f);
8817 if (strlen(filter_SSID) != 0)
8818 filter_enable = true;
8819 fclose(f);
8820 }
8821
8822 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
8823 return RETURN_ERR;
8824
8825 phyId = radio_index_to_phy(radio_index);
8826
8827 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
8828 _syscmd(cmd, buf, sizeof(buf));
8829 channels_num = strtol(buf, NULL, 10);
8830
8831 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8832 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
8833 fprintf(stderr, "cmd: %s\n", cmd);
8834 if ((f = popen(cmd, "r")) == NULL) {
8835 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8836 return RETURN_ERR;
8837 }
8838
8839 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8840 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8841
8842 ret = fgets(line, sizeof(line), f);
8843 while (ret != NULL) {
8844 if(strstr(line, "BSS") != NULL) { // new neighbor info
8845 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8846 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8847 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8848
8849 if (!filter_BSS) {
8850 index++;
8851 wifi_neighbor_ap2_t *tmp;
8852 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8853 if (tmp == NULL) { // no more memory to use
8854 index--;
8855 wifi_dbg_printf("%s: realloc failed\n", __func__);
8856 break;
8857 }
8858 scan_array = tmp;
8859 }
8860 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8861
8862 filter_BSS = false;
8863 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8864 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8865 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8866 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8867 } else if (strstr(line, "freq") != NULL) {
8868 sscanf(line," freq: %d", &freq);
8869 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
8870
8871 if (freq >= 2412 && freq <= 2484) {
8872 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8873 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8874 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8875 }
8876 else if (freq >= 5160 && freq <= 5805) {
8877 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8878 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8879 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8880 }
8881
8882 scan_array[index].ap_Noise = 0;
8883 if (get_noise_ret == RETURN_OK) {
8884 for (int i = 0; i < channels_num; i++) {
8885 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8886 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8887 break;
8888 }
8889 }
8890 }
8891 } else if (strstr(line, "beacon interval") != NULL) {
8892 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8893 } else if (strstr(line, "signal") != NULL) {
8894 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8895 } else if (strstr(line,"SSID") != NULL) {
8896 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8897 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8898 filter_BSS = true;
8899 }
8900 } else if (strstr(line, "Supported rates") != NULL) {
8901 char SRate[80] = {0}, *tmp = NULL;
8902 memset(buf, 0, sizeof(buf));
8903 strcpy(SRate, line);
8904 tmp = strtok(SRate, ":");
8905 tmp = strtok(NULL, ":");
8906 strcpy(buf, tmp);
8907 memset(SRate, 0, sizeof(SRate));
8908
8909 tmp = strtok(buf, " \n");
8910 while (tmp != NULL) {
8911 strcat(SRate, tmp);
8912 if (SRate[strlen(SRate) - 1] == '*') {
8913 SRate[strlen(SRate) - 1] = '\0';
8914 }
8915 strcat(SRate, ",");
8916
8917 tmp = strtok(NULL, " \n");
8918 }
8919 SRate[strlen(SRate) - 1] = '\0';
8920 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8921 } else if (strstr(line, "DTIM") != NULL) {
8922 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8923 } else if (strstr(line, "VHT capabilities") != NULL) {
8924 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8925 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8926 } else if (strstr(line, "HT capabilities") != NULL) {
8927 strcat(scan_array[index].ap_SupportedStandards, ",n");
8928 strcpy(scan_array[index].ap_OperatingStandards, "n");
8929 } else if (strstr(line, "VHT operation") != NULL) {
8930 ret = fgets(line, sizeof(line), f);
8931 sscanf(line," * channel width: %d", &vht_channel_width);
8932 if(vht_channel_width == 1) {
8933 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8934 } else {
8935 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8936 }
8937 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8938 continue;
8939 } else if (strstr(line, "HT operation") != NULL) {
8940 ret = fgets(line, sizeof(line), f);
8941 sscanf(line," * secondary channel offset: %s", &buf);
8942 if (!strcmp(buf, "above")) {
8943 //40Mhz +
8944 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
8945 }
8946 else if (!strcmp(buf, "below")) {
8947 //40Mhz -
8948 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8949 } else {
8950 //20Mhz
8951 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
8952 }
8953 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8954 continue;
8955 } else if (strstr(line, "HE capabilities") != NULL) {
8956 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8957 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8958 ret = fgets(line, sizeof(line), f);
8959 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8960 if (strstr(line, "HE40/2.4GHz") != NULL)
8961 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8962 else
8963 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8964 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8965 if (strstr(line, "HE80/5GHz") != NULL) {
8966 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8967 ret = fgets(line, sizeof(line), f);
8968 } else
8969 continue;
8970 if (strstr(line, "HE160/5GHz") != NULL)
8971 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
8972 }
8973 continue;
8974 } else if (strstr(line, "WPA") != NULL) {
8975 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8976 } else if (strstr(line, "RSN") != NULL) {
8977 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8978 } else if (strstr(line, "Group cipher") != NULL) {
8979 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8980 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8981 strcpy(scan_array[index].ap_EncryptionMode, "AES");
8982 }
8983 }
8984 ret = fgets(line, sizeof(line), f);
8985 }
8986
8987 if (!filter_BSS) {
8988 *output_array_size = index + 1;
8989 } else {
8990 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8991 *output_array_size = index;
8992 }
8993 *neighbor_ap_array = scan_array;
8994 pclose(f);
8995 free(channels_noise_arr);
8996 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8997 return RETURN_OK;
8998}
8999
9000INT wifi_getApAssociatedDeviceStats(
9001 INT apIndex,
9002 mac_address_t *clientMacAddress,
9003 wifi_associated_dev_stats_t *associated_dev_stats,
9004 u64 *handle)
9005{
9006 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9007 char interface_name[50] = {0};
9008 char cmd[1024] = {0};
9009 char mac_str[18] = {0};
9010 char *key = NULL;
9011 char *val = NULL;
9012 FILE *f = NULL;
9013 char *line = NULL;
9014 size_t len = 0;
9015
9016 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9017 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9018 return RETURN_ERR;
9019 }
9020
9021 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9022 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9023 if((f = popen(cmd, "r")) == NULL) {
9024 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9025 return RETURN_ERR;
9026 }
9027
9028 while ((getline(&line, &len, f)) != -1) {
9029 key = strtok(line,":");
9030 val = strtok(NULL,":");
9031
9032 if(!strncmp(key,"rx bytes",8))
9033 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9034 if(!strncmp(key,"tx bytes",8))
9035 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9036 if(!strncmp(key,"rx packets",10))
9037 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9038 if(!strncmp(key,"tx packets",10))
9039 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9040 if(!strncmp(key,"tx retries",10))
9041 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9042 if(!strncmp(key,"tx failed",9))
9043 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9044 if(!strncmp(key,"rx drop misc",13))
9045 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9046 if(!strncmp(key,"rx bitrate",10)) {
9047 val = strtok(val, " ");
9048 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9049 }
9050 if(!strncmp(key,"tx bitrate",10)) {
9051 val = strtok(val, " ");
9052 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9053 }
9054 }
9055 free(line);
9056 pclose(f);
9057 return RETURN_OK;
9058}
9059
9060INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9061{
9062 char interface_name[16] = {0};
9063 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9064
9065 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9066 if (NULL == output_string)
9067 return RETURN_ERR;
9068
9069 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9070 return RETURN_ERR;
9071 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", interface_name);
9072 _syscmd(cmd, buf, sizeof(buf));
9073
9074 //size of SSID name restricted to value less than 32 bytes
9075 snprintf(output_string, 32, "%s", buf);
9076 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9077
9078 return RETURN_OK;
9079}
9080
9081INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9082{
9083 //char cmd[MAX_CMD_SIZE] = {0};
9084 char config_file[MAX_BUF_SIZE] = {0};
9085 char buf[32] = {0};
9086
9087 if (!output_filterMode)
9088 return RETURN_ERR;
9089
9090 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9091 //_syscmd(cmd, buf, sizeof(buf));
9092 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9093 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
9094 if(strlen(buf) == 0) {
9095 *output_filterMode = 0;
9096 }
9097 else {
9098 int macaddr_acl_mode = strtol(buf, NULL, 10);
9099 if (macaddr_acl_mode == 1) {
9100 *output_filterMode = 1;
9101 } else if (macaddr_acl_mode == 0) {
9102 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9103 if (strlen(buf) == 0) {
9104 *output_filterMode = 0;
9105 } else {
9106 *output_filterMode = 2;
9107 }
9108 } else {
9109 return RETURN_ERR;
9110 }
9111 }
9112
9113 return RETURN_OK;
9114}
9115
9116INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9117{
9118 FILE *fp = NULL;
9119 char str[MAX_BUF_SIZE] = {0};
9120 int wificlientindex = 0 ;
9121 int count = 0;
9122 int signalstrength = 0;
9123 int arr[MACADDRESS_SIZE] = {0};
9124 unsigned char mac[MACADDRESS_SIZE] = {0};
9125 UINT wifi_count = 0;
9126 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9127 char pipeCmd[MAX_CMD_SIZE] = {0};
9128
9129 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9130 *output_array_size = 0;
9131 *associated_dev_array = NULL;
9132 char interface_name[50] = {0};
9133
9134 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9135 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9136 return RETURN_ERR;
9137 }
9138
9139 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9140 fp = popen(pipeCmd, "r");
9141 if (fp == NULL)
9142 {
9143 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9144 return RETURN_ERR;
9145 }
9146
9147 /* Read the output a line at a time - output it. */
9148 fgets(str, sizeof(str)-1, fp);
9149 wifi_count = (unsigned int) atoi ( str );
9150 *output_array_size = wifi_count;
9151 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9152 pclose(fp);
9153
9154 if(wifi_count == 0)
9155 {
9156 return RETURN_OK;
9157 }
9158 else
9159 {
9160 wifi_associated_dev2_t* temp = NULL;
9161 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9162 *associated_dev_array = temp;
9163 if(temp == NULL)
9164 {
9165 printf("Error Statement. Insufficient memory \n");
9166 return RETURN_ERR;
9167 }
9168
9169 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9170 system(pipeCmd);
9171
9172 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9173 if(fp == NULL)
9174 {
9175 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9176 return RETURN_ERR;
9177 }
9178 fclose(fp);
9179
9180 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
9181 fp = popen(pipeCmd, "r");
9182 if(fp)
9183 {
9184 for(count =0 ; count < wifi_count; count++)
9185 {
9186 fgets(str, MAX_BUF_SIZE, fp);
9187 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9188 {
9189 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9190 {
9191 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9192
9193 }
9194 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9195 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]);
9196 }
9197 temp[count].cli_AuthenticationState = 1; //TODO
9198 temp[count].cli_Active = 1; //TODO
9199 }
9200 pclose(fp);
9201 }
9202
9203 //Updating RSSI per client
9204 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
9205 fp = popen(pipeCmd, "r");
9206 if(fp)
9207 {
9208 pclose(fp);
9209 }
9210 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9211 if(fp)
9212 {
9213 for(count =0 ; count < wifi_count ;count++)
9214 {
9215 fgets(str, MAX_BUF_SIZE, fp);
9216 signalstrength = atoi(str);
9217 temp[count].cli_RSSI = signalstrength;
9218 }
9219 pclose(fp);
9220 }
9221
9222
9223 //LastDataDownlinkRate
9224 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
9225 fp = popen(pipeCmd, "r");
9226 if (fp)
9227 {
9228 pclose(fp);
9229 }
9230 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9231 if (fp)
9232 {
9233 for (count = 0; count < wifi_count; count++)
9234 {
9235 fgets(str, MAX_BUF_SIZE, fp);
9236 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9237 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9238 }
9239 pclose(fp);
9240 }
9241
9242 //LastDataUplinkRate
9243 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
9244 fp = popen(pipeCmd, "r");
9245 if (fp)
9246 {
9247 pclose(fp);
9248 }
9249 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9250 if (fp)
9251 {
9252 for (count = 0; count < wifi_count; count++)
9253 {
9254 fgets(str, MAX_BUF_SIZE, fp);
9255 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9256 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9257 }
9258 pclose(fp);
9259 }
9260 }
9261 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9262 return RETURN_OK;
9263
9264}
9265
9266INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9267{
9268#if 0
9269 /*char buf[1024] = {0};
9270 sprintf(cmd, "ifconfig %s ", interface_name);
9271 _syscmd(cmd, buf, sizeof(buf));*/
9272
9273 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9274 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9275 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9276 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9277
9278 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.
9279 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].
9280 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].
9281 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].
9282 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9283 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9284
9285 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9286 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9287 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9288 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.
9289 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.
9290 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.
9291 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.
9292 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.
9293 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.
9294 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.
9295 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9296#endif
9297
9298 FILE *fp = NULL;
9299 char interface_name[50] = {0};
9300 char pipeCmd[128] = {0};
9301 char str[256] = {0};
9302 wifi_ssidTrafficStats2_t *out = output_struct;
9303
9304 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9305 if (!output_struct)
9306 return RETURN_ERR;
9307
9308 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9309 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
9310 return RETURN_ERR;
9311 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
9312
9313 fp = popen(pipeCmd, "r");
9314 if (fp == NULL) {
9315 fprintf(stderr, "%s: popen failed\n", __func__);
9316 return RETURN_ERR;
9317 }
9318 fgets(str, sizeof(str), fp);
9319 pclose(fp);
9320
9321 if (strlen(str) == 0) // interface not exist
9322 return RETURN_OK;
9323
9324 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9325 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
9326
9327 memset(str, 0, sizeof(str));
9328 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
9329 fp = popen(pipeCmd, "r");
9330 if (fp == NULL) {
9331 fprintf(stderr, "%s: popen failed\n", __func__);
9332 return RETURN_ERR;
9333 }
9334 fgets(str, sizeof(str), fp);
9335
9336 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9337 &out->ssid_BroadcastPacketsSent);
9338 pclose(fp);
9339
9340 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9341 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9342
9343 // Not supported
9344 output_struct->ssid_RetransCount = 0;
9345 output_struct->ssid_FailedRetransCount = 0;
9346 output_struct->ssid_RetryCount = 0;
9347 output_struct->ssid_MultipleRetryCount = 0;
9348 output_struct->ssid_ACKFailureCount = 0;
9349 output_struct->ssid_AggregatedPacketCount = 0;
9350
9351 return RETURN_OK;
9352}
9353
9354//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).
9355INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9356{
9357 char output_val[16]={'\0'};
9358 char config_file[MAX_BUF_SIZE] = {0};
9359
9360 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9361 if (!output)
9362 return RETURN_ERR;
9363 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9364 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9365
9366 if( strcmp(output_val,"1") == 0 )
9367 *output = TRUE;
9368 else
9369 *output = FALSE;
9370 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9371
9372 return RETURN_OK;
9373}
9374
9375INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9376{
9377 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9378 char str[MAX_BUF_SIZE]={'\0'};
9379 char string[MAX_BUF_SIZE]={'\0'};
9380 char cmd[MAX_CMD_SIZE]={'\0'};
9381 char *ch;
9382 char config_file[MAX_BUF_SIZE] = {0};
9383 struct params params;
9384
9385 if(enable == TRUE)
9386 strcpy(string,"1");
9387 else
9388 strcpy(string,"0");
9389
9390 params.name = "ap_isolate";
9391 params.value = string;
9392
9393 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9394 wifi_hostapdWrite(config_file,&params,1);
9395 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9396
9397 return RETURN_OK;
9398}
9399
9400INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9401{
9402 if (NULL == output_dBm)
9403 return RETURN_ERR;
9404
9405 *output_dBm = 0;
9406 return RETURN_OK;
9407}
9408
9409INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9410{
9411 return RETURN_OK;
9412}
9413INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9414{
9415 return RETURN_OK;
9416}
9417INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9418{
9419 return RETURN_OK;
9420}
9421INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9422{
9423 return RETURN_OK;
9424}
9425INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9426{
9427 return RETURN_OK;
9428}
9429INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9430{
9431 char config_file[MAX_BUF_SIZE] = {0};
9432 struct params list;
9433
9434 list.name = "bss_transition";
9435 list.value = activate?"1":"0";
9436 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9437 wifi_hostapdWrite(config_file, &list, 1);
9438
9439 return RETURN_OK;
9440}
9441wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9442
9443void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9444{
9445 return;
9446}
9447
9448INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9449{
9450 // TODO Implement me!
9451 return RETURN_OK;
9452}
9453
9454INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9455{
9456 char file_name[128] = {0};
9457 char buf[128] = {0};
9458 FILE *f = NULL;
9459 int max_num_radios = 0;
9460
9461 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9462
9463 wifi_getMaxRadioNumber(&max_num_radios);
9464 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
9465 for (int index = 0; index < max_num_radios; index++) {
9466 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9467 f = fopen(file_name, "w");
9468 if (f == NULL)
9469 return RETURN_ERR;
9470 // For mode == 0 is to disable filter, just don't write to the file.
9471 if (mode)
9472 fprintf(f, "%s", essid);
9473
9474 fclose(f);
9475 }
9476 } else { // special case, need to set AP's SSID as filter for each radio.
9477 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9478 f = fopen(file_name, "w");
9479 if (f == NULL)
9480 return RETURN_ERR;
9481
9482 // For mode == 0 is to disable filter, just don't write to the file.
9483 if (mode)
9484 fprintf(f, "%s", essid);
9485
9486 fclose(f);
9487 }
9488
9489 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9490 return RETURN_OK;
9491}
9492
9493INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9494{
9495 // TODO Implement me!
9496 //Apply wifi_pushRadioChannel() instantly
9497 return RETURN_ERR;
9498}
9499
9500INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9501{
9502 // TODO Implement me!
9503 return RETURN_OK;
9504}
9505
9506#ifdef HAL_NETLINK_IMPL
9507static int tidStats_callback(struct nl_msg *msg, void *arg) {
9508 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9509 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9510 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9511 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9512 int rem , tid_index = 0;
9513
9514 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9515 wifi_associated_dev_tid_entry_t *stats_entry;
9516
9517 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9518 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9519 };
9520 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9521 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9522 };
9523
9524 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9525 genlmsg_attrlen(gnlh, 0), NULL);
9526
9527
9528 if (!tb[NL80211_ATTR_STA_INFO]) {
9529 fprintf(stderr, "station stats missing!\n");
9530 return NL_SKIP;
9531 }
9532
9533 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9534 tb[NL80211_ATTR_STA_INFO],
9535 stats_policy)) {
9536 fprintf(stderr, "failed to parse nested attributes!\n");
9537 return NL_SKIP;
9538 }
9539
9540 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9541 {
9542 stats_entry = &out->tid_array[tid_index];
9543
9544 stats_entry->tid = tid_index;
9545 stats_entry->ac = _tid_ac_index_get[tid_index];
9546
9547 if(sinfo[NL80211_STA_INFO_TID_STATS])
9548 {
9549 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9550 printf("failed to parse nested stats attributes!");
9551 return NL_SKIP;
9552 }
9553 }
9554 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9555 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9556
9557 if(tid_index < (PS_MAX_TID - 1))
9558 tid_index++;
9559 }
9560 //ToDo: sum_time_ms, ewma_time_ms
9561 return NL_SKIP;
9562}
9563#endif
9564
9565INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9566{
9567#ifdef HAL_NETLINK_IMPL
9568 Netlink nl;
9569 char if_name[10];
9570 char interface_name[16] = {0};
9571
9572 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9573 return RETURN_ERR;
9574
9575 snprintf(if_name, sizeof(if_name), "%s", interface_name);
9576
9577 nl.id = initSock80211(&nl);
9578
9579 if (nl.id < 0) {
9580 fprintf(stderr, "Error initializing netlink \n");
9581 return -1;
9582 }
9583
9584 struct nl_msg* msg = nlmsg_alloc();
9585
9586 if (!msg) {
9587 fprintf(stderr, "Failed to allocate netlink message.\n");
9588 nlfree(&nl);
9589 return -2;
9590 }
9591
9592 genlmsg_put(msg,
9593 NL_AUTO_PORT,
9594 NL_AUTO_SEQ,
9595 nl.id,
9596 0,
9597 0,
9598 NL80211_CMD_GET_STATION,
9599 0);
9600
9601 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9602 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9603 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9604 nl_send_auto(nl.socket, msg);
9605 nl_recvmsgs(nl.socket, nl.cb);
9606 nlmsg_free(msg);
9607 nlfree(&nl);
9608 return RETURN_OK;
9609#else
9610//iw implementation
9611#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9612#define TOTAL_MAX_LINES 50
9613
9614 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9615 char if_name[32] = {0};
9616 FILE *fp=NULL;
9617 char pipeCmd[1024]= {'\0'};
9618 int lines,tid_index=0;
9619 char mac_addr[20] = {'\0'};
9620
9621 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9622 return RETURN_ERR;
9623
9624 wifi_associated_dev_tid_entry_t *stats_entry;
9625
9626 strcpy(mac_addr,clientMacAddress);
9627
9628 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9629 fp= popen(pipeCmd,"r");
9630 if(fp == NULL)
9631 {
9632 perror("popen for station dump failed\n");
9633 return RETURN_ERR;
9634 }
9635 pclose(fp);
9636
9637 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9638 fp=popen(pipeCmd,"r");
9639 if(fp == NULL)
9640 {
9641 perror("popen for grep station failed\n");
9642 return RETURN_ERR;
9643 }
9644 else if(fgets(buf,sizeof(buf),fp) != NULL)
9645 lines=atoi(buf);
9646 else
9647 {
9648 pclose(fp);
9649 fprintf(stderr,"No devices are connected \n");
9650 return RETURN_ERR;
9651 }
9652 pclose(fp);
9653
9654 if(lines == 1)
9655 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9656
9657 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9658 {
9659 stats_entry = &tid_stats->tid_array[tid_index];
9660 stats_entry->tid = tid_index;
9661
9662 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);
9663
9664 fp=popen(pipeCmd,"r");
9665 if(fp ==NULL)
9666 {
9667 perror("Failed to read from tid file \n");
9668 return RETURN_ERR;
9669 }
9670 else if(fgets(buf,sizeof(buf),fp) != NULL)
9671 stats_entry->num_msdus = atol(buf);
9672
9673 pclose(fp);
9674 stats_entry->ac = _tid_ac_index_get[tid_index];
9675// TODO:
9676// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9677// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9678 }
9679 return RETURN_OK;
9680#endif
9681}
9682
9683
9684INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9685{
9686 char interface_name[16] = {0};
9687 char cmd[128]={0};
9688 char buf[128]={0};
9689 int freq = 0;
9690
9691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9692
9693 // full mode is used to scan all channels.
9694 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9695 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9696 ieee80211_channel_to_frequency(chan_list[0], &freq);
9697
9698 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9699 return RETURN_ERR;
9700
9701 if (freq)
9702 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
9703 else
9704 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
9705
9706 _syscmd(cmd, buf, sizeof(buf));
9707 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9708
9709 return RETURN_OK;
9710}
9711
9712
9713INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9714{
9715 // TODO Implement me!
9716 return RETURN_ERR;
9717}
9718
9719INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9720{
9721 // TODO Implement me!
9722 return RETURN_ERR;
9723}
9724
9725INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9726{
9727 // TODO Implement me!
9728 return RETURN_ERR;
9729}
9730
9731INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9732{
9733 // TODO Implement me!
9734 return RETURN_ERR;
9735}
9736
9737INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9738{
9739 // TODO Implement me!
9740 return RETURN_ERR;
9741}
9742
9743INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9744{
9745 // TODO Implement me!
9746 return RETURN_ERR;
9747}
9748
9749INT wifi_steering_eventUnregister(void)
9750{
9751 // TODO Implement me!
9752 return RETURN_ERR;
9753}
9754
9755INT wifi_delApAclDevices(INT apIndex)
9756{
9757#if 0
9758 char cmd[MAX_BUF_SIZE] = {0};
9759 char buf[MAX_BUF_SIZE] = {0};
9760
9761 /* Not reset proof solution */
9762 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
9763 if(_syscmd(cmd,buf,sizeof(buf)))
9764 return RETURN_ERR;
9765#endif
9766 char cmd[MAX_CMD_SIZE]={0};
9767 char buf[MAX_BUF_SIZE]={0};
9768
9769 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9770 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9771 if(_syscmd(cmd, buf, sizeof(buf)))
9772 return RETURN_ERR;
9773 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9774
9775 return RETURN_OK;
9776}
9777
9778#ifdef HAL_NETLINK_IMPL
9779static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9780 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9781 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9782 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9783 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9784 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9785 char mac_addr[20],dev[20];
9786
9787 nla_parse(tb,
9788 NL80211_ATTR_MAX,
9789 genlmsg_attrdata(gnlh, 0),
9790 genlmsg_attrlen(gnlh, 0),
9791 NULL);
9792
9793 if(!tb[NL80211_ATTR_STA_INFO]) {
9794 fprintf(stderr, "sta stats missing!\n");
9795 return NL_SKIP;
9796 }
9797
9798 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9799 fprintf(stderr, "failed to parse nested attributes!\n");
9800 return NL_SKIP;
9801 }
9802 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9803
9804 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9805
9806 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9807 fprintf(stderr, "failed to parse nested rate attributes!");
9808 return NL_SKIP;
9809 }
9810
9811 if(sinfo[NL80211_STA_INFO_TID_STATS])
9812 {
9813 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9814 printf("failed to parse nested stats attributes!");
9815 return NL_SKIP;
9816 }
9817 }
9818
9819 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9820 {
9821 printf("Type is VHT\n");
9822 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9823 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9824
9825 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9826 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9827 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9828 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9829 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9830 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9831 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9832 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9833 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9834 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9835 }
9836 else
9837 {
9838 printf(" OFDM or CCK \n");
9839 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9840 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9841 }
9842
9843 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9844 if(rinfo[NL80211_RATE_INFO_MCS])
9845 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9846 }
9847 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9848 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9849 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9850 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9851
9852 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9853 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9854
9855 if (sinfo[NL80211_STA_INFO_SIGNAL])
9856 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9857 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9858 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9859 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9860 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9861 //rssi_array need to be filled
9862 return NL_SKIP;
9863}
9864#endif
9865
9866INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9867{
9868#ifdef HAL_NETLINK_IMPL
9869 Netlink nl;
9870 char if_name[32];
9871 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9872 return RETURN_ERR;
9873
9874 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9875
9876 if (*output_array_size <= 0)
9877 return RETURN_OK;
9878
9879 nl.id = initSock80211(&nl);
9880
9881 if (nl.id < 0) {
9882 fprintf(stderr, "Error initializing netlink \n");
9883 return 0;
9884 }
9885
9886 struct nl_msg* msg = nlmsg_alloc();
9887
9888 if (!msg) {
9889 fprintf(stderr, "Failed to allocate netlink message.\n");
9890 nlfree(&nl);
9891 return 0;
9892 }
9893
9894 genlmsg_put(msg,
9895 NL_AUTO_PORT,
9896 NL_AUTO_SEQ,
9897 nl.id,
9898 0,
9899 0,
9900 NL80211_CMD_GET_STATION,
9901 0);
9902
9903 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9904 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9905 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9906 nl_send_auto(nl.socket, msg);
9907 nl_recvmsgs(nl.socket, nl.cb);
9908 nlmsg_free(msg);
9909 nlfree(&nl);
9910 return RETURN_OK;
9911#else
9912 //TODO Implement me
9913 return RETURN_OK;
9914#endif
9915}
9916
9917#ifdef HAL_NETLINK_IMPL
9918static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9919 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9920 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9921 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9922 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9923 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9924 char mac_addr[20],dev[20];
9925
9926 nla_parse(tb,
9927 NL80211_ATTR_MAX,
9928 genlmsg_attrdata(gnlh, 0),
9929 genlmsg_attrlen(gnlh, 0),
9930 NULL);
9931
9932 if(!tb[NL80211_ATTR_STA_INFO]) {
9933 fprintf(stderr, "sta stats missing!\n");
9934 return NL_SKIP;
9935 }
9936
9937 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9938 fprintf(stderr, "failed to parse nested attributes!\n");
9939 return NL_SKIP;
9940 }
9941
9942 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9943
9944 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9945
9946 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9947 fprintf(stderr, "failed to parse nested rate attributes!");
9948 return NL_SKIP;
9949 }
9950
9951 if(sinfo[NL80211_STA_INFO_TID_STATS])
9952 {
9953 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9954 printf("failed to parse nested stats attributes!");
9955 return NL_SKIP;
9956 }
9957 }
9958 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9959 {
9960 printf("Type is VHT\n");
9961 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9962 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9963
9964 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9965 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9966 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9967 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9968 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9969 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9970 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9971 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9972 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9973 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9974 }
9975 else
9976 {
9977 printf(" OFDM or CCK \n");
9978 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9979 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9980 }
9981
9982 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9983 if(rinfo[NL80211_RATE_INFO_MCS])
9984 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9985 }
9986
9987 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9988 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9989 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9990 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9991
9992 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9993 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9994 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9995
9996 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9997 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9998
9999 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10000 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10001
10002 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10003 ((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]);
10004
10005 return NL_SKIP;
10006}
10007#endif
10008
10009INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10010{
10011#ifdef HAL_NETLINK_IMPL
10012 Netlink nl;
10013 char if_name[10];
10014 char interface_name[16] = {0};
10015 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10016 return RETURN_ERR;
10017
10018 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10019
10020 if (*output_array_size <= 0)
10021 return RETURN_OK;
10022
10023 snprintf(if_name, sizeof(if_name), "%s", interface_name);
10024
10025 nl.id = initSock80211(&nl);
10026
10027 if(nl.id < 0) {
10028 fprintf(stderr, "Error initializing netlink \n");
10029 return 0;
10030 }
10031
10032 struct nl_msg* msg = nlmsg_alloc();
10033
10034 if(!msg) {
10035 fprintf(stderr, "Failed to allocate netlink message.\n");
10036 nlfree(&nl);
10037 return 0;
10038 }
10039
10040 genlmsg_put(msg,
10041 NL_AUTO_PORT,
10042 NL_AUTO_SEQ,
10043 nl.id,
10044 0,
10045 0,
10046 NL80211_CMD_GET_STATION,
10047 0);
10048
10049 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10050 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10051 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10052 nl_send_auto(nl.socket, msg);
10053 nl_recvmsgs(nl.socket, nl.cb);
10054 nlmsg_free(msg);
10055 nlfree(&nl);
10056 return RETURN_OK;
10057#else
10058 //TODO Implement me
10059 return RETURN_OK;
10060#endif
10061}
10062
10063INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10064{
10065 // TODO Implement me!
10066 char buf[MAX_BUF_SIZE] = {0};
10067 char config_file[MAX_BUF_SIZE] = {0};
10068
10069 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10070 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10071 *activate = (strncmp("1",buf,1) == 0);
10072
10073 return RETURN_OK;
10074}
10075
10076INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10077{
10078 char config_file[MAX_BUF_SIZE] = {0};
10079 struct params list;
10080
10081 list.name = "rrm_neighbor_report";
10082 list.value = activate?"1":"0";
10083 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10084 wifi_hostapdWrite(config_file, &list, 1);
10085
10086 return RETURN_OK;
10087}
10088
10089INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10090{
10091 char buf[32] = {0};
10092 char config_file[MAX_BUF_SIZE] = {0};
10093
10094 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10095 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10096 *activate = (strncmp("1",buf,1) == 0);
10097
10098 return RETURN_OK;
10099}
10100#undef HAL_NETLINK_IMPL
10101#ifdef HAL_NETLINK_IMPL
10102static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10103 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10104 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10105 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10106 char dev[20];
10107 int freq =0 ;
10108 static int i=0;
10109
10110 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10111
10112 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10113 };
10114
10115 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10116
10117 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10118
10119 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10120 fprintf(stderr, "survey data missing!\n");
10121 return NL_SKIP;
10122 }
10123
10124 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10125 {
10126 fprintf(stderr, "failed to parse nested attributes!\n");
10127 return NL_SKIP;
10128 }
10129
10130
10131 if(out[0].array_size == 1 )
10132 {
10133 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10134 {
10135 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10136 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10137 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10138
10139 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10140 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10141 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10142 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10143 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10144 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10145 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10146 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10147 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10148 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10149 if (sinfo[NL80211_SURVEY_INFO_TIME])
10150 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10151 return NL_STOP;
10152 }
10153 }
10154 else
10155 {
10156 if ( i <= out[0].array_size )
10157 {
10158 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10159 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10160 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10161
10162 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10163 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10164 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10165 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10166 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10167 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10168 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10169 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10170 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10171 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10172 if (sinfo[NL80211_SURVEY_INFO_TIME])
10173 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10174 }
10175 }
10176
10177 i++;
10178 return NL_SKIP;
10179}
10180#endif
10181
10182static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10183{
10184 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10185 FILE *fp;
10186
10187 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10188 {
10189 printf("Creating Frequency-Channel Map\n");
10190 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10191 }
10192 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10193 if((fp = popen(command, "r")))
10194 {
10195 fgets(output, sizeof(output), fp);
10196 *freqMHz = atoi(output);
10197 pclose(fp);
10198 }
10199
10200 return 0;
10201}
10202
10203static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10204{
10205 int freqMHz = -1;
10206 char cmd[MAX_CMD_SIZE] = {'\0'};
10207 char interface_name[16] = {0};
10208
10209 ieee80211_channel_to_frequency(channel, &freqMHz);
10210 if (freqMHz == -1) {
10211 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10212 return -1;
10213 }
10214
10215 wifi_GetInterfaceName(radioIndex, interface_name);
10216 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
10217 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10218 radioIndex, freqMHz);
10219 return -1;
10220 }
10221
10222 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10223 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10224 return -1;
10225 }
10226
10227 return 0;
10228}
10229
10230static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10231{
10232 const char *ptr = buf;
10233 char *key = NULL;
10234 char *val = NULL;
10235 char line[256] = { '\0' };
10236
10237 while (ptr = get_line_from_str_buf(ptr, line)) {
10238 if (strstr(line, "Frequency")) continue;
10239
10240 key = strtok(line, ":");
10241 val = strtok(NULL, " ");
10242 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10243
10244 if (!strcmp(key, "noise")) {
10245 sscanf(val, "%d", &stats->ch_noise);
10246 if (stats->ch_noise == 0) {
10247 // Workaround for missing noise information.
10248 // Assume -95 for 2.4G and -103 for 5G
10249 if (radioIndex == 0) stats->ch_noise = -95;
10250 if (radioIndex == 1) stats->ch_noise = -103;
10251 }
10252 }
10253 else if (!strcmp(key, "channel active time")) {
10254 sscanf(val, "%llu", &stats->ch_utilization_total);
10255 }
10256 else if (!strcmp(key, "channel busy time")) {
10257 sscanf(val, "%llu", &stats->ch_utilization_busy);
10258 }
10259 else if (!strcmp(key, "channel receive time")) {
10260 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10261 }
10262 else if (!strcmp(key, "channel transmit time")) {
10263 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10264 }
10265 };
10266
10267 return 0;
10268}
10269
10270INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10271{
10272 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10273#ifdef HAL_NETLINK_IMPL
10274 Netlink nl;
10275 wifi_channelStats_t_loc local[array_size];
10276 char if_name[32];
10277
10278 local[0].array_size = array_size;
10279
10280 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10281 return RETURN_ERR;
10282
10283 nl.id = initSock80211(&nl);
10284
10285 if (nl.id < 0) {
10286 fprintf(stderr, "Error initializing netlink \n");
10287 return -1;
10288 }
10289
10290 struct nl_msg* msg = nlmsg_alloc();
10291
10292 if (!msg) {
10293 fprintf(stderr, "Failed to allocate netlink message.\n");
10294 nlfree(&nl);
10295 return -2;
10296 }
10297
10298 genlmsg_put(msg,
10299 NL_AUTO_PORT,
10300 NL_AUTO_SEQ,
10301 nl.id,
10302 0,
10303 NLM_F_DUMP,
10304 NL80211_CMD_GET_SURVEY,
10305 0);
10306
10307 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10308 nl_send_auto(nl.socket, msg);
10309 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10310 nl_recvmsgs(nl.socket, nl.cb);
10311 nlmsg_free(msg);
10312 nlfree(&nl);
10313 //Copying the Values
10314 for(int i=0;i<array_size;i++)
10315 {
10316 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10317 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10318 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10319 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10320 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10321 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10322 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10323 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10324 }
10325#else
10326 ULONG channel = 0;
10327 int i;
10328 int number_of_channels = array_size;
10329 char buf[512];
10330 INT ret;
10331 wifi_channelStats_t tmp_stats;
10332
10333 if (number_of_channels == 0) {
10334 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10335 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10336 return RETURN_ERR;
10337 }
10338 number_of_channels = 1;
10339 input_output_channelStats_array[0].ch_number = channel;
10340 }
10341
10342 for (i = 0; i < number_of_channels; i++) {
10343
10344 input_output_channelStats_array[i].ch_noise = 0;
10345 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10346 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10347 input_output_channelStats_array[i].ch_utilization_busy = 0;
10348 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10349 input_output_channelStats_array[i].ch_utilization_total = 0;
10350
10351 memset(buf, 0, sizeof(buf));
10352 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10353 return RETURN_ERR;
10354 }
10355 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10356 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10357 return RETURN_ERR;
10358 }
10359
10360 // XXX: fake missing 'self' counter which is not available in iw survey output
10361 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10362 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10363
10364 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10365 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10366 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10367 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10368 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10369
10370 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",
10371 __func__,
10372 input_output_channelStats_array[i].ch_number,
10373 input_output_channelStats_array[i].ch_noise,
10374 input_output_channelStats_array[i].ch_utilization_total,
10375 input_output_channelStats_array[i].ch_utilization_busy,
10376 input_output_channelStats_array[i].ch_utilization_busy_rx,
10377 input_output_channelStats_array[i].ch_utilization_busy_tx,
10378 input_output_channelStats_array[i].ch_utilization_busy_self,
10379 input_output_channelStats_array[i].ch_utilization_busy_ext);
10380 }
10381#endif
10382 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10383 return RETURN_OK;
10384}
10385#define HAL_NETLINK_IMPL
10386
10387/* Hostapd events */
10388
10389#ifndef container_of
10390#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10391#define container_of(ptr, type, member) \
10392 ((type *)((char *)ptr - offset_of(type, member)))
10393#endif /* container_of */
10394
10395struct ctrl {
10396 char sockpath[128];
10397 char sockdir[128];
10398 char bss[IFNAMSIZ];
10399 char reply[4096];
10400 int ssid_index;
10401 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10402 void (*overrun)(struct ctrl *ctrl);
10403 struct wpa_ctrl *wpa;
10404 unsigned int ovfl;
10405 size_t reply_len;
10406 int initialized;
10407 ev_timer retry;
10408 ev_timer watchdog;
10409 ev_stat stat;
10410 ev_io io;
10411};
10412static wifi_newApAssociatedDevice_callback clients_connect_cb;
10413static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10414static struct ctrl wpa_ctrl[MAX_APS];
10415static int initialized;
10416
10417static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10418{
10419 char cbuf[256] = {};
10420 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10421 struct cmsghdr *cmsg;
10422 unsigned int ovfl = ctrl->ovfl;
10423 unsigned int drop;
10424
10425 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10426 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10427 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10428 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10429
10430 drop = ovfl - ctrl->ovfl;
10431 ctrl->ovfl = ovfl;
10432
10433 return drop;
10434}
10435
10436static void ctrl_close(struct ctrl *ctrl)
10437{
10438 if (ctrl->io.cb)
10439 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10440 if (ctrl->retry.cb)
10441 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10442 if (!ctrl->wpa)
10443 return;
10444
10445 wpa_ctrl_detach(ctrl->wpa);
10446 wpa_ctrl_close(ctrl->wpa);
10447 ctrl->wpa = NULL;
10448 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10449}
10450
10451static void ctrl_process(struct ctrl *ctrl)
10452{
10453 const char *str;
10454 int drops;
10455 int level;
10456 int err;
10457
10458 /* Example events:
10459 *
10460 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10461 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10462 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10463 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10464 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10465 */
10466 if (!(str = index(ctrl->reply, '>')))
10467 return;
10468 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10469 return;
10470
10471 str++;
10472
10473 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10474 if (!(str = index(ctrl->reply, ' ')))
10475 return;
10476 wifi_associated_dev_t sta;
10477 memset(&sta, 0, sizeof(sta));
10478
10479 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10480 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10481 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10482
10483 sta.cli_Active=true;
10484
10485 (clients_connect_cb)(ctrl->ssid_index, &sta);
10486 goto handled;
10487 }
10488
10489 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10490 if (!(str = index(ctrl->reply, ' ')))
10491 return;
10492
10493 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10494 goto handled;
10495 }
10496
10497 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10498 printf("CTRL_WPA: handle TERMINATING event\n");
10499 goto retry;
10500 }
10501
10502 if (strncmp("AP-DISABLED", str, 11) == 0) {
10503 printf("CTRL_WPA: handle AP-DISABLED\n");
10504 goto retry;
10505 }
10506
10507 printf("Event not supported!!\n");
10508
10509handled:
10510
10511 if ((drops = ctrl_get_drops(ctrl))) {
10512 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10513 if (ctrl->overrun)
10514 ctrl->overrun(ctrl);
10515 }
10516
10517 return;
10518
10519retry:
10520 printf("WPA_CTRL: closing\n");
10521 ctrl_close(ctrl);
10522 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10523 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10524}
10525
10526static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10527{
10528 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10529 int err;
10530
10531 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10532 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10533 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10534 ctrl->reply[ctrl->reply_len] = 0;
10535 if (err < 0) {
10536 if (errno == EAGAIN || errno == EWOULDBLOCK)
10537 return;
10538 ctrl_close(ctrl);
10539 ev_timer_again(EV_A_ &ctrl->retry);
10540 return;
10541 }
10542
10543 ctrl_process(ctrl);
10544}
10545
10546static int ctrl_open(struct ctrl *ctrl)
10547{
10548 int fd;
10549
10550 if (ctrl->wpa)
10551 return 0;
10552
10553 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10554 if (!ctrl->wpa)
10555 goto err;
10556
10557 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10558 goto err_close;
10559
10560 fd = wpa_ctrl_get_fd(ctrl->wpa);
10561 if (fd < 0)
10562 goto err_detach;
10563
10564 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10565 goto err_detach;
10566
10567 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10568 ev_io_start(EV_DEFAULT_ &ctrl->io);
10569
10570 return 0;
10571
10572err_detach:
10573 wpa_ctrl_detach(ctrl->wpa);
10574err_close:
10575 wpa_ctrl_close(ctrl->wpa);
10576err:
10577 ctrl->wpa = NULL;
10578 return -1;
10579}
10580
10581static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10582{
10583 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10584
10585 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10586 ctrl_open(ctrl);
10587}
10588
10589static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10590{
10591 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10592
10593 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10594 if (ctrl_open(ctrl) == 0) {
10595 printf("WPA_CTRL: retry successful\n");
10596 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10597 }
10598}
10599
10600int ctrl_enable(struct ctrl *ctrl)
10601{
10602 if (ctrl->wpa)
10603 return 0;
10604
10605 if (!ctrl->stat.cb) {
10606 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10607 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10608 }
10609
10610 if (!ctrl->retry.cb) {
10611 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10612 }
10613
10614 return ctrl_open(ctrl);
10615}
10616
10617static void
10618ctrl_msg_cb(char *buf, size_t len)
10619{
10620 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10621
10622 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10623 ctrl_process(ctrl);
10624}
10625
10626static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10627{
10628 int err;
10629
10630 if (!ctrl->wpa)
10631 return -1;
10632 if (*reply_len < 2)
10633 return -1;
10634
10635 (*reply_len)--;
10636 ctrl->reply_len = sizeof(ctrl->reply);
10637 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10638 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10639 if (err < 0)
10640 return err;
10641
10642 if (ctrl->reply_len > *reply_len)
10643 ctrl->reply_len = *reply_len;
10644
10645 *reply_len = ctrl->reply_len;
10646 memcpy(reply, ctrl->reply, *reply_len);
10647 reply[*reply_len - 1] = 0;
10648 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10649 return 0;
10650}
10651
10652static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10653{
10654 const char *pong = "PONG";
10655 const char *ping = "PING";
10656 char reply[1024];
10657 size_t len = sizeof(reply);
10658 int err;
10659 ULONG s, snum;
10660 INT ret;
10661 BOOL status;
10662
10663 printf("WPA_CTRL: watchdog cb\n");
10664
10665 ret = wifi_getSSIDNumberOfEntries(&snum);
10666 if (ret != RETURN_OK) {
10667 printf("%s: failed to get SSID count", __func__);
10668 return;
10669 }
10670
10671 if (snum > MAX_APS) {
10672 printf("more ssid than supported! %lu\n", snum);
10673 return;
10674 }
10675
10676 for (s = 0; s < snum; s++) {
10677 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10678 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
10679 continue;
10680 }
10681 if (status == false) continue;
10682
10683 memset(reply, 0, sizeof(reply));
10684 len = sizeof(reply);
10685 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10686 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10687 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10688 continue;
10689
10690 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10691 ctrl_close(&wpa_ctrl[s]);
10692 printf("WPA_CTRL: ev_timer_again %lu\n", s);
10693 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10694 }
10695}
10696
10697static int init_wpa()
10698{
10699 int ret = 0, i = 0;
10700 ULONG s, snum;
10701
10702 ret = wifi_getSSIDNumberOfEntries(&snum);
10703 if (ret != RETURN_OK) {
10704 printf("%s: failed to get SSID count", __func__);
10705 return RETURN_ERR;
10706 }
10707
10708 if (snum > MAX_APS) {
10709 printf("more ssid than supported! %lu\n", snum);
10710 return RETURN_ERR;
10711 }
10712
10713 for (s = 0; s < snum; s++) {
10714 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10715 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10716 wpa_ctrl[s].ssid_index = s;
10717 ctrl_enable(&wpa_ctrl[s]);
10718 }
10719
10720 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10721 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10722
10723 initialized = 1;
10724 printf("WPA_CTRL: initialized\n");
10725
10726 return RETURN_OK;
10727}
10728
10729void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10730{
10731 clients_connect_cb = callback_proc;
10732 if (!initialized)
10733 init_wpa();
10734}
10735
10736void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10737{
10738 clients_disconnect_cb = callback_proc;
10739 if (!initialized)
10740 init_wpa();
10741}
10742
10743INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10744{
10745 // TODO Implement me!
10746 return RETURN_ERR;
10747}
10748
10749INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10750{
10751 // TODO Implement me!
10752 return RETURN_ERR;
10753}
10754
10755INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10756{
10757 int i;
10758 char cmd[256];
10759 char channel_numbers_buf[256];
10760 char dfs_state_buf[256];
10761 char line[256];
10762 const char *ptr;
10763
10764 memset(cmd, 0, sizeof(cmd));
10765 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10766 memset(line, 0, sizeof(line));
10767 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10768 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10769
10770 if (radioIndex == 0) { // 2.4G - all allowed
10771 if (outputMapSize < 11) {
10772 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10773 return RETURN_ERR;
10774 }
10775
10776 for (i = 0; i < 11; i++) {
10777 outputMap[i].ch_number = i + 1;
10778 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10779 }
10780
10781 return RETURN_OK;
10782 }
10783
10784 if (radioIndex == 1) { // 5G
10785// Example output of iw list:
10786//
10787// Frequencies:
10788// * 5180 MHz [36] (17.0 dBm)
10789// * 5200 MHz [40] (17.0 dBm)
10790// * 5220 MHz [44] (17.0 dBm)
10791// * 5240 MHz [48] (17.0 dBm)
10792// * 5260 MHz [52] (23.0 dBm) (radar detection)
10793// DFS state: usable (for 78930 sec)
10794// DFS CAC time: 60000 ms
10795// * 5280 MHz [56] (23.0 dBm) (radar detection)
10796// DFS state: usable (for 78930 sec)
10797// DFS CAC time: 60000 ms
10798// * 5300 MHz [60] (23.0 dBm) (radar detection)
10799// DFS state: usable (for 78930 sec)
10800// DFS CAC time: 60000 ms
10801// * 5320 MHz [64] (23.0 dBm) (radar detection)
10802// DFS state: usable (for 78930 sec)
10803// DFS CAC time: 60000 ms
10804// * 5500 MHz [100] (disabled)
10805// * 5520 MHz [104] (disabled)
10806// * 5540 MHz [108] (disabled)
10807// * 5560 MHz [112] (disabled)
10808//
10809// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10810 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10811 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10812 return RETURN_ERR;
10813 }
10814
10815 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10816 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10817 return RETURN_ERR;
10818 }
10819
10820 ptr = channel_numbers_buf;
10821 i = 0;
10822 while (ptr = get_line_from_str_buf(ptr, line)) {
10823 if (i >= outputMapSize) {
10824 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10825 return RETURN_ERR;
10826 }
10827 sscanf(line, "%d", &outputMap[i].ch_number);
10828
10829 memset(cmd, 0, sizeof(cmd));
10830 // Below command should fetch string for DFS state (usable, available or unavailable)
10831 // Example line: "DFS state: usable (for 78930 sec)"
10832 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) {
10833 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10834 return RETURN_ERR;
10835 }
10836
10837 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10838 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10839 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10840 return RETURN_ERR;
10841 }
10842
10843 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10844
10845 if (!strcmp(dfs_state_buf, "usable")) {
10846 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10847 } else if (!strcmp(dfs_state_buf, "available")) {
10848 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10849 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10850 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10851 } else {
10852 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10853 }
10854 i++;
10855 }
10856
10857 return RETURN_OK;
10858 }
10859
10860 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10861 return RETURN_ERR;
10862}
10863
10864INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10865{
10866 // TODO Implement me!
10867 return RETURN_ERR;
10868}
10869
10870INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10871{
10872 return RETURN_OK;
10873}
10874
10875INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10876{
10877 // TODO Implement me!
10878 return RETURN_ERR;
10879}
10880
10881INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10882{
10883 // TODO API refrence Implementaion is present on RPI hal
10884 return RETURN_ERR;
10885}
10886
10887INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10888{
10889 char interface_name[16] = {0};
10890 char cmd[128]={'\0'};
10891 char buf[128]={'\0'};
10892 char *support;
10893 int maximum_tx = 0, current_tx = 0;
10894
10895 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10896 if(txpwr_pcntg == NULL)
10897 return RETURN_ERR;
10898
10899 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10900 return RETURN_ERR;
10901
10902 // Get the maximum tx power of the device
10903 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
10904 _syscmd(cmd, buf, sizeof(buf));
10905 maximum_tx = strtol(buf, NULL, 10);
10906
10907 // Get the current tx power
10908 memset(cmd, 0, sizeof(cmd));
10909 memset(buf, 0, sizeof(buf));
10910 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
10911 _syscmd(cmd, buf, sizeof(buf));
10912 current_tx = strtol(buf, NULL, 10);
10913
10914 // Get the power supported list and find the current power percentage in supported list
10915 memset(buf, 0, sizeof(buf));
10916 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10917 support = strtok(buf, ",");
10918 while(true)
10919 {
10920 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10921 *txpwr_pcntg = 100;
10922 wifi_dbg_printf("current power is not in supported list\n");
10923 return RETURN_OK;
10924 }
10925 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10926 if (tmp == current_tx) {
10927 *txpwr_pcntg = strtol(support, NULL, 10);
10928 break;
10929 }
10930 support = strtok(NULL, ",");
10931 }
10932 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10933 return RETURN_OK;
10934}
10935
10936INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10937{
10938 // TODO precac feature.
10939 struct params params = {0};
10940 char config_file[128] = {0};
10941
10942 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10943
10944 params.name = "enable_background_radar";
10945 params.value = enable?"1":"0";
10946 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10947 wifi_hostapdWrite(config_file, &params, 1);
10948 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10949
10950 /* TODO precac feature */
10951
10952 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10953 return RETURN_OK;
10954}
10955
10956INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10957{
10958 char config_file[128] = {0};
10959 char buf[64] = {0};
10960
10961 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10962 if (NULL == enable || NULL == precac)
10963 return RETURN_ERR;
10964
10965 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10966 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10967 if (strncmp(enable, "1", 1) == 0)
10968 *enable = true;
10969 else
10970 *enable = false;
10971
10972 /* TODO precac feature */
10973
10974 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10975 return RETURN_OK;
10976}
10977
10978INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10979{
10980 *supported = TRUE;
10981 return RETURN_OK;
10982}
10983
10984INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10985{
10986 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10987 struct params params = {0};
10988 char config_file[64] = {0};
10989 char buf[64] = {0};
10990 unsigned int set_mu_type = 0;
10991 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10992
10993 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10994 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10995
10996 if (strlen(buf) > 0)
10997 set_mu_type = strtol(buf, NULL, 10);
10998
10999 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11000 set_mu_type &= ~0x05; // unset bit 0, 2
11001 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11002 set_mu_type |= 0x01;
11003 set_mu_type &= ~0x04;
11004 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11005 set_mu_type &= ~0x01;
11006 set_mu_type |= 0x04;
11007 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11008 set_mu_type |= 0x05; // set bit 0, 2
11009 }
11010
11011 params.name = "hemu_onoff";
11012 sprintf(buf, "%u", set_mu_type);
11013 params.value = buf;
11014 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11015 wifi_hostapdWrite(config_file, &params, 1);
11016 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11017
11018 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11019 return RETURN_OK;
11020}
11021
11022INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11023{
11024 struct params params={0};
11025 char config_file[64] = {0};
11026 char buf[64] = {0};
11027 unsigned int get_mu_type = 0;
11028
11029 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11030
11031 if (mu_type == NULL)
11032 return RETURN_ERR;
11033
11034 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11035 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11036 get_mu_type = strtol(buf, NULL, 10);
11037
11038 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11039 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11040 else if (get_mu_type & 0x04)
11041 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11042 else if (get_mu_type & 0x01)
11043 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11044 else
11045 *mu_type = WIFI_DL_MU_TYPE_NONE;
11046
11047 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11048 return RETURN_OK;
11049}
11050
11051INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11052{
11053 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11054 struct params params={0};
11055 char config_file[64] = {0};
11056 char buf[64] = {0};
11057 unsigned int set_mu_type = 0;
11058 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11059
11060 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11061 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11062
11063 if (strlen(buf) > 0)
11064 set_mu_type = strtol(buf, NULL, 10);
11065
11066 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11067 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11068 set_mu_type &= ~0x0a;
11069 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11070 set_mu_type |= 0x02;
11071 set_mu_type &= ~0x08;
11072 }
11073
11074 params.name = "hemu_onoff";
11075 sprintf(buf, "%u", set_mu_type);
11076 params.value = buf;
11077 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11078 wifi_hostapdWrite(config_file, &params, 1);
11079 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11080
11081 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11082 return RETURN_OK;
11083}
11084
11085INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11086{
11087 struct params params={0};
11088 char config_file[64] = {0};
11089 char buf[64] = {0};
11090 unsigned int get_mu_type = 0;
11091
11092 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11093
11094 if (mu_type == NULL)
11095 return RETURN_ERR;
11096
11097 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11098 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11099
11100 get_mu_type = strtol(buf, NULL, 10);
11101 if (get_mu_type & 0x02)
11102 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11103 else
11104 *mu_type = WIFI_DL_MU_TYPE_NONE;
11105
11106 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11107 return RETURN_OK;
11108}
11109
11110
11111INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11112{
11113 char cmd[128] = {0};
11114 char buf[256] = {0};
11115 char config_file[64] = {0};
11116 char GI[8] = {0};
11117 int mode_map = 0;
11118 FILE *f = NULL;
11119 wifi_band band = band_invalid;
11120
11121 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11122
11123 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
11124 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11125 return RETURN_ERR;
11126 }
11127
11128 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
11129 band = wifi_index_to_band(radio_index);
11130
11131 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11132 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
11133 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
11134 _syscmd(cmd, buf, sizeof(buf));
11135 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11136 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11137 if (strstr(buf, "[SHORT-GI-") == NULL) {
11138 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
11139 _syscmd(cmd, buf, sizeof(buf));
11140 }
11141 if (band == band_5) {
11142 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11143 if (strstr(buf, "[SHORT-GI-") == NULL) {
11144 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
11145 _syscmd(cmd, buf, sizeof(buf));
11146 }
11147 }
11148 }
11149 wifi_reloadAp(radio_index);
11150
11151 if (guard_interval == wifi_guard_interval_400)
11152 strcpy(GI, "0.4");
11153 else if (guard_interval == wifi_guard_interval_800)
11154 strcpy(GI, "0.8");
11155 else if (guard_interval == wifi_guard_interval_1600)
11156 strcpy(GI, "1.6");
11157 else if (guard_interval == wifi_guard_interval_3200)
11158 strcpy(GI, "3.2");
11159 else if (guard_interval == wifi_guard_interval_auto)
11160 strcpy(GI, "auto");
11161 // Record GI for get GI function
11162 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11163 f = fopen(buf, "w");
11164 if (f == NULL)
11165 return RETURN_ERR;
11166 fprintf(f, "%s", GI);
11167 fclose(f);
11168 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11169 return RETURN_OK;
11170}
11171
11172INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11173{
11174 char buf[32] = {0};
11175 char cmd[64] = {0};
11176
11177 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11178
11179 if (guard_interval == NULL)
11180 return RETURN_ERR;
11181
11182 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11183 _syscmd(cmd, buf, sizeof(buf));
11184
11185 if (strncmp(buf, "0.4", 3) == 0)
11186 *guard_interval = wifi_guard_interval_400;
11187 else if (strncmp(buf, "0.8", 3) == 0)
11188 *guard_interval = wifi_guard_interval_800;
11189 else if (strncmp(buf, "1.6", 3) == 0)
11190 *guard_interval = wifi_guard_interval_1600;
11191 else if (strncmp(buf, "3.2", 3) == 0)
11192 *guard_interval = wifi_guard_interval_3200;
11193 else
11194 *guard_interval = wifi_guard_interval_auto;
11195
11196 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11197 return RETURN_OK;
11198}
11199
11200INT wifi_setBSSColor(INT radio_index, UCHAR color)
11201{
11202 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11203 struct params params = {0};
11204 char config_file[128] = {0};
11205 char bss_color[4] ={0};
11206
11207 params.name = "he_bss_color";
11208 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11209 params.value = bss_color;
11210 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11211 wifi_hostapdWrite(config_file, &params, 1);
11212 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11213
11214 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11215 return RETURN_OK;
11216}
11217
11218INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11219{
11220 char config_file[128] = {0};
11221 char buf[64] = {0};
11222 char temp_output[128] = {'\0'};
11223
11224 wifi_dbg_printf("\nFunc=%s\n", __func__);
11225 if (NULL == color)
11226 return RETURN_ERR;
11227
11228 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11229 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11230
11231 if(strlen(buf) > 0) {
11232 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11233 } else {
11234 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11235 }
11236
11237 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11238 wifi_dbg_printf("\noutput_string=%s\n", color);
11239
11240 return RETURN_OK;
11241}
11242
11243/* multi-psk support */
11244INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11245{
11246 char cmd[256];
11247 char interface_name[16] = {0};
11248
11249 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11250 return RETURN_ERR;
11251
11252 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11253 interface_name,
11254 mac[0],
11255 mac[1],
11256 mac[2],
11257 mac[3],
11258 mac[4],
11259 mac[5]
11260 );
11261 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11262 _syscmd(cmd, key->wifi_keyId, 64);
11263
11264
11265 return RETURN_OK;
11266}
11267
11268INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11269{
11270 char interface_name[16] = {0};
11271 FILE *fd = NULL;
11272 char fname[100];
11273 char cmd[128] = {0};
11274 char out[64] = {0};
11275 wifi_key_multi_psk_t * key = NULL;
11276 if(keysNumber < 0)
11277 return RETURN_ERR;
11278
11279 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11280 fd = fopen(fname, "w");
11281 if (!fd) {
11282 return RETURN_ERR;
11283 }
11284 key= (wifi_key_multi_psk_t *) keys;
11285 for(int i=0; i<keysNumber; ++i, key++) {
11286 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11287 }
11288 fclose(fd);
11289
11290 //reload file
11291 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11292 return RETURN_ERR;
11293 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
11294 _syscmd(cmd, out, 64);
11295 return RETURN_OK;
11296}
11297
11298INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11299{
11300 FILE *fd = NULL;
11301 char fname[100];
11302 char * line = NULL;
11303 char * pos = NULL;
11304 size_t len = 0;
11305 ssize_t read = 0;
11306 INT ret = RETURN_OK;
11307 wifi_key_multi_psk_t *keys_it = NULL;
11308
11309 if (keysNumber < 1) {
11310 return RETURN_ERR;
11311 }
11312
11313 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11314 fd = fopen(fname, "r");
11315 if (!fd) {
11316 return RETURN_ERR;
11317 }
11318
11319 if (keys == NULL) {
11320 ret = RETURN_ERR;
11321 goto close;
11322 }
11323
11324 keys_it = keys;
11325 while ((read = getline(&line, &len, fd)) != -1) {
11326 //Strip trailing new line if present
11327 if (read > 0 && line[read-1] == '\n') {
11328 line[read-1] = '\0';
11329 }
11330
11331 if(strcmp(line,"keyid=")) {
11332 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11333 if (!(pos = index(line, ' '))) {
11334 ret = RETURN_ERR;
11335 goto close;
11336 }
11337 pos++;
11338 //Here should be 00:00:00:00:00:00
11339 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11340 printf("Not supported MAC: %s\n", pos);
11341 }
11342 if (!(pos = index(pos, ' '))) {
11343 ret = RETURN_ERR;
11344 goto close;
11345 }
11346 pos++;
11347
11348 //The rest is PSK
11349 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11350 keys_it++;
11351
11352 if(--keysNumber <= 0)
11353 break;
11354 }
11355 }
11356
11357close:
11358 free(line);
11359 fclose(fd);
11360 return ret;
11361}
11362/* end of multi-psk support */
11363
11364INT wifi_setNeighborReports(UINT apIndex,
11365 UINT numNeighborReports,
11366 wifi_NeighborReport_t *neighborReports)
11367{
11368 char cmd[256] = { 0 };
11369 char hex_bssid[13] = { 0 };
11370 char bssid[18] = { 0 };
11371 char nr[256] = { 0 };
11372 char ssid[256];
11373 char hex_ssid[256];
11374 char interface_name[16] = {0};
11375 INT ret;
11376
11377 /*rmeove all neighbors*/
11378 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
11379 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11380 return RETURN_ERR;
11381 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);
11382 system(cmd);
11383
11384 for(unsigned int i = 0; i < numNeighborReports; i++)
11385 {
11386 memset(ssid, 0, sizeof(ssid));
11387 ret = wifi_getSSIDName(apIndex, ssid);
11388 if (ret != RETURN_OK)
11389 return RETURN_ERR;
11390
11391 memset(hex_ssid, 0, sizeof(hex_ssid));
11392 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11393 sprintf(hex_ssid + k,"%02x", ssid[j]);
11394
11395 snprintf(hex_bssid, sizeof(hex_bssid),
11396 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11397 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11398 snprintf(bssid, sizeof(bssid),
11399 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11400 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11401
11402 snprintf(nr, sizeof(nr),
11403 "%s" // bssid
11404 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11405 "%02hhx" // operclass
11406 "%02hhx" // channel
11407 "%02hhx", // phy_mode
11408 hex_bssid,
11409 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11410 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11411 neighborReports[i].opClass,
11412 neighborReports[i].channel,
11413 neighborReports[i].phyTable);
11414
11415 snprintf(cmd, sizeof(cmd),
11416 "hostapd_cli set_neighbor "
11417 "%s " // bssid
11418 "ssid=%s " // ssid
11419 "nr=%s " // nr
11420 "-i %s",
11421 bssid,hex_ssid,nr, interface_name);
11422
11423 if (WEXITSTATUS(system(cmd)) != 0)
11424 {
11425 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11426 }
11427 }
11428
11429 return RETURN_OK;
11430}
11431
11432INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11433{
11434 return RETURN_OK;
11435}
11436
11437#ifdef _WIFI_HAL_TEST_
11438int main(int argc,char **argv)
11439{
11440 int index;
11441 INT ret=0;
11442 char buf[1024]="";
11443
11444 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11445 if(argc<3)
11446 {
11447 if(argc==2)
11448 {
11449 if(!strcmp(argv[1], "init"))
11450 return wifi_init();
11451 if(!strcmp(argv[1], "reset"))
11452 return wifi_reset();
11453 if(!strcmp(argv[1], "wifi_getHalVersion"))
11454 {
11455 char buffer[64];
11456 if(wifi_getHalVersion(buffer)==RETURN_OK)
11457 printf("Version: %s\n", buffer);
11458 else
11459 printf("Error in wifi_getHalVersion\n");
11460 return RETURN_OK;
11461 }
11462 }
11463 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11464 exit(-1);
11465 }
11466
11467 index = atoi(argv[2]);
11468 if(strstr(argv[1], "wifi_getApName")!=NULL)
11469 {
11470 wifi_getApName(index,buf);
11471 printf("Ap name is %s \n",buf);
11472 return 0;
11473 }
11474 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11475 {
11476 BOOL b = FALSE;
11477 BOOL *output_bool = &b;
11478 wifi_getRadioAutoChannelEnable(index,output_bool);
11479 printf("Channel enabled = %d \n",b);
11480 return 0;
11481 }
11482 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11483 {
11484 wifi_getApWpaEncryptionMode(index,buf);
11485 printf("encryption enabled = %s\n",buf);
11486 return 0;
11487 }
11488 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11489 {
11490 BOOL b = FALSE;
11491 BOOL *output_bool = &b;
11492 wifi_getApSsidAdvertisementEnable(index,output_bool);
11493 printf("advertisment enabled = %d\n",b);
11494 return 0;
11495 }
11496 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11497 {
11498 if(argc <= 3 )
11499 {
11500 printf("Insufficient arguments \n");
11501 exit(-1);
11502 }
11503
11504 char sta[20] = {'\0'};
11505 ULLONG handle= 0;
11506 strcpy(sta,argv[3]);
11507 mac_address_t st;
11508 mac_addr_aton(st,sta);
11509
11510 wifi_associated_dev_tid_stats_t tid_stats;
11511 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11512 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11513 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);
11514 }
11515
11516 if(strstr(argv[1], "getApEnable")!=NULL) {
11517 BOOL enable;
11518 ret=wifi_getApEnable(index, &enable);
11519 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11520 }
11521 else if(strstr(argv[1], "setApEnable")!=NULL) {
11522 BOOL enable = atoi(argv[3]);
11523 ret=wifi_setApEnable(index, enable);
11524 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11525 }
11526 else if(strstr(argv[1], "getApStatus")!=NULL) {
11527 char status[64];
11528 ret=wifi_getApStatus(index, status);
11529 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11530 }
11531 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11532 {
11533 wifi_getSSIDNameStatus(index,buf);
11534 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11535 return 0;
11536 }
11537 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11538 wifi_ssidTrafficStats2_t stats={0};
11539 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11540 printf("%s %d: returns %d\n", argv[1], index, ret);
11541 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11542 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11543 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11544 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11545 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11546 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11547 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11548 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11549 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11550 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11551 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11552 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11553 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11554 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11555 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11556 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11557 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11558 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11559 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11560 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11561 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11562 }
11563 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11564 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11565 UINT array_size=0;
11566 UINT i=0;
11567 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11568 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11569 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11570 printf(" neighbor %d:\n", i);
11571 printf(" ap_SSID =%s\n", pt->ap_SSID);
11572 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11573 printf(" ap_Mode =%s\n", pt->ap_Mode);
11574 printf(" ap_Channel =%d\n", pt->ap_Channel);
11575 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11576 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11577 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11578 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11579 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11580 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11581 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11582 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11583 printf(" ap_Noise =%d\n", pt->ap_Noise);
11584 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11585 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11586 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11587 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11588 }
11589 if(neighbor_ap_array)
11590 free(neighbor_ap_array); //make sure to free the list
11591 }
11592 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11593 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11594 UINT array_size=0;
11595 UINT i=0;
11596 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11597 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11598 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11599 printf(" associated_dev %d:\n", i);
11600 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11601 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11602 printf(" cli_SNR =%d\n", pt->cli_SNR);
11603 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11604 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11605 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11606 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11607 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11608 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11609 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11610 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11611 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11612 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11613 }
11614 if(associated_dev_array)
11615 free(associated_dev_array); //make sure to free the list
11616 }
11617
11618 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11619 {
11620#define MAX_ARRAY_SIZE 64
11621 int i, array_size;
11622 char *p, *ch_str;
11623 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11624
11625 if(argc != 5)
11626 {
11627 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11628 exit(-1);
11629 }
11630 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11631
11632 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11633 {
11634 strtok_r(ch_str, ",", &p);
11635 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11636 }
11637 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11638 if(!array_size)
11639 array_size=1;//Need to print current channel statistics
11640 for(i=0; i<array_size; i++)
11641 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11642 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11643 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11644 input_output_channelStats_array[i].ch_number,\
11645 input_output_channelStats_array[i].ch_noise,\
11646 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11647 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11648 input_output_channelStats_array[i].ch_utilization_busy,\
11649 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11650 input_output_channelStats_array[i].ch_utilization_total);
11651 }
11652
11653 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11654 {
11655 if(argc <= 3 )
11656 {
11657 printf("Insufficient arguments \n");
11658 exit(-1);
11659 }
11660 char mac_addr[20] = {'\0'};
11661 wifi_device_t output_struct;
11662 int dev_index = atoi(argv[3]);
11663
11664 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11665 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11666 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);
11667 }
11668
11669 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11670 {
11671 if (argc <= 3)
11672 {
11673 printf("Insufficient arguments\n");
11674 exit(-1);
11675 }
11676 char args[256];
11677 wifi_NeighborReport_t *neighborReports;
11678
11679 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11680 if (!neighborReports)
11681 {
11682 printf("Failed to allocate memory");
11683 exit(-1);
11684 }
11685
11686 for (int i = 3; i < argc; ++i)
11687 {
11688 char *val;
11689 int j = 0;
11690 memset(args, 0, sizeof(args));
11691 strncpy(args, argv[i], sizeof(args));
11692 val = strtok(args, ";");
11693 while (val != NULL)
11694 {
11695 if (j == 0)
11696 {
11697 mac_addr_aton(neighborReports[i - 3].bssid, val);
11698 } else if (j == 1)
11699 {
11700 neighborReports[i - 3].info = strtol(val, NULL, 16);
11701 } else if (j == 2)
11702 {
11703 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11704 } else if (j == 3)
11705 {
11706 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11707 } else if (j == 4)
11708 {
11709 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11710 } else {
11711 printf("Insufficient arguments]n\n");
11712 exit(-1);
11713 }
11714 val = strtok(NULL, ";");
11715 j++;
11716 }
11717 }
11718
11719 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11720 if (ret != RETURN_OK)
11721 {
11722 printf("wifi_setNeighborReports ret = %d", ret);
11723 exit(-1);
11724 }
11725 }
11726 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11727 {
11728 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11729 printf("%s.\n", buf);
11730 else
11731 printf("Error returned\n");
11732 }
11733 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11734 {
11735 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11736 printf("%s.\n", buf);
11737 else
11738 printf("Error returned\n");
11739 }
11740 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11741 {
11742 if (argc <= 2)
11743 {
11744 printf("Insufficient arguments\n");
11745 exit(-1);
11746 }
11747 char buf[64]= {'\0'};
11748 wifi_getRadioOperatingChannelBandwidth(index,buf);
11749 printf("Current bandwidth is %s \n",buf);
11750 return 0;
11751 }
11752 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11753 {
11754 if (argc <= 5)
11755 {
11756 printf("Insufficient arguments\n");
11757 exit(-1);
11758 }
11759 UINT channel = atoi(argv[3]);
11760 UINT width = atoi(argv[4]);
11761 UINT beacon = atoi(argv[5]);
11762 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11763 printf("Result = %d", ret);
11764 }
11765
11766 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11767 return 0;
11768}
11769
11770#endif
11771
11772#ifdef WIFI_HAL_VERSION_3
11773
11774INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11775{
11776 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11777 if (bitMap & WIFI_BITRATE_1MBPS)
11778 strcat(BasicRate, "1,");
11779 if (bitMap & WIFI_BITRATE_2MBPS)
11780 strcat(BasicRate, "2,");
11781 if (bitMap & WIFI_BITRATE_5_5MBPS)
11782 strcat(BasicRate, "5.5,");
11783 if (bitMap & WIFI_BITRATE_6MBPS)
11784 strcat(BasicRate, "6,");
11785 if (bitMap & WIFI_BITRATE_9MBPS)
11786 strcat(BasicRate, "9,");
11787 if (bitMap & WIFI_BITRATE_11MBPS)
11788 strcat(BasicRate, "11,");
11789 if (bitMap & WIFI_BITRATE_12MBPS)
11790 strcat(BasicRate, "12,");
11791 if (bitMap & WIFI_BITRATE_18MBPS)
11792 strcat(BasicRate, "18,");
11793 if (bitMap & WIFI_BITRATE_24MBPS)
11794 strcat(BasicRate, "24,");
11795 if (bitMap & WIFI_BITRATE_36MBPS)
11796 strcat(BasicRate, "36,");
11797 if (bitMap & WIFI_BITRATE_48MBPS)
11798 strcat(BasicRate, "48,");
11799 if (bitMap & WIFI_BITRATE_54MBPS)
11800 strcat(BasicRate, "54,");
11801 if (strlen(BasicRate) != 0) // remove last comma
11802 BasicRate[strlen(BasicRate) - 1] = '\0';
11803 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11804 return RETURN_OK;
11805}
11806
11807INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11808{
11809 UINT BitMap = 0;
11810 char *rate;
11811
11812 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11813 rate = strtok(BasicRatesList, ",");
11814 while(rate != NULL)
11815 {
11816 if (strcmp(rate, "1") == 0)
11817 BitMap |= WIFI_BITRATE_1MBPS;
11818 else if (strcmp(rate, "2") == 0)
11819 BitMap |= WIFI_BITRATE_2MBPS;
11820 else if (strcmp(rate, "5.5") == 0)
11821 BitMap |= WIFI_BITRATE_5_5MBPS;
11822 else if (strcmp(rate, "6") == 0)
11823 BitMap |= WIFI_BITRATE_6MBPS;
11824 else if (strcmp(rate, "9") == 0)
11825 BitMap |= WIFI_BITRATE_9MBPS;
11826 else if (strcmp(rate, "11") == 0)
11827 BitMap |= WIFI_BITRATE_11MBPS;
11828 else if (strcmp(rate, "12") == 0)
11829 BitMap |= WIFI_BITRATE_12MBPS;
11830 else if (strcmp(rate, "18") == 0)
11831 BitMap |= WIFI_BITRATE_18MBPS;
11832 else if (strcmp(rate, "24") == 0)
11833 BitMap |= WIFI_BITRATE_24MBPS;
11834 else if (strcmp(rate, "36") == 0)
11835 BitMap |= WIFI_BITRATE_36MBPS;
11836 else if (strcmp(rate, "48") == 0)
11837 BitMap |= WIFI_BITRATE_48MBPS;
11838 else if (strcmp(rate, "54") == 0)
11839 BitMap |= WIFI_BITRATE_54MBPS;
11840 rate = strtok(NULL, ",");
11841 }
11842 *basicRateBitMap = BitMap;
11843 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11844 return RETURN_OK;
11845}
11846
11847// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
11848INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11849{
11850 char buf[128] = {0};
11851 char cmd[128] = {0};
11852 char config_file[64] = {0};
11853 int bandwidth;
11854 int set_mode = 0;
11855 wifi_radio_operationParam_t current_param;
11856
11857 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11858
11859 multiple_set = TRUE;
11860 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11861 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11862 return RETURN_ERR;
11863 }
11864 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11865 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11866 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11867 return RETURN_ERR;
11868 }
11869 }
11870
11871 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11872 bandwidth = 20;
11873 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11874 bandwidth = 40;
11875 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11876 bandwidth = 80;
11877 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11878 bandwidth = 160;
11879 if (operationParam->autoChannelEnabled){
11880 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11881 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11882 return RETURN_ERR;
11883 }
11884 }else{
11885 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11886 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11887 return RETURN_ERR;
11888 }
11889 }
11890
11891 if (current_param.variant != operationParam->variant) {
11892 // Two different definition bit map, so need to check every bit.
11893 if (operationParam->variant & WIFI_80211_VARIANT_A)
11894 set_mode |= WIFI_MODE_A;
11895 if (operationParam->variant & WIFI_80211_VARIANT_B)
11896 set_mode |= WIFI_MODE_B;
11897 if (operationParam->variant & WIFI_80211_VARIANT_G)
11898 set_mode |= WIFI_MODE_G;
11899 if (operationParam->variant & WIFI_80211_VARIANT_N)
11900 set_mode |= WIFI_MODE_N;
11901 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11902 set_mode |= WIFI_MODE_AC;
11903 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11904 set_mode |= WIFI_MODE_AX;
11905 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11906 memset(buf, 0, sizeof(buf));
11907 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11908 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11909 return RETURN_ERR;
11910 }
11911 }
11912 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11913 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11914 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11915 return RETURN_ERR;
11916 }
11917 }
11918 if (current_param.beaconInterval != operationParam->beaconInterval) {
11919 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11920 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11921 return RETURN_ERR;
11922 }
11923 }
11924 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11925 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11926 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11927 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11928 return RETURN_ERR;
11929 }
11930 }
11931 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11932 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11933 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11934 return RETURN_ERR;
11935 }
11936 }
11937 if (current_param.guardInterval != operationParam->guardInterval) {
11938 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11939 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11940 return RETURN_ERR;
11941 }
11942 }
11943 if (current_param.transmitPower != operationParam->transmitPower) {
11944 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11945 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11946 return RETURN_ERR;
11947 }
11948 }
11949 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11950 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11951 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11952 return RETURN_ERR;
11953 }
11954 }
11955 if (current_param.obssCoex != operationParam->obssCoex) {
11956 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11957 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11958 return RETURN_ERR;
11959 }
11960 }
11961 if (current_param.stbcEnable != operationParam->stbcEnable) {
11962 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11963 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11964 return RETURN_ERR;
11965 }
11966 }
11967 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11968 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11969 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11970 return RETURN_ERR;
11971 }
11972 }
11973
11974 // if enable is true, then restart the radio
11975 wifi_setRadioEnable(index, FALSE);
11976 if (operationParam->enable == TRUE)
11977 wifi_setRadioEnable(index, TRUE);
11978 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11979
11980 return RETURN_OK;
11981}
11982
11983INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11984{
11985 char band[64] = {0};
11986 char buf[256] = {0};
11987 char config_file[64] = {0};
11988 char cmd[128] = {0};
11989 int ret = RETURN_ERR;
11990 int mode = 0;
11991 ULONG channel = 0;
11992 BOOL enabled = FALSE;
11993
11994 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11995 printf("Entering %s index = %d\n", __func__, (int)index);
11996
11997 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11998 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11999 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
12000 {
12001 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
12002 return RETURN_ERR;
12003 }
12004 operationParam->enable = enabled;
12005
12006 memset(band, 0, sizeof(band));
12007 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
12008 {
12009 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
12010 return RETURN_ERR;
12011 }
12012
12013 if (!strcmp(band, "2.4GHz"))
12014 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
12015 else if (!strcmp(band, "5GHz"))
12016 operationParam->band = WIFI_FREQUENCY_5_BAND;
12017 else if (!strcmp(band, "6GHz"))
12018 operationParam->band = WIFI_FREQUENCY_6_BAND;
12019 else
12020 {
12021 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
12022 band);
12023 }
12024
12025 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12026 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12027 operationParam->channel = 0;
12028 operationParam->autoChannelEnabled = TRUE;
12029 } else {
12030 operationParam->channel = strtol(buf, NULL, 10);
12031 operationParam->autoChannelEnabled = FALSE;
12032 }
12033
12034 memset(buf, 0, sizeof(buf));
12035 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12036 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12037 return RETURN_ERR;
12038 }
12039 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12040 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12041 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
12042 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
12043 else
12044 {
12045 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12046 return false;
12047 }
12048
12049 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12050 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12051 return RETURN_ERR;
12052 }
12053 // Two different definition bit map, so need to check every bit.
12054 if (mode & WIFI_MODE_A)
12055 operationParam->variant |= WIFI_80211_VARIANT_A;
12056 if (mode & WIFI_MODE_B)
12057 operationParam->variant |= WIFI_80211_VARIANT_B;
12058 if (mode & WIFI_MODE_G)
12059 operationParam->variant |= WIFI_80211_VARIANT_G;
12060 if (mode & WIFI_MODE_N)
12061 operationParam->variant |= WIFI_80211_VARIANT_N;
12062 if (mode & WIFI_MODE_AC)
12063 operationParam->variant |= WIFI_80211_VARIANT_AC;
12064 if (mode & WIFI_MODE_AX)
12065 operationParam->variant |= WIFI_80211_VARIANT_AX;
12066 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12067 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12068 return RETURN_ERR;
12069 }
12070 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12071 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12072 return RETURN_ERR;
12073 }
12074 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12075 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12076 return RETURN_ERR;
12077 }
12078
12079 memset(buf, 0, sizeof(buf));
12080 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12081 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12082 return RETURN_ERR;
12083 }
12084 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12085
12086 memset(buf, 0, sizeof(buf));
12087 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12088 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12089 return RETURN_ERR;
12090 }
12091 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12092
12093 memset(buf, 0, sizeof(buf));
12094 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12095 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12096
12097 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12098 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12099 return RETURN_ERR;
12100 }
12101 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12102 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12103 return RETURN_ERR;
12104 }
12105
12106 memset(buf, 0, sizeof(buf));
12107 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12108 if (strcmp(buf, "-1") == 0) {
12109 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12110 operationParam->ctsProtection = FALSE;
12111 } else {
12112 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12113 operationParam->ctsProtection = TRUE;
12114 }
12115
12116 memset(buf, 0, sizeof(buf));
12117 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12118 if (strcmp(buf, "0") == 0)
12119 operationParam->obssCoex = FALSE;
12120 else
12121 operationParam->obssCoex = TRUE;
12122
12123 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12124 _syscmd(cmd, buf, sizeof(buf));
12125 if (strlen(buf) != 0)
12126 operationParam->stbcEnable = TRUE;
12127 else
12128 operationParam->stbcEnable = FALSE;
12129
12130 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12131 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12132 return RETURN_ERR;
12133 }
12134
12135 // Below value is hardcoded
12136
12137 operationParam->numSecondaryChannels = 0;
12138 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12139 operationParam->channelSecondary[i] = 0;
12140 }
12141 operationParam->csa_beacon_count = 15;
12142 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
12143
12144 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12145 return RETURN_OK;
12146}
12147
12148static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12149{
12150 int max_radio_num = 0;
12151
12152 wifi_getMaxRadioNumber(&max_radio_num);
12153 if (radioIndex >= max_radio_num) {
12154 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12155 return RETURN_ERR;
12156 }
12157
12158 return (arrayIndex * max_radio_num) + radioIndex;
12159}
12160
12161wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12162 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12163 return WIFI_BITRATE_1MBPS;
12164 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12165 return WIFI_BITRATE_2MBPS;
12166 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12167 return WIFI_BITRATE_5_5MBPS;
12168 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12169 return WIFI_BITRATE_6MBPS;
12170 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12171 return WIFI_BITRATE_9MBPS;
12172 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12173 return WIFI_BITRATE_11MBPS;
12174 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12175 return WIFI_BITRATE_12MBPS;
12176 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12177 return WIFI_BITRATE_18MBPS;
12178 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12179 return WIFI_BITRATE_24MBPS;
12180 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12181 return WIFI_BITRATE_36MBPS;
12182 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12183 return WIFI_BITRATE_48MBPS;
12184 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12185 return WIFI_BITRATE_54MBPS;
12186 return WIFI_BITRATE_DEFAULT;
12187}
12188
12189INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12190{
12191 if (beacon == WIFI_BITRATE_1MBPS)
12192 strcpy(beacon_str, "1Mbps");
12193 else if (beacon == WIFI_BITRATE_2MBPS)
12194 strcpy(beacon_str, "2Mbps");
12195 else if (beacon == WIFI_BITRATE_5_5MBPS)
12196 strcpy(beacon_str, "5.5Mbps");
12197 else if (beacon == WIFI_BITRATE_6MBPS)
12198 strcpy(beacon_str, "6Mbps");
12199 else if (beacon == WIFI_BITRATE_9MBPS)
12200 strcpy(beacon_str, "9Mbps");
12201 else if (beacon == WIFI_BITRATE_11MBPS)
12202 strcpy(beacon_str, "11Mbps");
12203 else if (beacon == WIFI_BITRATE_12MBPS)
12204 strcpy(beacon_str, "12Mbps");
12205 else if (beacon == WIFI_BITRATE_18MBPS)
12206 strcpy(beacon_str, "18Mbps");
12207 else if (beacon == WIFI_BITRATE_24MBPS)
12208 strcpy(beacon_str, "24Mbps");
12209 else if (beacon == WIFI_BITRATE_36MBPS)
12210 strcpy(beacon_str, "36Mbps");
12211 else if (beacon == WIFI_BITRATE_48MBPS)
12212 strcpy(beacon_str, "48Mbps");
12213 else if (beacon == WIFI_BITRATE_54MBPS)
12214 strcpy(beacon_str, "54Mbps");
12215 return RETURN_OK;
12216}
12217
12218INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12219{
12220 INT mode = 0;
12221 INT ret = -1;
12222 INT output = 0;
12223 int i = 0;
12224 int vap_index = 0;
12225 BOOL enabled = FALSE;
12226 char buf[256] = {0};
12227 wifi_vap_security_t security = {0};
12228 map->num_vaps = 5; // Hardcoded
12229
12230 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12231 printf("Entering %s index = %d\n", __func__, (int)index);
12232
12233 for (i = 0; i < 5; i++)
12234 {
12235 map->vap_array[i].radio_index = index;
12236
12237 vap_index = array_index_to_vap_index(index, i);
12238 if (vap_index < 0)
12239 return RETURN_ERR;
12240
12241 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
12242
12243 map->vap_array[i].vap_index = vap_index;
12244
12245 memset(buf, 0, sizeof(buf));
12246 ret = wifi_getApName(vap_index, buf);
12247 if (ret != RETURN_OK) {
12248 printf("%s: wifi_getApName return error\n", __func__);
12249 return RETURN_ERR;
12250 }
12251 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12252
12253 memset(buf, 0, sizeof(buf));
12254 ret = wifi_getSSIDName(vap_index, buf);
12255 if (ret != RETURN_OK) {
12256 printf("%s: wifi_getSSIDName return error\n", __func__);
12257 return RETURN_ERR;
12258 }
12259 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
12260
12261 ret = wifi_getSSIDEnable(vap_index, &enabled);
12262 if (ret != RETURN_OK) {
12263 printf("%s: wifi_getSSIDEnable return error\n", __func__);
12264 return RETURN_ERR;
12265 }
12266 map->vap_array[i].u.bss_info.enabled = enabled;
12267
12268 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12269 if (ret != RETURN_OK) {
12270 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12271 return RETURN_ERR;
12272 }
12273 map->vap_array[i].u.bss_info.showSsid = enabled;
12274
12275 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12276 if (ret != RETURN_OK) {
12277 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12278 return RETURN_ERR;
12279 }
12280 map->vap_array[i].u.bss_info.isolation = enabled;
12281
12282 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12283 if (ret != RETURN_OK) {
12284 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12285 return RETURN_ERR;
12286 }
12287 map->vap_array[i].u.bss_info.bssMaxSta = output;
12288
12289 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12290 if (ret != RETURN_OK) {
12291 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12292 return RETURN_ERR;
12293 }
12294 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
12295
12296 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12297 if (ret != RETURN_OK) {
12298 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12299 return RETURN_ERR;
12300 }
12301 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
12302
12303 ret = wifi_getApSecurity(vap_index, &security);
12304 if (ret != RETURN_OK) {
12305 printf("%s: wifi_getApSecurity return error\n", __func__);
12306 return RETURN_ERR;
12307 }
12308 map->vap_array[i].u.bss_info.security = security;
12309
12310 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12311 if (ret != RETURN_OK) {
12312 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12313 return RETURN_ERR;
12314 }
12315 if (mode == 0)
12316 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12317 else
12318 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12319 if (mode == 1)
12320 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12321 else if (mode == 2)
12322 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
12323
12324 ret = wifi_getApWmmEnable(vap_index, &enabled);
12325 if (ret != RETURN_OK) {
12326 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12327 return RETURN_ERR;
12328 }
12329 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
12330
12331 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12332 if (ret != RETURN_OK) {
12333 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
12334 return RETURN_ERR;
12335 }
12336 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
12337
12338 memset(buf, 0, sizeof(buf));
12339 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
12340 if (ret != RETURN_OK) {
12341 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12342 return RETURN_ERR;
12343 }
12344 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
12345
12346 memset(buf, 0, sizeof(buf));
12347 ret = wifi_getBaseBSSID(vap_index, buf);
12348 if (ret != RETURN_OK) {
12349 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12350 return RETURN_ERR;
12351 }
12352 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12353 &map->vap_array[i].u.bss_info.bssid[0],
12354 &map->vap_array[i].u.bss_info.bssid[1],
12355 &map->vap_array[i].u.bss_info.bssid[2],
12356 &map->vap_array[i].u.bss_info.bssid[3],
12357 &map->vap_array[i].u.bss_info.bssid[4],
12358 &map->vap_array[i].u.bss_info.bssid[5]);
12359 // 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]);
12360
12361 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12362 if (ret != RETURN_OK) {
12363 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12364 return RETURN_ERR;
12365 }
12366 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
12367
12368 // TODO: wps, noack
12369 }
12370 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12371 return RETURN_OK;
12372}
12373
12374void checkVapStatus(int apIndex, bool *enable)
12375{
12376 char if_name[16] = {0};
12377 char cmd[128] = {0};
12378 char buf[128] = {0};
12379
12380 *enable = FALSE;
12381 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12382 return;
12383
12384 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12385 _syscmd(cmd, buf, sizeof(buf));
12386 if (strlen(buf) > 0)
12387 *enable = TRUE;
12388 return;
12389}
12390
12391static int prepareInterface(UINT apIndex, char *new_interface)
12392{
12393 char cur_interface[16] = {0};
12394 char config_file[128] = {0};
12395 char cmd[128] = {0};
12396 char buf[16] = {0};
12397 int max_radio_num = 0;
12398 int radioIndex = -1;
12399 int phyIndex = -1;
12400
12401 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12402 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12403
12404 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12405 wifi_getMaxRadioNumber(&max_radio_num);
12406 radioIndex = apIndex % max_radio_num;
12407 phyIndex = radio_index_to_phy(radioIndex);
12408 // disable and del old interface, then add new interface
12409 wifi_setApEnable(apIndex, FALSE);
12410 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
12411 _syscmd(cmd, buf, sizeof(buf));
12412 }
12413 // update the vap status file
12414 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12415 _syscmd(cmd, buf, sizeof(buf));
12416 return RETURN_OK;
12417}
12418
12419INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12420{
12421 char interface_name[16] = {0};
12422 unsigned int i;
12423 wifi_vap_info_t *vap_info = NULL;
12424 int acl_mode;
12425 int ret = 0;
12426 char *sec_str = NULL;
12427 char buf[256] = {0};
12428 char cmd[128] = {0};
12429 char config_file[64] = {0};
12430 char bssid[32] = {0};
12431 char psk_file[64] = {0};
12432 bool enable = FALSE;
12433
12434 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12435 printf("Entering %s index = %d\n", __func__, (int)index);
12436 for (i = 0; i < map->num_vaps; i++)
12437 {
12438 multiple_set = TRUE;
12439 vap_info = &map->vap_array[i];
12440
12441 // Check vap status file to enable multiple ap if the system boot.
12442 checkVapStatus(vap_info->vap_index, &enable);
12443 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
12444 continue;
12445
12446 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12447
12448 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12449 enable = FALSE;
12450
12451 // multi-ap first up need to copy current radio config
12452 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
12453 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12454 _syscmd(cmd, buf, sizeof(buf));
12455 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12456 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12457 } else {
12458 // Check whether the interface name is valid or this ap change it.
12459 int apIndex = -1;
12460 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12461 if (apIndex != -1 && apIndex != vap_info->vap_index)
12462 continue;
12463 prepareInterface(vap_info->vap_index, vap_info->vap_name);
12464 }
12465
12466 struct params params[3];
12467 params[0].name = "interface";
12468 params[0].value = vap_info->vap_name;
12469 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12470 params[1].name = "bssid";
12471 params[1].value = bssid;
12472 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
12473 params[2].name = "wpa_psk_file";
12474 params[2].value = psk_file;
12475
12476 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12477 wifi_hostapdWrite(config_file, params, 3);
12478
12479 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12480 _syscmd(cmd, buf, sizeof(buf));
12481
12482 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12483 if (ret != RETURN_OK) {
12484 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12485 return RETURN_ERR;
12486 }
12487
12488 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12489 if (ret != RETURN_OK) {
12490 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12491 return RETURN_ERR;
12492 }
12493
12494 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12495 if (ret != RETURN_OK) {
12496 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12497 return RETURN_ERR;
12498 }
12499
12500 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12501 if (ret != RETURN_OK) {
12502 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12503 return RETURN_ERR;
12504 }
12505
12506 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12507 if (ret != RETURN_OK) {
12508 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12509 return RETURN_ERR;
12510 }
12511
12512 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12513 if (ret != RETURN_OK) {
12514 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12515 return RETURN_ERR;
12516 }
12517
12518 if (vap_info->u.bss_info.mac_filter_enable == false){
12519 acl_mode = 0;
12520 }else {
12521 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
12522 acl_mode = 2;
12523 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12524 _syscmd(cmd, buf, sizeof(buf));
12525 }else{
12526 acl_mode = 1;
12527 }
12528 }
12529
12530 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12531 if (ret != RETURN_OK) {
12532 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12533 return RETURN_ERR;
12534 }
12535
12536 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12537 if (ret != RETURN_OK) {
12538 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12539 return RETURN_ERR;
12540 }
12541
12542 memset(buf, 0, sizeof(buf));
12543 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12544 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12545 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12546 if (ret != RETURN_OK) {
12547 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12548 return RETURN_ERR;
12549 }
12550
12551 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12552 if (ret != RETURN_OK) {
12553 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12554 return RETURN_ERR;
12555 }
12556
12557 wifi_setApEnable(vap_info->vap_index, TRUE);
12558 multiple_set = FALSE;
12559
12560 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
12561 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12562 if (ret != RETURN_OK) {
12563 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12564 return RETURN_ERR;
12565 }
12566
12567 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12568 if (ret != RETURN_OK) {
12569 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12570 return RETURN_ERR;
12571 }
12572
12573 // TODO mgmtPowerControl, interworking, wps
12574 }
12575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12576 return RETURN_OK;
12577}
12578
12579int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12580{
12581 char *token, *next;
12582 const char s[2] = ",";
12583 int count =0;
12584
12585 /* get the first token */
12586 token = strtok_r(pchannels, s, &next);
12587
12588 /* walk through other tokens */
12589 while( token != NULL && count < MAX_CHANNELS) {
12590 chlistptr->channels_list[count++] = atoi(token);
12591 token = strtok_r(NULL, s, &next);
12592 }
12593
12594 return count;
12595}
12596
12597static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12598{
12599 INT status;
12600 wifi_channels_list_t *chlistp;
12601 CHAR output_string[64];
12602 CHAR pchannels[128];
12603 CHAR interface_name[16] = {0};
12604 wifi_band band;
12605
12606 if(rcap == NULL)
12607 {
12608 return RETURN_ERR;
12609 }
12610
12611 rcap->numSupportedFreqBand = 1;
12612 band = wifi_index_to_band(radioIndex);
12613
12614 if (band == band_2_4)
12615 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12616 else if (band == band_5)
12617 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12618 else if (band == band_6)
12619 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
12620
12621 chlistp = &(rcap->channel_list[0]);
12622 memset(pchannels, 0, sizeof(pchannels));
12623
12624 /* possible number of radio channels */
12625 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12626 {
12627 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12628 }
12629 /* Number of channels and list*/
12630 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12631
12632 /* autoChannelSupported */
12633 /* always ON with wifi_getRadioAutoChannelSupported */
12634 rcap->autoChannelSupported = TRUE;
12635
12636 /* DCSSupported */
12637 /* always ON with wifi_getRadioDCSSupported */
12638 rcap->DCSSupported = TRUE;
12639
12640 /* zeroDFSSupported - TBD */
12641 rcap->zeroDFSSupported = FALSE;
12642
12643 /* Supported Country List*/
12644 memset(output_string, 0, sizeof(output_string));
12645 status = wifi_getRadioCountryCode(radioIndex, output_string);
12646 if( status != 0 ) {
12647 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12648 return RETURN_ERR;
12649 } else {
12650 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12651 }
12652 if(!strcmp(output_string,"US")){
12653 rcap->countrySupported[0] = wifi_countrycode_US;
12654 rcap->countrySupported[1] = wifi_countrycode_CA;
12655 } else if (!strcmp(output_string,"CA")) {
12656 rcap->countrySupported[0] = wifi_countrycode_CA;
12657 rcap->countrySupported[1] = wifi_countrycode_US;
12658 } else {
12659 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12660 }
12661
12662 rcap->numcountrySupported = 2;
12663
12664 /* csi */
12665 rcap->csi.maxDevices = 8;
12666 rcap->csi.soudingFrameSupported = TRUE;
12667
12668 wifi_GetInterfaceName(radioIndex, interface_name);
12669 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
12670
12671 /* channelWidth - all supported bandwidths */
12672 int i=0;
12673 rcap->channelWidth[i] = 0;
12674 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12675 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12676 WIFI_CHANNELBANDWIDTH_40MHZ);
12677
12678 }
12679 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
12680 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12681 WIFI_CHANNELBANDWIDTH_40MHZ |
12682 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12683 }
12684
12685
12686 /* mode - all supported variants */
12687 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12688 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
12689 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
12690 }
12691 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
12692 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12693 }
12694 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12695 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
12696 }
12697 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12698 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12699
12700 /* supportedBitRate - all supported bitrates */
12701 rcap->supportedBitRate[i] = 0;
12702 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12703 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12704 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12705 }
12706 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
12707 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12708 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12709 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12710 }
12711
12712
12713 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12714 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12715 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12716 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12717 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12718 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12719 rcap->cipherSupported = 0;
12720 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12721 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12722
12723 return RETURN_OK;
12724}
12725
12726INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12727{
12728 INT status = 0, radioIndex = 0;
12729 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
12730 int iter = 0;
12731 unsigned int j = 0;
12732 int max_num_radios;
12733 wifi_interface_name_idex_map_t *iface_info = NULL;
12734
12735 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12736
12737 memset(cap, 0, sizeof(wifi_hal_capability_t));
12738
12739 /* version */
12740 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12741 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12742
12743 /* number of radios platform property */
12744 wifi_getMaxRadioNumber(&max_num_radios);
12745 cap->wifi_prop.numRadios = max_num_radios;
12746
12747 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12748 {
12749 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12750 if (status != 0) {
12751 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12752 return RETURN_ERR;
12753 }
12754
12755 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12756 {
12757 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
12758 {
12759 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12760 return RETURN_ERR;
12761 }
12762 iface_info = &cap->wifi_prop.interface_map[iter];
12763 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12764 iface_info->rdk_radio_index = radioIndex;
12765 memset(output, 0, sizeof(output));
12766 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12767 {
12768 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12769 }
12770 // TODO: bridge name
12771 // TODO: vlan id
12772 // TODO: primary
12773 iface_info->index = array_index_to_vap_index(radioIndex, j);
12774 memset(output, 0, sizeof(output));
12775 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
12776 {
12777 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12778 }
12779 iter++;
12780 }
12781 }
12782
12783 cap->BandSteeringSupported = FALSE;
12784 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12785 return RETURN_OK;
12786}
12787
12788INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12789{
12790 struct params h_config={0};
12791 char config_file[64] = {0};
12792
12793 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12794
12795 h_config.name = "okc";
12796 h_config.value = okc_enable?"1":"0";
12797
12798 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12799 wifi_hostapdWrite(config_file, &h_config, 1);
12800 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12801
12802 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12803 return RETURN_OK;
12804}
12805
12806INT wifi_setSAEMFP(int ap_index, BOOL enable)
12807{
12808 struct params h_config={0};
12809 char config_file[64] = {0};
12810 char buf[128] = {0};
12811
12812 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12813
12814 h_config.name = "sae_require_mfp";
12815 h_config.value = enable?"1":"0";
12816
12817 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12818 wifi_hostapdWrite(config_file, &h_config, 1);
12819 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12820
12821 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12822 return RETURN_OK;
12823}
12824
12825INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12826{
12827 struct params h_config={0};
12828 char config_file[64] = {0};
12829 char buf[128] = {0};
12830
12831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12832
12833 h_config.name = "sae_pwe";
12834 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12835 h_config.value = buf;
12836
12837 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12838 wifi_hostapdWrite(config_file, &h_config, 1);
12839 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12840
12841 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12842 return RETURN_OK;
12843}
12844
12845INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12846{
12847 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12848 struct params h_config={0};
12849 char config_file[64] = {0};
12850
12851 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12852
12853 h_config.name = "wpa_disable_eapol_key_retries";
12854 h_config.value = disable_EAPOL_retries?"1":"0";
12855
12856 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12857 wifi_hostapdWrite(config_file, &h_config, 1);
12858 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12859
12860 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12861 return RETURN_OK;
12862}
12863
12864INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12865{
12866 char buf[128] = {0};
12867 char config_file[128] = {0};
12868 char password[64] = {0};
12869 char mfp[32] = {0};
12870 char wpa_mode[32] = {0};
12871 BOOL okc_enable = FALSE;
12872 BOOL sae_MFP = FALSE;
12873 BOOL disable_EAPOL_retries = TRUE;
12874 int sae_pwe = 0;
12875 struct params params = {0};
12876 wifi_band band = band_invalid;
12877
12878 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12879
12880 multiple_set = TRUE;
12881 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12882 if (security->mode == wifi_security_mode_none) {
12883 strcpy(wpa_mode, "None");
12884 } else if (security->mode == wifi_security_mode_wpa_personal)
12885 strcpy(wpa_mode, "WPA-Personal");
12886 else if (security->mode == wifi_security_mode_wpa2_personal)
12887 strcpy(wpa_mode, "WPA2-Personal");
12888 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12889 strcpy(wpa_mode, "WPA-WPA2-Personal");
12890 else if (security->mode == wifi_security_mode_wpa_enterprise)
12891 strcpy(wpa_mode, "WPA-Enterprise");
12892 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12893 strcpy(wpa_mode, "WPA2-Enterprise");
12894 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12895 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
12896 else if (security->mode == wifi_security_mode_wpa3_personal) {
12897 strcpy(wpa_mode, "WPA3-Personal");
12898 okc_enable = TRUE;
12899 sae_MFP = TRUE;
12900 sae_pwe = 2;
12901 disable_EAPOL_retries = FALSE;
12902 } else if (security->mode == wifi_security_mode_wpa3_transition) {
12903 strcpy(wpa_mode, "WPA3-Personal-Transition");
12904 okc_enable = TRUE;
12905 sae_MFP = TRUE;
12906 sae_pwe = 2;
12907 disable_EAPOL_retries = FALSE;
12908 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
12909 strcpy(wpa_mode, "WPA3-Enterprise");
12910 sae_MFP = TRUE;
12911 sae_pwe = 2;
12912 disable_EAPOL_retries = FALSE;
12913 }
12914
12915 band = wifi_index_to_band(ap_index);
12916 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12917 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12918 return RETURN_ERR;
12919 }
12920
12921 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
12922 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
12923 wifi_setSAEMFP(ap_index, sae_MFP);
12924 wifi_setSAEpwe(ap_index, sae_pwe);
12925 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
12926
12927 if (security->mode != wifi_security_mode_none) {
12928 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12929 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12930 password[63] = '\0';
12931 wifi_setApSecurityKeyPassphrase(ap_index, password);
12932 }
12933 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12934 params.name = "sae_password";
12935 params.value = security->u.key.key;
12936 wifi_hostapdWrite(config_file, &params, 1);
12937 }
12938 }
12939
12940 if (security->mode != wifi_security_mode_none) {
12941 memset(&params, 0, sizeof(params));
12942 params.name = "wpa_pairwise";
12943 if (security->encr == wifi_encryption_tkip)
12944 params.value = "TKIP";
12945 else if (security->encr == wifi_encryption_aes)
12946 params.value = "CCMP";
12947 else if (security->encr == wifi_encryption_aes_tkip)
12948 params.value = "TKIP CCMP";
12949 wifi_hostapdWrite(config_file, &params, 1);
12950 }
12951
12952 if (security->mfp == wifi_mfp_cfg_disabled)
12953 strcpy(mfp, "Disabled");
12954 else if (security->mfp == wifi_mfp_cfg_optional)
12955 strcpy(mfp, "Optional");
12956 else if (security->mfp == wifi_mfp_cfg_required)
12957 strcpy(mfp, "Required");
12958 wifi_setApSecurityMFPConfig(ap_index, mfp);
12959
12960 memset(&params, 0, sizeof(params));
12961 params.name = "transition_disable";
12962 if (security->wpa3_transition_disable == TRUE)
12963 params.value = "0x01";
12964 else
12965 params.value = "0x00";
12966 wifi_hostapdWrite(config_file, &params, 1);
12967
12968 memset(&params, 0, sizeof(params));
12969 params.name = "wpa_group_rekey";
12970 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12971 params.value = buf;
12972 wifi_hostapdWrite(config_file, &params, 1);
12973
12974 memset(&params, 0, sizeof(params));
12975 params.name = "wpa_strict_rekey";
12976 params.value = security->strict_rekey?"1":"0";
12977 wifi_hostapdWrite(config_file, &params, 1);
12978
12979 memset(&params, 0, sizeof(params));
12980 params.name = "wpa_pairwise_update_count";
12981 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12982 params.value = buf;
12983 wifi_hostapdWrite(config_file, &params, 1);
12984
12985 memset(&params, 0, sizeof(params));
12986 params.name = "disable_pmksa_caching";
12987 params.value = security->disable_pmksa_caching?"1":"0";
12988 wifi_hostapdWrite(config_file, &params, 1);
12989
12990 wifi_setApEnable(ap_index, FALSE);
12991 wifi_setApEnable(ap_index, TRUE);
12992
12993 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12994
12995 return RETURN_OK;
12996}
12997
12998INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12999{
13000 char buf[256] = {0};
13001 char config_file[128] = {0};
13002 int disable = 0;
13003 // struct params params = {0};
13004
13005 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13006 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13007 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13008 security->mode = wifi_security_mode_none;
13009 if (strlen(buf) != 0) {
13010 if (!strcmp(buf, "WPA-Personal"))
13011 security->mode = wifi_security_mode_wpa_personal;
13012 else if (!strcmp(buf, "WPA2-Personal"))
13013 security->mode = wifi_security_mode_wpa2_personal;
13014 else if (!strcmp(buf, "WPA-WPA2-Personal"))
13015 security->mode = wifi_security_mode_wpa_wpa2_personal;
13016 else if (!strcmp(buf, "WPA-Enterprise"))
13017 security->mode = wifi_security_mode_wpa_enterprise;
13018 else if (!strcmp(buf, "WPA2-Enterprise"))
13019 security->mode = wifi_security_mode_wpa2_enterprise;
13020 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
13021 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
13022 else if (!strcmp(buf, "WPA3-Personal"))
13023 security->mode = wifi_security_mode_wpa3_personal;
13024 else if (!strcmp(buf, "WPA3-Personal-Transition"))
13025 security->mode = wifi_security_mode_wpa3_transition;
13026 else if (!strcmp(buf, "WPA3-Enterprise"))
13027 security->mode = wifi_security_mode_wpa3_enterprise;
13028 }
13029
13030 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13031 if (security->mode == wifi_security_mode_none)
13032 security->encr = wifi_encryption_none;
13033 else {
13034 if (strcmp(buf, "TKIP") == 0)
13035 security->encr = wifi_encryption_tkip;
13036 else if (strcmp(buf, "CCMP") == 0)
13037 security->encr = wifi_encryption_aes;
13038 else
13039 security->encr = wifi_encryption_aes_tkip;
13040 }
13041
13042 if (security->mode != wifi_encryption_none) {
13043 memset(buf, 0, sizeof(buf));
13044 // wpa3 can use one or both configs as password, so we check sae_password first.
13045 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
13046 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
13047 security->u.key.type = wifi_security_key_type_sae;
13048 } else {
13049 security->u.key.type = wifi_security_key_type_psk;
13050 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13051 }
13052 strncpy(security->u.key.key, buf, sizeof(buf));
13053 security->u.key.key[255] = '\0';
13054 }
13055
13056 memset(buf, 0, sizeof(buf));
13057 wifi_getApSecurityMFPConfig(ap_index, buf);
13058 if (strcmp(buf, "Disabled") == 0)
13059 security->mfp = wifi_mfp_cfg_disabled;
13060 else if (strcmp(buf, "Optional") == 0)
13061 security->mfp = wifi_mfp_cfg_optional;
13062 else if (strcmp(buf, "Required") == 0)
13063 security->mfp = wifi_mfp_cfg_required;
13064
13065 memset(buf, 0, sizeof(buf));
13066 security->wpa3_transition_disable = FALSE;
13067 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13068 disable = strtol(buf, NULL, 16);
13069 if (disable != 0)
13070 security->wpa3_transition_disable = TRUE;
13071
13072 memset(buf, 0, sizeof(buf));
13073 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13074 if (strlen(buf) == 0)
13075 security->rekey_interval = 86400;
13076 else
13077 security->rekey_interval = strtol(buf, NULL, 10);
13078
13079 memset(buf, 0, sizeof(buf));
13080 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13081 if (strlen(buf) == 0)
13082 security->strict_rekey = 1;
13083 else
13084 security->strict_rekey = strtol(buf, NULL, 10);
13085
13086 memset(buf, 0, sizeof(buf));
13087 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13088 if (strlen(buf) == 0)
13089 security->eapol_key_retries = 4;
13090 else
13091 security->eapol_key_retries = strtol(buf, NULL, 10);
13092
13093 memset(buf, 0, sizeof(buf));
13094 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13095 if (strlen(buf) == 0)
13096 security->disable_pmksa_caching = FALSE;
13097 else
13098 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13099
13100 /* TODO
13101 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13102 */
13103 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13104 security->eap_identity_req_timeout = 0;
13105 security->eap_identity_req_retries = 0;
13106 security->eap_req_timeout = 0;
13107 security->eap_req_retries = 0;
13108 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13109 return RETURN_OK;
13110}
13111
13112#endif /* WIFI_HAL_VERSION_3 */
13113
13114#ifdef WIFI_HAL_VERSION_3_PHASE2
13115INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13116{
13117 char interface_name[16] = {0};
13118 char cmd[128] = {0};
13119 char buf[128] = {0};
13120 char *mac_addr = NULL;
13121 BOOL status = FALSE;
13122 size_t len = 0;
13123
13124 if(ap_index > MAX_APS)
13125 return RETURN_ERR;
13126
13127 *output_numDevices = 0;
13128 wifi_getApEnable(ap_index, &status);
13129 if (status == FALSE)
13130 return RETURN_OK;
13131
13132 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13133 return RETURN_ERR;
13134 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
13135 _syscmd(cmd, buf, sizeof(buf));
13136
13137 mac_addr = strtok(buf, "\n");
13138 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13139 *output_numDevices = i + 1;
13140 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13141 addr_ptr = output_deviceMacAddressArray[i];
13142 mac_addr_aton(addr_ptr, mac_addr);
13143 mac_addr = strtok(NULL, "\n");
13144 }
13145
13146 return RETURN_OK;
13147}
13148#else
13149INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13150{
13151 char interface_name[16] = {0};
13152 char cmd[128];
13153 BOOL status = false;
13154
13155 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13156 return RETURN_ERR;
13157
13158 output_buf[0] = '\0';
13159
13160 wifi_getApEnable(ap_index,&status);
13161 if (!status)
13162 return RETURN_OK;
13163
13164 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13165 return RETURN_ERR;
13166 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
13167 _syscmd(cmd, output_buf, output_buf_size);
13168
13169 return RETURN_OK;
13170}
13171#endif
13172
13173INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13174{
13175 char output[16]={'\0'};
13176 char config_file[MAX_BUF_SIZE] = {0};
13177
13178 if (!enable)
13179 return RETURN_ERR;
13180
13181 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13182 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13183
13184 if (strlen(output) == 0)
13185 *enable = FALSE;
13186 else if (strncmp(output, "1", 1) == 0)
13187 *enable = TRUE;
13188 else
13189 *enable = FALSE;
13190
13191 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13192 return RETURN_OK;
13193}
13194
13195INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13196{
13197 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
13198 return RETURN_ERR;
13199 *output_enable=TRUE;
13200 return RETURN_OK;
13201}
13202
13203INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13204{
13205 char cmd[128] = {0};
13206 char buf[128] = {0};
13207 char line[128] = {0};
13208 size_t len = 0;
13209 FILE *f = NULL;
13210 int index = 0;
13211 int exp = 0;
13212 int mantissa = 0;
13213 int duration = 0;
13214 int radio_index = 0;
13215 int max_radio_num = 0;
13216 uint twt_wake_interval = 0;
13217 int phyId = 0;
13218 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13219
13220 wifi_getMaxRadioNumber(&max_radio_num);
13221
13222 radio_index = ap_index % max_radio_num;
13223
13224 phyId = radio_index_to_phy(radio_index);
13225 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
13226 _syscmd(cmd, buf, sizeof(buf));
13227 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13228 if (*numSessionReturned > maxNumberSessions)
13229 *numSessionReturned = maxNumberSessions;
13230 else if (*numSessionReturned < 1) {
13231 *numSessionReturned = 0;
13232 return RETURN_OK;
13233 }
13234
13235 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
13236 if ((f = popen(cmd, "r")) == NULL) {
13237 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13238 return RETURN_ERR;
13239 }
13240
13241 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
13242 while((fgets(line, sizeof(line), f)) != NULL) {
13243 char *tmp = NULL;
13244 strcpy(buf, line);
13245 tmp = strtok(buf, " ");
13246 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13247 tmp = strtok(NULL, " ");
13248 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13249 tmp = strtok(NULL, " ");
13250 if (strstr(tmp, "t")) {
13251 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13252 }
13253 if (strstr(tmp, "a")) {
13254 twtSessions[index].twtParameters.operation.announced = TRUE;
13255 }
13256 tmp = strtok(NULL, " ");
13257 exp = strtol(tmp, NULL, 10);
13258 tmp = strtok(NULL, " ");
13259 mantissa = strtol(tmp, NULL, 10);
13260 tmp = strtok(NULL, " ");
13261 duration = strtol(tmp, NULL, 10);
13262
13263 // only implicit supported
13264 twtSessions[index].twtParameters.operation.implicit = TRUE;
13265 // only individual agreement supported
13266 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13267
13268 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13269 twt_wake_interval = mantissa * (1 << exp);
13270 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
13271 // Overflow handling
13272 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13273 } else {
13274 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13275 }
13276 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13277 index++;
13278 }
13279
13280 pclose(f);
13281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13282 return RETURN_OK;
13283}