lib_chan 简化版

我觉得那个lib_chan太烦,用法我也觉得不那么清晰,反正我不喜欢。
我把它改了改,其实完全不一样,就是中间人的协议类似。
这样我觉得用起来舒服些。


-module(mm).
-compile(export_all).

client_start(Address,Port,Pid) ->
spawn(fun() ->connect(Address,Port,Pid) end).

connect(Address,Port,Pid) ->
{ok,Socket}=gen_tcp:connect(Address,Port,[binary,{packet,4}]),
loop(Socket,Pid).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

server_start(Port,Pid) ->
spawn(fun() ->start_parallel_server(Port,Pid) end),
ok.

start_parallel_server(Port,Pid) ->
link(Pid), %% Pid死的时候,listen也得死
{ok,Listen}=gen_tcp:listen(Port,[binary,{reuseaddr,true},{packet,4},{active,true}]),
spawn(fun()->par_connect(Listen,Pid) end),
%% just waiting
receive
after infinity ->
true
end.

par_connect(Listen,Pid) ->
case gen_tcp:accept(Listen) of
{ok,Socket} ->
spawn(fun()->par_connect(Listen,Pid) end),%% 启动一个新进程来accept连接,当前进程处理接受的socket
link(Pid), %% Pid死的时候,mm也得死(当前进程变成了mm)
loop(Socket,Pid);
{error,closed} ->
io:format("Listenning accept socket error,and was closed!~n")
end.

