📄 wlan_11d.c
字号:
/*
* File: wlan_11d.c
*/
#include "include.h"
#define TX_PWR_DEFAULT 10
/* Following 2 structure defines the supported channels */
CHANNEL_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}
};
CHANNEL_FREQ_POWER channel_freq_power_UN_AJ[] = {
{8, 5040, TX_PWR_DEFAULT},
{12, 5060, TX_PWR_DEFAULT},
{16, 5080, TX_PWR_DEFAULT},
{34, 5170, TX_PWR_DEFAULT},
{38, 5190, TX_PWR_DEFAULT},
{42, 5210, TX_PWR_DEFAULT},
{46, 5230, TX_PWR_DEFAULT},
{36, 5180, TX_PWR_DEFAULT},
{40, 5200, TX_PWR_DEFAULT},
{44, 5220, TX_PWR_DEFAULT},
{48, 5240, TX_PWR_DEFAULT},
{52, 5260, TX_PWR_DEFAULT},
{56, 5280, TX_PWR_DEFAULT},
{60, 5300, TX_PWR_DEFAULT},
{64, 5320, TX_PWR_DEFAULT},
{100, 5500, TX_PWR_DEFAULT},
{104, 5520, TX_PWR_DEFAULT},
{108, 5540, TX_PWR_DEFAULT},
{112, 5560, TX_PWR_DEFAULT},
{116, 5580, TX_PWR_DEFAULT},
{120, 5600, TX_PWR_DEFAULT},
{124, 5620, TX_PWR_DEFAULT},
{128, 5640, TX_PWR_DEFAULT},
{132, 5660, TX_PWR_DEFAULT},
{136, 5680, TX_PWR_DEFAULT},
{140, 5700, TX_PWR_DEFAULT},
{149, 5745, TX_PWR_DEFAULT},
{153, 5765, TX_PWR_DEFAULT},
{157, 5785, TX_PWR_DEFAULT},
{161, 5805, TX_PWR_DEFAULT},
{165, 5825, TX_PWR_DEFAULT},
/* {240, 4920, TX_PWR_DEFAULT},
{244, 4940, TX_PWR_DEFAULT},
{248, 4960, TX_PWR_DEFAULT},
{252, 4980, TX_PWR_DEFAULT},
channels for 11J JP 10M channel gap */
};
static region_code_mapping_t 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 */
};
u8 wlan_region_2_code( char *region )
/* Convert Region string to code integer*/
{
int i;
int size = sizeof(region_code_mapping)/sizeof(region_code_mapping_t);
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);
}
char *wlan_code_2_region( u8 code )
/*Convert interger code to region string*/
{
int i;
int size =sizeof(region_code_mapping)/ sizeof(region_code_mapping_t);
for ( i=0; i< size; i++ ) {
if ( region_code_mapping[i].code == code )
return (region_code_mapping[i].region);
}
return NULL;
}
u32 chan_2_freq ( u16 chan, u8 band )
{
CHANNEL_FREQ_POWER *cf;
u8 cnt;
int i;
ENTER();
#ifdef MULTI_BANDS
if ( band & BAND_A ) {
cf =channel_freq_power_UN_AJ;
cnt = sizeof(channel_freq_power_UN_AJ)/sizeof(CHANNEL_FREQ_POWER);
}
else
#endif
{
cf = channel_freq_power_UN_BG;
cnt = sizeof(channel_freq_power_UN_BG)/sizeof(CHANNEL_FREQ_POWER);
}
for ( i=0; i< cnt; i++ ) {
if ( chan == cf[i].Channel ) {
LEAVE();
return cf[i].Freq;
}
}
LEAVE();
return 0;
}
int wlan_generate_domain_info_11d(
parsed_region_chan_11d_t * parsed_region_chan,
wlan_802_11d_domain_reg_t *domaininfo)
/*generate domaininfo from parsed_region_chan*/
{
u8 NoOfSubband =0;
u8 NoOfChan = parsed_region_chan->NoOfChan;
u8 NoOfParsedChan =0;
u8 firstChan=0, nextChan=0, maxPwr=0;
int i, flag =0;
ENTER();
memcpy( domaininfo->CountryCode, parsed_region_chan->CountryCode,
COUNTRY_CODE_LEN);
PRINTK2("11D:NoOfChan=%d\n",NoOfChan );
HEXDUMP( "11D:parsed_region_chan:", (char *)parsed_region_chan,
sizeof(parsed_region_chan_11d_t) );
for ( i=0; i<NoOfChan; i++ ) {
if ( !flag ) {
flag = 1;
nextChan = firstChan = parsed_region_chan->chanPwr[i].chan;
maxPwr = parsed_region_chan->chanPwr[i].pwr;
NoOfParsedChan = 1;
continue;
}
if ( parsed_region_chan->chanPwr[i].chan == nextChan+1 &&
parsed_region_chan->chanPwr[i].pwr == maxPwr ) {
nextChan++;
NoOfParsedChan++;
}
else {
domaininfo->Subband[NoOfSubband].FirstChan = firstChan;
domaininfo->Subband[NoOfSubband].NoOfChan = NoOfParsedChan;
domaininfo->Subband[NoOfSubband].MaxTxPwr = maxPwr;
NoOfSubband++;
nextChan = firstChan = parsed_region_chan->chanPwr[i].chan;
maxPwr = parsed_region_chan->chanPwr[i].pwr;
}
}
if( flag ) {
domaininfo->Subband[NoOfSubband].FirstChan = firstChan;
domaininfo->Subband[NoOfSubband].NoOfChan = NoOfParsedChan;
domaininfo->Subband[NoOfSubband].MaxTxPwr = maxPwr;
NoOfSubband++;
}
domaininfo->NoOfSubband = NoOfSubband;
PRINTK2("NoOfSubband=%x\n", domaininfo->NoOfSubband);
HEXDUMP( "11D:domaininfo:", (char *)domaininfo,
COUNTRY_CODE_LEN+ 1 +
sizeof(IEEEtypes_SubbandSet_t)*NoOfSubband );
LEAVE();
return 0;
}
void wlan_generate_parsed_region_chan_11d(
REGION_CHANNEL *region_chan,
parsed_region_chan_11d_t *parsed_region_chan )
/*generate parsed_region_chan from Domain Info learned from AP/IBSS*/
{
int i;
CHANNEL_FREQ_POWER *cfp;
ENTER();
if( region_chan ==NULL ) {
PRINTK2("11D: region_chan is NULL\n");
return;
}
cfp = region_chan->CFP;
if( cfp ==NULL ) {
PRINTK2("11D: cfp equal 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);
PRINTK2("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;
PRINTK("11D: Chan[%d] Pwr[%d]\n", parsed_region_chan->chanPwr[i].chan,
parsed_region_chan->chanPwr[i].pwr );
}
parsed_region_chan->NoOfChan = region_chan->NrCFP;
PRINTK2("11D: NoOfChan[%d]\n", parsed_region_chan->NoOfChan);
LEAVE();
return;
}
static u8 wlan_get_chan_11d( u8 band, int firstChan, int NoOfChan )
/*find the NoOfChan-th chan after the firstChan*/
{
int i;
CHANNEL_FREQ_POWER *cfp;
int cfp_no;
ENTER();
/*get chan list table*/
#ifdef MULTI_BANDS
if (band & (BAND_B | BAND_G))
#endif
{
cfp =channel_freq_power_UN_BG;
cfp_no = sizeof(channel_freq_power_UN_BG)/
sizeof(CHANNEL_FREQ_POWER);
}
#ifdef MULTI_BANDS
else {
if (band & BAND_A) {
cfp =channel_freq_power_UN_AJ;
cfp_no = sizeof(channel_freq_power_UN_AJ)/
sizeof(CHANNEL_FREQ_POWER);
}
else {
PRINTK2("Wrong Band[%d\n", band );
return 0;
}
}
#endif
/*If firstChan is in the chan list */
for ( i=0; i<cfp_no; i++ ) {
if( (cfp+i)->Channel == firstChan ) {
PRINTK2("firstChan found\n");
break;
}
}
/*if beyond the boundary*/
if ( i<cfp_no ) {
if( i+NoOfChan < cfp_no )
return (cfp+i+NoOfChan)->Channel;
else
return (cfp+cfp_no-1)->Channel;
}
LEAVE();
return 0;
}
extern CHANNEL_FREQ_POWER *wlan_get_region_cfp_table( u8 region,
u8 band, int * cfp_no);
BOOLEAN wlan_region_chan_supported_11d( u8 region, u8 band, u8 chan )
/*check if chan is supported in the region*/
{
CHANNEL_FREQ_POWER *cfp;
int cfp_no;
int idx;
ENTER();
if ( (cfp= wlan_get_region_cfp_table(region, band, &cfp_no)) == NULL ) {
return FALSE;
}
for ( idx=0; idx < cfp_no; idx++ ) {
if( chan == (cfp+idx)->Channel ) {
/* If Mrvl Chip Supported? */
if( (cfp+idx)->Unsupported ) {
return FALSE;
}
else {
return TRUE;
}
}
}
/*chan is not in the region table*/
LEAVE();
return FALSE;
}
int wlan_parse_domain_info_11d(
IEEEtypes_CountryInfoFullSet_t *CountryInfo, u8 band,
parsed_region_chan_11d_t * parsed_region_chan )
/*generate parsed_region_chan from CountryInfo*/
/*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
*/
{
int NoOfSubband, NoOfChan;
int lastChan, firstChan, curChan;
u8 region;
u8 idx =0; /*chan index in parsed_region_chan*/
int j, i;
ENTER();
HEXDUMP("CountryInfo:", (char *)CountryInfo, 30 );
if( (*(CountryInfo->CountryCode))==0 || (CountryInfo->Len <= COUNTRY_CODE_LEN ) ){
/* No region Info or Wrong region info: treat as No 11D info*/
LEAVE();
return WLAN_STATUS_SUCCESS;
}
/*Step1: check region_code*/
parsed_region_chan->region = region =
wlan_region_2_code(CountryInfo->CountryCode);
PRINTK2("regioncode=%x\n",(int)parsed_region_chan->region);
HEXDUMP("CountryCode:", (char *)CountryInfo->CountryCode, COUNTRY_CODE_LEN);
parsed_region_chan->band = band;
memcpy( parsed_region_chan->CountryCode, CountryInfo->CountryCode,
COUNTRY_CODE_LEN);
NoOfSubband = (CountryInfo->Len - COUNTRY_CODE_LEN)/
sizeof(IEEEtypes_SubbandSet_t);
for ( j=0, lastChan=0; j<NoOfSubband; j++ ) {
/*Step2&3. Check First Chan Num increment and no overlap*/
if ( CountryInfo->Subband[j].FirstChan <= lastChan ) {
PRINTK("11D: Chan[%d>%d] Overlap\n",
CountryInfo->Subband[j].FirstChan, lastChan );
continue;
/*Skip the overlaped triplets
LEAVE();
return WLAN_STATUS_FAILURE;
*/
}
firstChan = CountryInfo->Subband[j].FirstChan;
NoOfChan = CountryInfo->Subband[j].NoOfChan;
/*Copy to parsed_region_chan*/
for ( i = 0; idx<MAX_NO_OF_CHAN && i< NoOfChan; i++ ) {
/*step4: channel is supported?*/
curChan = wlan_get_chan_11d( band, firstChan, i);
PRINTK2("firstChan[%d], i[%d] band[%d] curChan[%d]\n",
firstChan, i, band, curChan);
/* Chan is not found in UN table*/
if( curChan == 0 || curChan == lastChan ) {
break;
}
lastChan = curChan;
/*step5: Check if curChan is supported by mrvl in region*/
if ( wlan_region_chan_supported_11d( region, band, curChan) ) {
parsed_region_chan->chanPwr[idx].chan = curChan;
parsed_region_chan->chanPwr[idx].pwr =
CountryInfo->Subband[j].MaxTxPwr;
idx++;
}
else {
/*not supported and ignore the chan*/
PRINTK("11D:i[%d] chan[%d] unsupported in region[%x] band[%d]\n",
i, curChan, region, band );
}
}
/*Step6: Add other checking if any*/
}
parsed_region_chan->NoOfChan = idx;
PRINTK2("NoOfChan=%x\n", parsed_region_chan->NoOfChan );
HEXDUMP( "11D:parsed_region_chan:", (char *)parsed_region_chan,
2 + COUNTRY_CODE_LEN +
sizeof(parsed_region_chan_11d_t)*idx );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -