📄 11d.c
字号:
/** * This file contains functions for 802.11D. */#include <linux/ctype.h>#include <linux/kernel.h>#include <linux/wireless.h>#include "host.h"#include "decl.h"#include "11d.h"#include "dev.h"#include "wext.h"#define TX_PWR_DEFAULT 10static struct region_code_mapping region_code_mapping[] = { {"US ", 0x10}, /* US FCC */ {"CA ", 0x10}, /* IC Canada */ {"SG ", 0x10}, /* Singapore */ {"EU ", 0x30}, /* ETSI */ {"AU ", 0x30}, /* Australia */ {"KR ", 0x30}, /* Republic Of Korea */ {"ES ", 0x31}, /* Spain */ {"FR ", 0x32}, /* France */ {"JP ", 0x40}, /* Japan */};/* Following 2 structure defines the supported channels */static struct chan_freq_power channel_freq_power_UN_BG[] = { {1, 2412, TX_PWR_DEFAULT}, {2, 2417, TX_PWR_DEFAULT}, {3, 2422, TX_PWR_DEFAULT}, {4, 2427, TX_PWR_DEFAULT}, {5, 2432, TX_PWR_DEFAULT}, {6, 2437, TX_PWR_DEFAULT}, {7, 2442, TX_PWR_DEFAULT}, {8, 2447, TX_PWR_DEFAULT}, {9, 2452, TX_PWR_DEFAULT}, {10, 2457, TX_PWR_DEFAULT}, {11, 2462, TX_PWR_DEFAULT}, {12, 2467, TX_PWR_DEFAULT}, {13, 2472, TX_PWR_DEFAULT}, {14, 2484, TX_PWR_DEFAULT}};static u8 wlan_region_2_code(u8 * region){ u8 i; u8 size = sizeof(region_code_mapping)/ sizeof(struct region_code_mapping); for (i = 0; region[i] && i < COUNTRY_CODE_LEN; i++) region[i] = toupper(region[i]); for (i = 0; i < size; i++) { if (!memcmp(region, region_code_mapping[i].region, COUNTRY_CODE_LEN)) return (region_code_mapping[i].code); } /* default is US */ return (region_code_mapping[0].code);}static u8 *wlan_code_2_region(u8 code){ u8 i; u8 size = sizeof(region_code_mapping) / sizeof(struct region_code_mapping); for (i = 0; i < size; i++) { if (region_code_mapping[i].code == code) return (region_code_mapping[i].region); } /* default is US */ return (region_code_mapping[0].region);}/** * @brief This function finds the nrchan-th chan after the firstchan * @param band band * @param firstchan first channel number * @param nrchan number of channels * @return the nrchan-th chan number*/static u8 wlan_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 * chan)/*find the nrchan-th chan after the firstchan*/{ u8 i; struct chan_freq_power *cfp; u8 cfp_no; cfp = channel_freq_power_UN_BG; cfp_no = sizeof(channel_freq_power_UN_BG) / sizeof(struct chan_freq_power); for (i = 0; i < cfp_no; i++) { if ((cfp + i)->channel == firstchan) { lbs_deb_11d("firstchan found\n"); break; } } if (i < cfp_no) { /*if beyond the boundary */ if (i + nrchan < cfp_no) { *chan = (cfp + i + nrchan)->channel; return 1; } } return 0;}/** * @brief This function Checks if chan txpwr is learned from AP/IBSS * @param chan chan number * @param parsed_region_chan pointer to parsed_region_chan_11d * @return TRUE; FALSE*/static u8 wlan_channel_known_11d(u8 chan, struct parsed_region_chan_11d * parsed_region_chan){ struct chan_power_11d *chanpwr = parsed_region_chan->chanpwr; u8 nr_chan = parsed_region_chan->nr_chan; u8 i = 0; lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)chanpwr, sizeof(struct chan_power_11d) * nr_chan); for (i = 0; i < nr_chan; i++) { if (chan == chanpwr[i].chan) { lbs_deb_11d("found chan %d\n", chan); return 1; } } lbs_deb_11d("chan %d not found\n", chan); return 0;}u32 libertas_chan_2_freq(u8 chan, u8 band){ struct chan_freq_power *cf; u16 cnt; u16 i; u32 freq = 0; cf = channel_freq_power_UN_BG; cnt = sizeof(channel_freq_power_UN_BG) / sizeof(struct chan_freq_power); for (i = 0; i < cnt; i++) { if (chan == cf[i].channel) freq = cf[i].freq; } return freq;}static int generate_domain_info_11d(struct parsed_region_chan_11d *parsed_region_chan, struct wlan_802_11d_domain_reg * domaininfo){ u8 nr_subband = 0; u8 nr_chan = parsed_region_chan->nr_chan; u8 nr_parsedchan = 0; u8 firstchan = 0, nextchan = 0, maxpwr = 0; u8 i, flag = 0; memcpy(domaininfo->countrycode, parsed_region_chan->countrycode, COUNTRY_CODE_LEN); lbs_deb_11d("nrchan %d\n", nr_chan); lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)parsed_region_chan, sizeof(struct parsed_region_chan_11d)); for (i = 0; i < nr_chan; i++) { if (!flag) { flag = 1; nextchan = firstchan = parsed_region_chan->chanpwr[i].chan; maxpwr = parsed_region_chan->chanpwr[i].pwr; nr_parsedchan = 1; continue; } if (parsed_region_chan->chanpwr[i].chan == nextchan + 1 && parsed_region_chan->chanpwr[i].pwr == maxpwr) { nextchan++; nr_parsedchan++; } else { domaininfo->subband[nr_subband].firstchan = firstchan; domaininfo->subband[nr_subband].nrchan = nr_parsedchan; domaininfo->subband[nr_subband].maxtxpwr = maxpwr; nr_subband++; nextchan = firstchan = parsed_region_chan->chanpwr[i].chan; maxpwr = parsed_region_chan->chanpwr[i].pwr; } } if (flag) { domaininfo->subband[nr_subband].firstchan = firstchan; domaininfo->subband[nr_subband].nrchan = nr_parsedchan; domaininfo->subband[nr_subband].maxtxpwr = maxpwr; nr_subband++; } domaininfo->nr_subband = nr_subband; lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband); lbs_deb_hex(LBS_DEB_11D, "domaininfo", (char *)domaininfo, COUNTRY_CODE_LEN + 1 + sizeof(struct ieeetypes_subbandset) * nr_subband); return 0;}/** * @brief This function generates parsed_region_chan from Domain Info learned from AP/IBSS * @param region_chan pointer to struct region_channel * @param *parsed_region_chan pointer to parsed_region_chan_11d * @return N/A*/static void wlan_generate_parsed_region_chan_11d(struct region_channel * region_chan, struct parsed_region_chan_11d * parsed_region_chan){ u8 i; struct chan_freq_power *cfp; if (region_chan == NULL) { lbs_deb_11d("region_chan is NULL\n"); return; } cfp = region_chan->CFP; if (cfp == NULL) { lbs_deb_11d("cfp is NULL \n"); return; } parsed_region_chan->band = region_chan->band; parsed_region_chan->region = region_chan->region; memcpy(parsed_region_chan->countrycode, wlan_code_2_region(region_chan->region), COUNTRY_CODE_LEN); lbs_deb_11d("region 0x%x, band %d\n", parsed_region_chan->region, parsed_region_chan->band); for (i = 0; i < region_chan->nrcfp; i++, cfp++) { parsed_region_chan->chanpwr[i].chan = cfp->channel; parsed_region_chan->chanpwr[i].pwr = cfp->maxtxpower; lbs_deb_11d("chan %d, pwr %d\n", parsed_region_chan->chanpwr[i].chan, parsed_region_chan->chanpwr[i].pwr); } parsed_region_chan->nr_chan = region_chan->nrcfp; lbs_deb_11d("nrchan %d\n", parsed_region_chan->nr_chan); return;}/** * @brief generate parsed_region_chan from Domain Info learned from AP/IBSS * @param region region ID * @param band band * @param chan chan * @return TRUE;FALSE*/static u8 wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan){ struct chan_freq_power *cfp; int cfp_no; u8 idx; int ret = 0; lbs_deb_enter(LBS_DEB_11D); cfp = libertas_get_region_cfp_table(region, band, &cfp_no); if (cfp == NULL) return 0; for (idx = 0; idx < cfp_no; idx++) { if (chan == (cfp + idx)->channel) { /* If Mrvl Chip Supported? */ if ((cfp + idx)->unsupported) { ret = 0; } else { ret = 1; } goto done; } } /*chan is not in the region table */done: lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); return ret;}/** * @brief This function checks if chan txpwr is learned from AP/IBSS * @param chan chan number * @param parsed_region_chan pointer to parsed_region_chan_11d * @return 0*/static int parse_domain_info_11d(struct ieeetypes_countryinfofullset* countryinfo, u8 band, struct parsed_region_chan_11d * parsed_region_chan){ u8 nr_subband, nrchan; u8 lastchan, firstchan; u8 region; u8 curchan = 0; u8 idx = 0; /*chan index in parsed_region_chan */ u8 j, i; lbs_deb_enter(LBS_DEB_11D); /*validation Rules: 1. valid region Code 2. First Chan increment 3. channel range no overlap 4. channel is valid? 5. channel is supported by region? 6. Others */ lbs_deb_hex(LBS_DEB_11D, "countryinfo", (u8 *) countryinfo, 30); if ((*(countryinfo->countrycode)) == 0 || (countryinfo->len <= COUNTRY_CODE_LEN)) { /* No region Info or Wrong region info: treat as No 11D info */ goto done; } /*Step1: check region_code */ parsed_region_chan->region = region = wlan_region_2_code(countryinfo->countrycode); lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region); lbs_deb_hex(LBS_DEB_11D, "countrycode", (char *)countryinfo->countrycode, COUNTRY_CODE_LEN); parsed_region_chan->band = band; memcpy(parsed_region_chan->countrycode, countryinfo->countrycode, COUNTRY_CODE_LEN);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -