一起玩转GNU Radio:选择器Selector

本文深入探讨了GNURadio中的选择器模块,引用了Alexandros-Apostolos A. Boulogeorgos作者的GitHub资源,该资源包含大量GRC实例。作者计划逐步解析这些实例,并分享个人理解和扩展内容,包括模块参数解释和功能描述。同时,作者将分享自己的GNURadio实例,旨在为GNURadio用户和爱好者提供帮助,鼓励互动和资源共享。

本文内容、开发板及配件仅限用于学校或科研院所开展科研实验!

本文介绍GNU Radio中的选择器模块。

在开始介绍之前,首先推荐一下Alexandros-Apostolos A. Boulogeorgos作者的https://github.com/aboulogeorgos/Wireless-communication-systems-Lab,这里作者分享了大量的GRC实例,但是我看目前关注的人数很少。我也是看了这个之后,被作者整理汇总工作的细致程度深深打动,下定决心一口气读完了作者分享的所有实例。

我打算在接下来一段时间里,首先把作者分享的实例,加上我个人的理解,继续丰富一下内容(例如XX模块中的参数的含义解释,以及XX模块的功能解释等等),然后,也把我这几年来搜集到的、自己改写的一些GNU Radio实例分享给大家,希望能够对关注、使用GNU Radio的朋友有所帮助。也欢迎大家有问题及时反馈给我,或者有好的实例,一起分享给大家。

目录

一、selector.grc

二、有用链接


一、selector.grc

参考下列代码实现,仿照对应的目录形式,请你给出一个能在wifi样机中打印"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 }
最新发布
10-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值