现在,再次给出下列需求的完整代码、流程、解释注释:
参考下列代码实现,仿照对应的目录形式,请你给出一个能在样机中打印"hello world"的项目示例:
参考目录形式:
├── Makefile
└── src
├── bcm
│ ├── cs_scan_bcm.c
│ └── cs_scan_bcm.h
├── chansel.c
├── chansel.h
├── cs_log.h
├── cs_scan_api.c
├── cs_scan_api.h
├── cs_util.c
├── cs_util.h
├── Makefile
├── mtk
│ ├── cs_scan_mtk.c
│ └── cs_scan_mtk.h
├── qca
│ ├── cs_scan_qca.c
│ └── cs_scan_qca.h
└── wl_common.h
其中第一层目录下的Makefile如下:
#
# Copyright (c) 2020 Shenzhen TP-LINK Technologies Co.Ltd.
#
#
include $(TOPDIR)/rules.mk
PKG_NAME:=channel-selector
PKG_RELEASE:=1
PKG_VERSION:=1.0
include $(INCLUDE_DIR)/package.mk
TARGET_CFLAGS += -std=gnu99
TARGET_CFLAGS += -I./include/ -I./ipc/
TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/
TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/json-c
TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/libubox
#TARGET_CFLAGS += -DCONFIG_CONF_METHOD=1
TARGET_LDFLAGS += -Wl,--start-group -ldl -Wl,--end-group
TARGET_LDFLAGS += -L$(STAGING_DIR)/usr/lib -lubox -lubus -lblobmsg_json
TARGET_LDFLAGS += -ljson-c
TARGET_LDFLAGS += -L$(STAGING_DIR)/usr/lib
TARGET_LDFLAGS += -L$(STAGING_DIR)/lib
ifeq ($(CONFIG_IPF_PLATFORM_QCA), y)
$(info $$CONFIG_IPF_PLATFORM_QCA is [${CONFIG_IPF_PLATFORM_QCA}])
TARGET_CFLAGS +=-DCONFIG_PLATFORM_QCA=1
CS_MAKEOPT += CONFIG_PLATFORM_QCA=1
CMAKE_OPTIONS += \
-DWL_PLATFORM=QCA
else ifeq ($(CONFIG_IPF_PLATFORM_MTK), y)
$(info $$CONFIG_IPF_PLATFORM_MTK is [${CONFIG_IPF_PLATFORM_MTK}])
TARGET_CFLAGS +=-DCONFIG_PLATFORM_MTK=1
CS_MAKEOPT += CONFIG_PLATFORM_MTK=1
CMAKE_OPTIONS += \
-DWL_PLATFORM=MTK
else ifeq ($(CONFIG_IPF_PLATFORM_BCM), y)
$(info $$CONFIG_IPF_PLATFORM_BCM is [${CONFIG_IPF_PLATFORM_BCM}])
TARGET_CFLAGS +=-DCONFIG_PLATFORM_BCM=1
CS_MAKEOPT += CONFIG_PLATFORM_BCM=1
CMAKE_OPTIONS += \
-DWL_PLATFORM=BCM
else
$(info No CONFIG_IPF_PLATFORM_XXX set, default QCA)
TARGET_CFLAGS +=-DCONFIG_PLATFORM_QCA=1
CS_MAKEOPT += CONFIG_PLATFORM_QCA=1
CMAKE_OPTIONS += \
-DWL_PLATFORM=QCA
endif
ifeq ($(CONFIG_WEXT_SIOCIWPRIV_NUM_RESTRIC_32), y)
TARGET_CFLAGS += -DWEXT_SIOCIWPRIV_NUM_RESTRIC_32=1
endif
ifeq ($(CONFIG_IS_MT798x), y)
TARGET_CFLAGS += -DCONFIG_IS_MT798x=1
endif
ifeq ($(CONFIG_OD_CHANNELLIMIT_SUPPORT), y)
TARGET_CFLAGS += -DOUTDOOR_CHANNELLIMIT
endif
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) -u ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) $(CS_MAKEOPT) $(TARGET_CONFIGURE_OPTS) LDFLAGS="$(TARGET_LDFLAGS)" CFLAGS="$(TARGET_CFLAGS)"
endef
define Package/channel-selector
SECTION:=TP-LINK
CATEGORY:=TP-LINK iplatform apps
MAINTAINER:= Wu Kan <wukan_w10495@tp-link.com.cn>
DEPENDS:=+libjson +libjson-c +libubox +libblobmsg-json +libubus +ubus +libuci +common
TITLE:= Channel Selector
endef
define Package/channel-selector/Description
Data collector, syncer and transfer for AI Projects.
endef
define Package/channel-selector/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/chansel $(1)/usr/sbin
endef
$(eval $(call BuildPackage,$(PKG_NAME)))
下一级目录下的Makefile如下:
ifeq ($(CONFIG_PLATFORM_QCA), 1)
SRC_C = $(wildcard *.c qca/*.c)
SRC_H = $(wildcard *.h qca/*.h)
else ifeq ($(CONFIG_PLATFORM_MTK), 1)
SRC_C = $(wildcard *.c mtk/*.c)
SRC_H = $(wildcard *.h mtk/*.h)
else ifeq ($(CONFIG_PLATFORM_BCM), 1)
SRC_C = $(wildcard *.c bcm/*.c)
SRC_H = $(wildcard *.h bcm/*.h)
endif
OBJS = $(patsubst %.c,%.o,$(SRC_C))
BIN = chansel
all: $(BIN)
$(OBJS): %.o: %.c $(SRC_H)
$(CC) $(CFLAGS) -c -o $@ $<
$(BIN): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^
clean:
rm $(OBJS) $(BIN)
而chansel.c的代码实现如下:
/*
* Copyright (c) 2006-2020 TP-Link Technologies CO.,LTD. All rights reserved.
*
* File name : chansel.c
* Description : Channel selector.
*
* Author : Wu Kan
* Date Created : 2020-09-28
*/
#include <net/ethernet.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "chansel.h"
#include "cs_util.h"
#include "cs_log.h"
#include "cs_scan_api.h"
/* -------------------------------------------------------------------------- */
/* DEFINES */
/* -------------------------------------------------------------------------- */
#define LINE_BUF_SIZE 256
#define MAX_CHN_SCORE 65535
#define CURRENT_CHANNEL_RATIO 75
#define CHANNELLIMIT_LEN 2
#define COUNTRY_CODE_LEN 5
#define FINAL_6G_CHANNEL 233
#define PROTECT_ERROR_NUM 6
#define ARR_SIZE(_a) \
sizeof(_a) / sizeof(_a[0])
#define MAX_FILTER_MAC_CNT 32
struct eth_addr_list {
int addr_cnt;
struct ether_addr mac_list[MAX_FILTER_MAC_CNT];
};
/* -------------------------------------------------------------------------- */
/* LOCAL VARIABLES */
/* -------------------------------------------------------------------------- */
struct {
const char *ifname;
const char *filter_file;
int channel_keep_thres;
int radio;
int limit_radio1_to_band4;
} chansel_opt = {0};
static CS_CHANNEL_STATE_T channel_state = {0};
struct eth_addr_list l_filter_mac_list = {0};
static CS_CHANNEL_LIST_T channel_list = {0};
static uint8_t l_sideband_channel_list[] = {1, 11, 12, 13, 165};
static uint8_t l_sideband_channel_of_6g[] = {229};
static uint8_t l_block_channel_of_6g[] = {101,117,133,149,165,181,197,213};
static uint8_t current_6G_channel;
static int overlap_flag ;
static int shift_num ;
/* -------------------------------------------------------------------------- */
/* LOCAL PROTOTYPES */
/* -------------------------------------------------------------------------- */
static void print_usage(void);
static int parse_args(char **argv);
static int get_config(char* config, int *value);
#ifdef OUTDOOR_CHANNELLIMIT
static void get_outdoor_channellimit(char* channellimit);
#endif
static int init_channel(CS_CHANNEL_STATE_T *state);
static int init_filter(const char *filename);
static bool match_filter(const struct ether_addr *addr);
static int handle_scan_result(CS_CHANNEL_STATE_T *state,
const CS_SCAN_RESULT_T *result);
static int handle_scan_entry(CS_CHANNEL_STATE_T *state,
const CS_AP_SCAN_INFO_T *entry);
static bool is_sideband(uint8_t channel);
static bool is_blockband_6g(uint8_t channel);
static uint8_t choose_channel(CS_CHANNEL_STATE_T *state);
static int append_filter_mac(const struct ether_addr *mac);
static int is_240m_mode(void);
/* -------------------------------------------------------------------------- */
/* LOCAL FUNCTIONS */
/* -------------------------------------------------------------------------- */
static void print_usage(void)
{
printf("Usage:\n");
printf("chansel [interface] <-r radio> <-f filter_file> <-t channel_keep_thres\n\n");
}
static int parse_args(char **argv)
{
char *arg;
argv++;
/* ifname */
arg = *argv;
if (arg == NULL) {
cs_log_err("No ifname input!");
return -1;
}
chansel_opt.ifname = arg;
argv++;
while ((arg = *argv) != NULL) {
if (!strcmp(arg, "-f")) {
argv++;
arg = *argv;
if (arg == NULL) {
cs_log_err("Invalid arguments.");
return -1;
}
chansel_opt.filter_file = arg;
}
if (!strcmp(arg, "-r")) {
argv++;
arg = *argv;
if (arg == NULL) {
cs_log_err("Invalid arguments.");
return -1;
}
if (!strcmp(arg, "1") || !strcmp(arg, "1+")) {
chansel_opt.radio = 1;
if (!strcmp(arg, "1+")) {
chansel_opt.limit_radio1_to_band4 = 1;
} else {
chansel_opt.limit_radio1_to_band4 = 0;
}
} else if (!strcmp(arg, "2")) {
chansel_opt.radio = 2;
} else if (!strcmp(arg, "3")) {
chansel_opt.radio = 3;
} else {
chansel_opt.radio = 0;
}
}
if (!strcmp(arg, "-t")) {
argv++;
arg = *argv;
chansel_opt.channel_keep_thres = atoi(arg);
if (chansel_opt.channel_keep_thres <= 0) {
chansel_opt.channel_keep_thres = CURRENT_CHANNEL_RATIO;
}
}
argv++;
}
if (chansel_opt.channel_keep_thres <= 0) {
chansel_opt.channel_keep_thres = CURRENT_CHANNEL_RATIO;
}
return 0;
}
#ifdef OUTDOOR_CHANNELLIMIT
static void get_outdoor_channellimit(char* channellimit)
{
FILE *fd;
int len;
char info[CHANNELLIMIT_LEN] = {0};
char cmd[70] = {0};
if (!channellimit)
return;
memset(info, 0, CHANNELLIMIT_LEN);
sprintf(cmd, "echo $(uci get band_limit.outdoor.channellimit) | tr -d \"\\n\"");
fd = popen(cmd, "r");
if (NULL == fd)
{
strcpy(channellimit, "0");
}
else
{
len = fread(info, sizeof(char), CHANNELLIMIT_LEN, fd);
pclose(fd);
if((info[0] != '\n') && (info[0] != '\0'))
{
memcpy(channellimit, info, strlen(info));
} else {
strcpy(channellimit, "0");
}
}
}
#endif
//get some config about channel limit
static int get_config(char* config, int *value){
FILE *fd;
char info[5] = {0};
char cmd[100] = {0};
if (!config || !value)
return 0;
memset(info, 0, 5);
if (!strcmp(config, "country_limit_band4"))
sprintf(cmd, "echo $(uci get channel-selector.list.country_limit_band4 -c /etc/profile.d/) | tr -d \"\\n\"");
else if(!strcmp(config, "chn_min_5g"))
sprintf(cmd, "echo $(uci get channel-selector.list.chn_min_5g -c /etc/profile.d/) | tr -d \"\\n\"");
else if(!strcmp(config, "chn_max_5g"))
sprintf(cmd, "echo $(uci get channel-selector.list.chn_max_5g -c /etc/profile.d/) | tr -d \"\\n\"");
else if(!strcmp(config, "chn_min_6g"))
sprintf(cmd, "echo $(uci get channel-selector.list.chn_min_6g -c /etc/profile.d/) | tr -d \"\\n\"");
else if(!strcmp(config, "chn_max_6g"))
sprintf(cmd, "echo $(uci get channel-selector.list.chn_max_6g -c /etc/profile.d/) | tr -d \"\\n\"");
else if(!strcmp(config, "country_limit_band3"))
sprintf(cmd, "echo $(uci get channel-selector.list.country_limit_band3 -c /etc/profile.d/) | tr -d \"\\n\"");
else
return 0;
fd = popen(cmd, "r");
if (NULL == fd)
{
return 0;
}
else
{
fread(info, sizeof(char), 5, fd);
pclose(fd);
char tmp[5] = {0};
if((info[0] != '\n') && (info[0] != '\0'))
{
memcpy(tmp, info, strlen(info));
} else {
strcpy(tmp, "0");
}
if (atoi(tmp))
*value = atoi(tmp);
}
return 1;
}
static bool is_bandwidth_160_5g()
{
FILE *fd;
int len;
char res[LINE_BUF_SIZE] = {0};
char cmd[LINE_BUF_SIZE] = {0};
sprintf(cmd, "echo $(uci get wifi.ap.enable_ht160) | tr -d \"\\n\"");
fd = popen(cmd, "r");
if (fd)
{
len = fread(res, sizeof(char), sizeof(res), fd);
pclose(fd);
if ((res[0] != '\n') && (res[0] != '\0'))
{
if (res[0] == '1') {
return true;
}
}
}
return false;
}
static int init_channel(CS_CHANNEL_STATE_T *state)
{
int idx = 0;
CS_CHANNEL_INFO_T *p_chn_info = NULL;
uint8_t chn_min = 1;
uint8_t chn_max = CS_MAX_CHANNEL;
#ifdef OUTDOOR_CHANNELLIMIT
char channellimit_id[CHANNELLIMIT_LEN] = {0};
memset(channellimit_id, 0, CHANNELLIMIT_LEN);
get_outdoor_channellimit(channellimit_id);
int country_limit_band3 = 0;
get_config("country_limit_band3", &country_limit_band3);
#endif
if (chansel_opt.radio == 1) {
//init 5G-auto-channel range
get_config("chn_min_5g", &chn_min);
if (chansel_opt.limit_radio1_to_band4 == 1){
chn_min = 149;
} else {
chn_max = 100;
}
get_config("chn_max_5g", &chn_max);
#ifdef OUTDOOR_CHANNELLIMIT
if(!strcmp(channellimit_id, "1") && country_limit_band3){
cs_log_err("country support 5G band3");
chn_min = 100;
chn_max = 128;
}
#endif
cs_log_err("init_channel: channel range(%d~%d)", chn_min, chn_max);
} else if(chansel_opt.radio == 2) {
chn_min = 100;
} else if(chansel_opt.radio == 3) {
//for 6G
chn_min = 69;
chn_max = FINAL_6G_CHANNEL;
get_config("chn_min_6g", &chn_min);
get_config("chn_max_6g", &chn_max);
memset(l_sideband_channel_list,0,sizeof(l_sideband_channel_list));
memcpy(l_sideband_channel_list,l_sideband_channel_of_6g,sizeof(l_sideband_channel_of_6g));
}
if (cs_get_channel_list(chansel_opt.ifname, &channel_list) < 0) {
cs_log_err("Fail to get channel list of vap(%s).", chansel_opt.ifname);
return -1;
}
if (chansel_opt.limit_radio1_to_band4 != 1 && chansel_opt.radio == 1 && is_bandwidth_160_5g() && (149 <= chn_min || 161 == chn_max) && (channel_list.cur_chan < 149)){
chn_min = 36;
chn_max = 100;
cs_log_err("init_channel: channel range change from HT80 to HT160(%d~%d)", chn_min, chn_max);
}
if (!state) {
cs_log_err("Null channel state.");
return -1;
}
for (idx = 0; idx < channel_list.chan_num; idx ++) {
if (is_sideband(channel_list.chan_list[idx])) {
continue;
}
if (is_blockband_6g(channel_list.chan_list[idx]) && 3 == chansel_opt.radio ){
continue;
}
if (channel_list.chan_list[idx] >= chn_min &&
channel_list.chan_list[idx] <= chn_max ) {
p_chn_info = &state->chn_list[channel_list.chan_list[idx]];
p_chn_info->used = 1;
p_chn_info->score = MAX_CHN_SCORE;
}
}
return 0;
}
static int append_filter_mac(const struct ether_addr *mac)
{
int idx = l_filter_mac_list.addr_cnt;
if (idx >= MAX_FILTER_MAC_CNT) {
cs_log_info("Filter mac list is full.");
return -1;
}
memcpy(&l_filter_mac_list.mac_list[idx], mac, sizeof(struct ether_addr));
cs_log_debug("%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx apends to mac filter.",
mac->ether_addr_octet[0],
mac->ether_addr_octet[1],
mac->ether_addr_octet[2],
mac->ether_addr_octet[3],
mac->ether_addr_octet[4],
mac->ether_addr_octet[5]);
l_filter_mac_list.addr_cnt++;
return 0;
}
static int init_filter(const char *filename)
{
char line[LINE_BUF_SIZE] = {0};
struct ether_addr mac = {0};
FILE *fp = NULL;
int filter_size = 0;
fp = fopen(filename, "r");
if (!fp) {
cs_log_err("Fail to open file: %s", filename);
return -1;
}
while (fgets(line, sizeof(line), fp) != NULL &&
filter_size < MAX_FILTER_MAC_CNT) {
sscanf(line, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&mac.ether_addr_octet[0],
&mac.ether_addr_octet[1],
&mac.ether_addr_octet[2],
&mac.ether_addr_octet[3],
&mac.ether_addr_octet[4],
&mac.ether_addr_octet[5]);
append_filter_mac(&mac);
filter_size++;
}
fclose(fp);
return 0;
}
static bool match_filter(const struct ether_addr *addr)
{
struct ether_addr addr1 = {0};
struct ether_addr addr2 = {0};
int idx;
bool ret = false;
memcpy(&addr1, addr, sizeof(addr1));
addr1.ether_addr_octet[0] = 0;
addr1.ether_addr_octet[1] = 0;
for (idx = 0; idx < l_filter_mac_list.addr_cnt; idx++) {
memcpy(&addr2, &l_filter_mac_list.mac_list[idx], sizeof(addr2));
addr2.ether_addr_octet[0] = 0;
addr2.ether_addr_octet[1] = 0;
ret = is_addr_similar(&addr1, &addr2);
if (ret == true) {
cs_log_debug("%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx mactches "
"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
addr->ether_addr_octet[0], addr->ether_addr_octet[1],
addr->ether_addr_octet[2], addr->ether_addr_octet[3],
addr->ether_addr_octet[4], addr->ether_addr_octet[5],
l_filter_mac_list.mac_list[idx].ether_addr_octet[0],
l_filter_mac_list.mac_list[idx].ether_addr_octet[1],
l_filter_mac_list.mac_list[idx].ether_addr_octet[2],
l_filter_mac_list.mac_list[idx].ether_addr_octet[3],
l_filter_mac_list.mac_list[idx].ether_addr_octet[4],
l_filter_mac_list.mac_list[idx].ether_addr_octet[5]);
break;
}
}
return ret;
}
static int handle_scan_result(CS_CHANNEL_STATE_T *state,
const CS_SCAN_RESULT_T *result)
{
int i;
struct ether_addr bssid = {0};
if (!state) {
cs_log_err("Null channel state.");
return -1;
}
if (!result) {
cs_log_err("Null scan result.");
return -1;
}
//add operation of 6G
if(chansel_opt.radio==3){
state->chn_list[current_6G_channel].ap_num=result->ap_num;
state->chn_list[current_6G_channel].overlap_num=PROTECT_ERROR_NUM;
/*给所有的信道添加一个初始底值,减少因为扫描失误等原因优化的可能性,并且对信道的ap进行判断,如果某个信道的ap数大于保护值6就把其flag标志位1通过移位来实现存储
*如果所有的信道都超过底值了,就把信道中的底值取消,否则不取消,底值的计算为允许一次噪声为-30到-60间的ap扫描误差的值,通过计算为6
*/
if(result->ap_num >= PROTECT_ERROR_NUM){
overlap_flag |= (1<<shift_num);
}
shift_num++;
}else{
for (i = 0; i < result->ap_num; i++) {
memcpy(bssid.ether_addr_octet, result->ap_list[i].bssid,
sizeof(bssid.ether_addr_octet));
if (match_filter(&bssid)) {
continue;
}
handle_scan_entry(state, &result->ap_list[i]);
}
}
return 0;
}
static int handle_scan_entry(CS_CHANNEL_STATE_T *state,
const CS_AP_SCAN_INFO_T *entry)
{
uint8_t channel = entry->channel;
if (channel > 4) {
state->chn_list[channel - 4].overlap_num++;
}
if (channel > 3) {
state->chn_list[channel - 3].overlap_num++;
}
if (channel > 2) {
state->chn_list[channel - 2].overlap_num++;
}
if (channel > 1) {
state->chn_list[channel - 1].overlap_num++;
}
state->chn_list[channel].ap_num++;
if (channel < CS_MAX_CHANNEL - 1) {
state->chn_list[channel + 1].overlap_num++;
}
if (channel < CS_MAX_CHANNEL - 2) {
state->chn_list[channel + 2].overlap_num++;
}
if (channel < CS_MAX_CHANNEL - 3) {
state->chn_list[channel + 3].overlap_num++;
}
if (channel < CS_MAX_CHANNEL - 4) {
state->chn_list[channel + 4].overlap_num++;
}
return 0;
}
static bool is_sideband(uint8_t channel)
{
int i;
for (i = 0; i < ARR_SIZE(l_sideband_channel_list); i++) {
if (channel == l_sideband_channel_list[i]) {
return true;
}
}
return false;
}
static bool is_blockband_6g(uint8_t channel)
{
int i;
for (i = 0; i < ARR_SIZE(l_block_channel_of_6g); i++) {
if (channel == l_block_channel_of_6g[i]) {
return true;
}
}
return false;
}
static bool is_bandwidth_240_5g()
{
FILE *fd;
int len;
char res[LINE_BUF_SIZE] = {0};
char cmd[LINE_BUF_SIZE] = {0};
sprintf(cmd, "echo $(uci get ext_wifi.ap.enable_ht240) | tr -d \"\\n\"");
fd = popen(cmd, "r");
if (fd)
{
len = fread(res, sizeof(char), sizeof(res), fd);
pclose(fd);
if ((res[0] != '\n') && (res[0] != '\0'))
{
if (res[0] == '1') {
return true;
}
}
}
return false;
}
static uint8_t choose_channel(CS_CHANNEL_STATE_T *state)
{
int idx;
uint8_t best_chn = 0;
int best_score = 0;
int current_socre;
CS_CHANNEL_INFO_T *p_chn_info = NULL;
int radio = chansel_opt.radio;
uint8_t chan_min = 1;
uint8_t chan_max = CS_MAX_CHANNEL;
int all_no_need_protect=0;
bool no_need_protect = false;
int country_limit_band4 = 0;
if (radio == 1) {
#ifdef OUTDOOR_CHANNELLIMIT
//uci get band_limit.outdoor.channellimit
char channellimit_id[CHANNELLIMIT_LEN] = {0};
memset(channellimit_id, 0, CHANNELLIMIT_LEN);
get_outdoor_channellimit(channellimit_id);
int country_limit_band3 = 0;
get_config("country_limit_band3",&country_limit_band3);
#endif
get_config("country_limit_band4", &country_limit_band4);
if (chansel_opt.limit_radio1_to_band4 == 1){
chan_min = 149;
chan_max = 161;
} else {
chan_min = 36;
chan_max = 48;
}
if (country_limit_band4){
if( (is_bandwidth_160_5g() && channel_list.cur_chan >= 149) || !is_bandwidth_160_5g()){
cs_log_err("choose 5G band4 channel. ");
chan_min = 149;
chan_max = 161;
}
else{
chan_min = 36;
chan_max = 48;
}
}
#ifdef OUTDOOR_CHANNELLIMIT
else if(!strcmp(channellimit_id, "1") && country_limit_band3){
cs_log_err("country support 5G band3");
chan_min = 100;
chan_max = 128;
}
#endif
} else if (radio == 2) {
chan_min = 100;
} else if(radio == 3) {
//for 6G
//get country
chan_min = 69;
chan_max = FINAL_6G_CHANNEL;
get_config("chn_min_6g", &chan_min);
get_config("chn_max_6g", &chan_max);
}
if(radio==3){
shift_num -= 1;
for(shift_num ; shift_num >= 0 ; shift_num--){
all_no_need_protect |= (1 << shift_num);
};
if(overlap_flag == all_no_need_protect){ //如果6G的信道扫描出来的结果都大于等于6,那么不添加overlap_num保护,置0
no_need_protect = true;
}
}
cs_log_debug("Channel | Score | Apnum | Overlaped");
for (idx = 0; idx < CS_MAX_CHANNEL; idx++) {
if (state->chn_list[idx].used) {
if(no_need_protect){
state->chn_list[idx].overlap_num = 0;
}
state->chn_list[idx].score /=
(state->chn_list[idx].ap_num + state->chn_list[idx].overlap_num + 1);
cs_log_debug(" %3d %5d %3d %3d",
idx, state->chn_list[idx].score,
state->chn_list[idx].ap_num,
state->chn_list[idx].overlap_num);
}
}
for (idx = 0; idx < channel_list.chan_num; idx++) {
/* We should avoid using sideband channel for the low tx power.
Working in sideband may decrease covering area. */
if (is_sideband(channel_list.chan_list[idx])) {
continue;
}
if (is_blockband_6g(channel_list.chan_list[idx]) && 3 == radio ){
continue;
}
if (channel_list.chan_list[idx] < chan_min ||
channel_list.chan_list[idx] > chan_max) {
continue;
}
p_chn_info = &state->chn_list[channel_list.chan_list[idx]];
if (best_score < p_chn_info->score) {
best_score = p_chn_info->score;
best_chn = channel_list.chan_list[idx];
}
}
/* If best score is not too larger than current,
select current channel as the best. */
current_socre = state->chn_list[channel_list.cur_chan].score;
cs_log_debug("Best channel %3hhu has score: %5d\n"
"Curr channel %3hhu has score: %5d",
best_chn, best_score,
channel_list.cur_chan, current_socre);
if (is_240m_mode() && (radio == 1)){
cs_log_debug("Bandwidth is 240M, keep current channel as the best.");
best_chn = channel_list.cur_chan;
}
if (current_socre * 100 / best_score > chansel_opt.channel_keep_thres) {
cs_log_debug("Keep current channel as the best.");
best_chn = channel_list.cur_chan;
}
if (is_bandwidth_240_5g() && (channel_list.cur_chan == 116)) {
cs_log_debug("5G bandwidth 240M, keep current channel as the best.");
best_chn = channel_list.cur_chan;
}
return best_chn;
}
/* -------------------------------------------------------------------------- */
/* PUBLIC FUNCTIONS */
/* -------------------------------------------------------------------------- */
int main(int argc, char **argv)
{
CS_SCAN_RESULT_T scan_result = {0};
uint8_t best_channel;
uint8_t chn_idx = 0;
uint8_t scan_count = 0;
uint8_t radio = chansel_opt.radio;
overlap_flag = 0;
shift_num = 0;
if (parse_args(argv) < 0) {
print_usage();
return -1;
}
if (chansel_opt.filter_file != NULL) {
if (init_filter(chansel_opt.filter_file) < 0) {
return -1;
}
}
if (init_channel(&channel_state) < 0) {
return -1;
}
#if 0
if (cs_flush_scan_result(chansel_opt.ifname) < 0) {
return -1;
}
#endif
#if 0
if (cs_do_scan(chansel_opt.ifname) < 0) {
return -1;
}
#endif
for (chn_idx = 0; chn_idx < CS_MAX_CHANNEL; chn_idx++) {
if (channel_state.chn_list[chn_idx].used) {
memset(&scan_result, 0, sizeof(scan_result));
scan_result.ap_num = MAX_SCAN_AP_NUM;
if (cs_get_scan_result(chansel_opt.ifname, &scan_result, chn_idx, &scan_count) < 0) {
return -1;
}
current_6G_channel = chn_idx;
if (handle_scan_result(&channel_state, &scan_result) < 0) {
return -1;
}
}
}
best_channel = choose_channel(&channel_state);
printf("Best channel is %u\n", best_channel);
return 0;
}
static int is_240m_mode(void)
{
#define CONFIG_LEN 5
FILE *fd;
char info[CONFIG_LEN + 1] = {0};
char cmd[100] = {0};
int ret = 0;
sprintf(cmd, "echo $(uci get ext_wifi.ap.enable_ht240 -c /etc/config/) | tr -d \"\\n\"");
fd = popen(cmd, "r");
if (NULL == fd)
{
cs_log_err("get 240M mode config fail");
return ret;
}
else
{
fread(info, sizeof(char), CONFIG_LEN, fd);
pclose(fd);
char tmp[CONFIG_LEN + 1] = {0};
if((info[0] != '\n') && (info[0] != '\0'))
{
memcpy(tmp, info, strlen(info));
} else {
strcpy(tmp, "0");
}
ret = atoi(tmp);
}
return ret;
#undef CONFIG_LEN
}