loop(Socket,Pid) ->
receive
{tcp,Socket,Data} ->
Term=binary_to_term(Data),
Pid ! {mm,self(),Term},
loop(Socket,Pid);
{tcp_closed,Socket} ->
Pid !{mm_closed,self()};
{send,Term} ->
gen_tcp:send(Socket,term_to_binary(Term)),
loop(Socket,Pid);
close -> %% when client or server exit,use it,gen a tcp_closed at another point
gen_tcp:close(Socket)
end.
static int _getAcsReport(UINT32 rid, CHANNEL_DEPLOY_ACS_TABLE *pTable, BOOL isChannelSelect) { INT32 i = 0, n = 0; INT32 apid = 0; UINT8 retry = 0; struct ifreq ifr; struct iwreq *piwr = NULL; INT32 upVapNum = 0; char upVapName[MAX_VAP_PER_RADIO][VAP_NAME_LEN] = {0}; UINT8 *pIfname = NULL; UINT32 originalChannel = 0; struct ieee80211req_athdbg reqdbg; struct ieee80211_acs_dbg acsdbg; #if TP_QCA_SDK_VERSION_HIGHER(11,4,0) UINT32 originalChannelIdx = 0; #endif/* TP_QCA_SDK_VERSION_HIGHER(11,4,0) */ /* for 6G PSC */ ACS_SCAN_ITEM filtertmp[CHSCAN_MAX_PSC_CHANNEL_NUM]; int new_num = 0; if (NULL == pTable) { CD_ERROR("input invalid \n"); return -1; } if (rid < 0 || rid > MAX_RADIO_NUM_SUPP()) { CD_ERROR("radio ID error\n"); return -1; } /* 因为在采集数据之前需要做6G频段的判断,所以在进入之前对rdaioID进行赋值 */ pTable->radioID = rid; CD_DEBUG("try to do acs and get report...\n"); /*初始化网络套接字*/ if ((wlan_lib_initSocket(&l_sock)) < 0) { CD_ERROR("failed to init sock\n"); return -1; } memset(upVapName, 0, sizeof(upVapName)); /* get all up vaps in radio */ upVapNum = wlan_lib_getUpVapList(rid, upVapName); if (upVapNum == 0) { CD_ERROR("not up vap\n"); return -1; } pIfname = upVapName[0]; // 选取首个活跃VAP作为操作接口 if (isChannelSelect) { /* trigger acs scan and it will change vaps' channel * so, get original channel for restore */ if(WLAN_OK != wlan_lib_getVapChanFreq(pIfname, &originalChannel)) //保存原始信道 { CD_ERROR("get channel failed for %s\n", pIfname); return -1; } #if TP_QCA_SDK_VERSION_HIGHER(11,4,0) /* 高于该版本不需要先down再up,可以直接触发 */ util_execFormatCmd("cfg80211tool %s channel 0", upVapName[i]); #else for(i = 0; i < upVapNum; ++i) { util_execFormatCmd("ifconfig %s down", upVapName[i]); } for(i = 0; i < upVapNum; ++i) { util_execFormatCmd("iwconfig %s freq -1", upVapName[i]); } for(i = 0; i < upVapNum; ++i) { util_execFormatCmd("ifconfig %s up", upVapName[i]); } #endif /* TP_QCA_SDK_VERSION_HIGHER(11,4,0) */ } else { /* trigger acs scan but will not change vaps' channel */ util_execFormatCmd("wifitool %s tr069_getacsscan 1", pIfname); } /* waiting acs scan finish, 5s for 2G\5G1\5G2, 20s for 6G */ if(RADIO_IS_6G(pTable->radioID)) { usleep(CHSCAN_WAIT_MICROSECOND_ALL_CHANNEL_6G); } else { usleep(CHSCAN_WAIT_MICROSECOND_ALL_CHANNEL); } /* get acs report */ memset(&ifr, 0, sizeof(ifr)); memset(&reqdbg, 0, sizeof(struct ieee80211req_athdbg)); memset(&acsdbg, 0, sizeof(struct ieee80211_acs_dbg)); piwr = (struct iwreq *)&ifr; strncpy(piwr->ifr_name, pIfname, IFNAMELEN); piwr->u.data.pointer = (void *) &reqdbg; piwr->u.data.length = (sizeof(struct ieee80211req_athdbg)); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0)) if (piwr->u.data.length > IW_PRIV_SIZE_MASK) /* 内核限制 */ { piwr->u.data.length /= 8; } #endif reqdbg.cmd = IEEE80211_DBGREQ_GETACSREPORT; reqdbg.data.acs_rep.data_addr = &acsdbg; reqdbg.data.acs_rep.data_size = sizeof(struct ieee80211_acs_dbg); reqdbg.data.acs_rep.index = 0; acsdbg.entry_id = 0; retry = 0; while(retry++ < CHSCAN_MAX_GET_RESULT_RETRY) { if (ioctl(l_sock, IEEE80211_IOCTL_DBGREQ, piwr) < 0) { CD_ERROR("ioctl error, reason: %s\r\n", strerror(errno)); goto leave; } /* if acs in progress, nchans will be set to 0 by driver */ if (0 < acsdbg.nchans) { break; } /* acs in progress, wait 500ms and retry */ usleep(CHSCAN_WAIT_MICROSECOND_SCAN_INTERVAL); } if(retry > CHSCAN_MAX_GET_RESULT_RETRY) { CD_ERROR("get acs report exceed %d times\r\n", retry); goto leave; } n = 0; for (i = 0; i < acsdbg.nchans; i++) { acsdbg.entry_id = i; reqdbg.cmd = IEEE80211_DBGREQ_GETACSREPORT; if (ioctl(l_sock, IEEE80211_IOCTL_DBGREQ, piwr) < 0) { CD_ERROR("ioctl error, reason: %s\r\n", strerror(errno)); goto leave; } if( acsdbg.chan_load > 100) { acsdbg.chan_load = 100; } if(n < MAX_CHANNEL_NUM) { pTable->acsItem[n].channel = acsdbg.ieee_chan; pTable->acsItem[n].bssNum = acsdbg.chan_nbss; pTable->acsItem[n].maxrssi = acsdbg.chan_maxrssi + NOISE_LEVEL; pTable->acsItem[n].minrssi = acsdbg.chan_minrssi + NOISE_LEVEL; pTable->acsItem[n].nsFloor = acsdbg.noisefloor; pTable->acsItem[n].rxUtil = acsdbg.chan_load; n ++; } } CD_DEBUG("getChanUtil done, channel num=%d \n", n); pTable->itemNum = n; //实际获取的信道数量 /* 对于6G信道,只需要返回13个PSC信道 */ if (RADIO_IS_6G(pTable->radioID)) { memset(filtertmp, 0, sizeof(ACS_SCAN_ITEM) * CHSCAN_MAX_PSC_CHANNEL_NUM); for(i = 0; i < MAX_CHANNEL_NUM; i++) { if(API_IS_6G_PSC_CHANNEL(pTable->acsItem[i].channel)) { CD_DEBUG("Find the PSC Channel: %d",pTable->acsItem[i].channel); filtertmp[new_num] = pTable->acsItem[i]; new_num += 1; } else { continue; } } pTable->itemNum = new_num; for(i = 0; i < pTable->itemNum; i++) { pTable->acsItem[i] = filtertmp[i]; } CD_DEBUG("The psc channel num is %d \n", new_num); } if (isChannelSelect) { /* wait for channel selection finish, 5s */ usleep(CHSCAN_WAIT_MICROSECOND_ALL_CHANNEL); /* get acs result channel */ if(WLAN_OK != wlan_lib_getVapChanFreq(pIfname, &pTable->acsChannel)) { CD_ERROR("get channel failed for %s\n", pIfname); goto leave; } CD_DEBUG("pTable->acsChannel: %d", pTable->acsChannel); /* set target channel because acs will change channel */ #if TP_QCA_SDK_VERSION_HIGHER(11,4,0) /* 对于6G信道,需要使用新的修改信道的命令 */ if(RADIO_IS_6G(pTable->radioID)) { originalChannelIdx = MHZ_TO_CHANNUM(originalChannel); util_execFormatCmd("cfg80211tool %s channel %d 3", pIfname, originalChannelIdx); } /* 对于非6G信道,无法使用iwconfig + 频率来配置,可以使用 iwconfig + 信道号来配置 */ else { originalChannelIdx = MHZ_TO_CHANNUM(originalChannel); util_execFormatCmd("iwconfig %s freq %d", pIfname, originalChannelIdx); } #else util_execFormatCmd("iwconfig %s freq %d", pIfname, originalChannel); #endif /* TP_QCA_SDK_VERSION_HIGHER(11,4,0) */ } return 0; leave: if (isChannelSelect) { /* set target channel because acs will change channel */ #if TP_QCA_SDK_VERSION_HIGHER(11,4,0) /* 对于6G信道,需要使用新的修改信道的命令 */ if(RADIO_IS_6G(pTable->radioID)) { originalChannelIdx = MHZ_TO_CHANNUM(originalChannel); util_execFormatCmd("cfg80211tool %s channel %d 3", pIfname, originalChannelIdx); } /* 对于非6G信道,无法使用iwconfig + 频率来配置,可以使用 iwconfig + 信道号来配置 */ else { originalChannelIdx = MHZ_TO_CHANNUM(originalChannel); util_execFormatCmd("iwconfig %s freq %d", pIfname, originalChannelIdx); } #else util_execFormatCmd("iwconfig %s freq %d", pIfname, originalChannel); #endif /* TP_QCA_SDK_VERSION_HIGHER(11,4,0) */ } return -1; } 上述提供的_getAcsReport函数是在QCA机型上实现的,现在要在BCM机型上实现,需要如何改进,给出完整的代码
10-10
现在,再次给出下列需求的完整代码、流程、解释注释: 参考下列代码实现,仿照对应的目录形式,请你给出一个能在样机中打印"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
``` import torch import torch.nn as nn from skimage.segmentation import chan_vese import numpy as np from torch.nn import Conv2d from torchvision.ops import FeaturePyramidNetwork from torchvision.models import resnet50 import os os.environ['KMP_DUPLICATE_LIB_OK']='TRUE' def process_conv_output(conv_output): assert conv_output.shape == (64, 16, 3, 3), "Input tensor shape is not correct!" chunks = torch.chunk(conv_output, chunks=4, dim=0) for idx, chunk in enumerate(chunks): print(f"Chunk {idx} Shape: ", chunk.shape) assert chunk.shape == (16, 16, 3, 3) return chunks class ImageSegmentationModel(nn.Module): def __init__(self): super(ImageSegmentationModel,self).__init__() self.conv_layers = nn.Sequential( nn.Conv2d(1,128,kernel_size=3,stride=2), nn.MaxPool2d(kernel_size=3,stride=2), nn.ReLU(), nn.Conv2d(128,64, kernel_size=3, stride=2), nn.MaxPool2d(kernel_size=3, stride=2), nn.ReLU(), nn.Conv2d(64,32,kernel_size=3,stride=2), nn.MaxPool2d(kernel_size=3,stride=2), nn.ReLU(), nn.Conv2d(32,16,kernel_size=3,stride=2) ) self.resnet = resnet50(pretrained=True) self.initial_layer = nn.Sequential( self.resnet.conv1, # 输出通道64 self.resnet.bn1, self.resnet.relu, self.resnet.maxpool # 输出通道64 ) self.layer1 = self.resnet.layer1 self.layer2 = self.resnet.layer2 self.layer3 = self.resnet.layer3 self.layer4 = self.resnet.layer4 self.fpn = FeaturePyramidNetwork([256,512,1024,2048],256) self.conv_layers11 = nn.Conv2d(256,1,kernel_size=1,stride=1) self.final_conv = nn.Conv2d(16,21,kernel_size=1,stride=1) self.softmax = nn.Softmax(dim=1) def preprocess(self,x): x = torch.nn.functional.interpolate(x,size=(511,511),mode='bilinear',align_corners=False) x = torch.mean(x,dim=1,keepdim=True) x_np = x.detach().cpu().numpy() segmented = [] for i in range(x_np.shape[0]): img = x_np[i,0] #init =np.array([[img.shape[1]-1,0],[img.shape[1]-1,img.shape[0]-1],[0,img.shape[0]-1,],[0,0]]) snake = chan_vese(img,mu=0.25, lambda1=1.0, lambda2=1.0, tol=0.001, max_num_iter=500, dt=0.5) seg = np.zeros_like(img) from skimage.draw import polygon rr, cc = polygon(snake[:,1],snake[:,0],seg.shape) seg[rr, cc] = 1 segmented.append(seg) segmented = np.array(segmented) segmented = torch.from_numpy(segmented).unsqueeze(1).float().to(x.device) return segmented def forward(self,x): y = torch.nn.functional.interpolate(x,size=(511,511),mode='bilinear',align_corners=False) x = self.preprocess(x) conv_output = self.conv_layers(x) conv_output_tuple = process_conv_output(conv_output) print("conv_output:", conv_output.shape) z = self.initial_layer(y) c1 = self.layer1(z) # [batch,256,H,W] c2 = self.layer2(c1) # [batch,512,H,W] c3 = self.layer3(c2) # [batch,1024,H,W] c4 = self.layer4(c3) # [batch,2048,H,W] fpn_input = { 'feat1': c1, 'feat2': c2, 'feat3': c3, 'feat4': c4 } fpn_output = self.fpn(fpn_input) fpn_output_upsampled = torch.nn.functional.interpolate(fpn_output['feat1'], size=(511, 511), mode='bilinear', align_corners=False) final_output = nn.functional.conv2d(fpn_output_upsampled,conv_output_tuple,stride=1,padding=1,groups=16) final_output = self.final_conv(final_output) final_output = self.softmax(final_output) return final_output```改动不涉及fpn_output请重新修改
03-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值