/* * Copyright (c) 2007-2008 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "cprecomp.h" #include "ratectrl.h" #include "../hal/hpreg.h" /* TODO : change global variable to constant */ u8_t zgWpaRadiusOui[] = { 0x00, 0x50, 0xf2, 0x01 }; u8_t zgWpaAesOui[] = { 0x00, 0x50, 0xf2, 0x04 }; u8_t zgWpa2RadiusOui[] = { 0x00, 0x0f, 0xac, 0x01 }; u8_t zgWpa2AesOui[] = { 0x00, 0x0f, 0xac, 0x04 }; const u16_t zcCwTlb[16] = { 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 4095, 4095, 4095}; void zfStaStartConnectCb(zdev_t* dev); /************************************************************************/ /* */ /* FUNCTION DESCRIPTION zfStaPutApIntoBlockingList */ /* Put AP into blocking AP list. */ /* */ /* INPUTS */ /* dev : device pointer */ /* bssid : AP's BSSID */ /* weight : weight of AP */ /* */ /* OUTPUTS */ /* none */ /* */ /* AUTHOR */ /* Stephen Chen Atheros Communications, INC. 2006.12 */ /* */ /************************************************************************/ void zfStaPutApIntoBlockingList(zdev_t* dev, u8_t* bssid, u8_t weight) { u16_t i, j; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); if (weight > 0) { zmw_enter_critical_section(dev); /*Find same bssid entry first*/ for (i=0; ista.blockingApList[i].addr[j]!= bssid[j]) { break; } } if(j==6) { break; } } /*This bssid doesn't have old record.Find an empty entry*/ if (i == ZM_MAX_BLOCKING_AP_LIST_SIZE) { for (i=0; ista.blockingApList[i].weight == 0) { break; } } } /* If the list is full, pick one entry for replacement */ if (i == ZM_MAX_BLOCKING_AP_LIST_SIZE) { i = bssid[5] & (ZM_MAX_BLOCKING_AP_LIST_SIZE-1); } /* Update AP address and weight */ for (j=0; j<6; j++) { wd->sta.blockingApList[i].addr[j] = bssid[j]; } wd->sta.blockingApList[i].weight = weight; zmw_leave_critical_section(dev); } return; } /************************************************************************/ /* */ /* FUNCTION DESCRIPTION zfStaIsApInBlockingList */ /* Is AP in blocking list. */ /* */ /* INPUTS */ /* dev : device pointer */ /* bssid : AP's BSSID */ /* */ /* OUTPUTS */ /* TRUE : AP in blocking list */ /* FALSE : AP not in blocking list */ /* */ /* AUTHOR */ /* Stephen Chen Atheros Communications, INC. 2006.12 */ /* */ /************************************************************************/ u16_t zfStaIsApInBlockingList(zdev_t* dev, u8_t* bssid) { u16_t i, j; zmw_get_wlan_dev(dev); //zmw_declare_for_critical_section(); //zmw_enter_critical_section(dev); for (i=0; ista.blockingApList[i].weight != 0) { for (j=0; j<6; j++) { if (wd->sta.blockingApList[i].addr[j] != bssid[j]) { break; } } if (j == 6) { //zmw_leave_critical_section(dev); return TRUE; } } } //zmw_leave_critical_section(dev); return FALSE; } /************************************************************************/ /* */ /* FUNCTION DESCRIPTION zfStaRefreshBlockList */ /* Is AP in blocking list. */ /* */ /* INPUTS */ /* dev : device pointer */ /* flushFlag : flush whole blocking list */ /* */ /* OUTPUTS */ /* none */ /* */ /* AUTHOR */ /* Stephen Chen Atheros Communications, INC. 2006.12 */ /* */ /************************************************************************/ void zfStaRefreshBlockList(zdev_t* dev, u16_t flushFlag) { u16_t i; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); zmw_enter_critical_section(dev); for (i=0; ista.blockingApList[i].weight != 0) { if (flushFlag != 0) { wd->sta.blockingApList[i].weight = 0; } else { wd->sta.blockingApList[i].weight--; } } } zmw_leave_critical_section(dev); return; } /************************************************************************/ /* */ /* FUNCTION DESCRIPTION zfStaConnectFail */ /* Handle Connect failure. */ /* */ /* INPUTS */ /* dev : device pointer */ /* bssid : BSSID */ /* reason : reason of failure */ /* */ /* OUTPUTS */ /* none */ /* */ /* AUTHOR */ /* Stephen Chen Atheros Communications, INC. 2006.12 */ /* */ /************************************************************************/ void zfStaConnectFail(zdev_t* dev, u16_t reason, u16_t* bssid, u8_t weight) { zmw_get_wlan_dev(dev); /* Change internal state */ zfChangeAdapterState(dev, ZM_STA_STATE_DISCONNECT); /* Improve WEP/TKIP performace with HT AP, detail information please look bug#32495 */ //zfHpSetTTSIFSTime(dev, 0x8); /* Notify wrapper of connection status changes */ if (wd->zfcbConnectNotify != NULL) { wd->zfcbConnectNotify(dev, reason, bssid); } /* Put AP into internal blocking list */ zfStaPutApIntoBlockingList(dev, (u8_t *)bssid, weight); /* Issue another SCAN */ if ( wd->sta.bAutoReconnect ) { zm_debug_msg0("Start internal scan..."); zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL); zfScanMgrScanStart(dev, ZM_SCAN_MGR_SCAN_INTERNAL); } } u8_t zfiWlanIBSSGetPeerStationsCount(zdev_t* dev) { zmw_get_wlan_dev(dev); return wd->sta.oppositeCount; } u8_t zfiWlanIBSSIteratePeerStations(zdev_t* dev, u8_t numToIterate, zfpIBSSIteratePeerStationCb callback, void *ctx) { u8_t oppositeCount; u8_t i; u8_t index = 0; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); zmw_enter_critical_section(dev); oppositeCount = wd->sta.oppositeCount; if ( oppositeCount > numToIterate ) { oppositeCount = numToIterate; } for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++) { if ( oppositeCount == 0 ) { break; } if ( wd->sta.oppositeInfo[i].valid == 0 ) { continue; } callback(dev, &wd->sta.oppositeInfo[i], ctx, index++); oppositeCount--; } zmw_leave_critical_section(dev); return index; } s8_t zfStaFindFreeOpposite(zdev_t* dev, u16_t *sa, int *pFoundIdx) { int oppositeCount; int i; zmw_get_wlan_dev(dev); oppositeCount = wd->sta.oppositeCount; for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++) { if ( oppositeCount == 0 ) { break; } if ( wd->sta.oppositeInfo[i].valid == 0 ) { continue; } oppositeCount--; if ( zfMemoryIsEqual((u8_t*) sa, wd->sta.oppositeInfo[i].macAddr, 6) ) { //wd->sta.oppositeInfo[i].aliveCounter++; wd->sta.oppositeInfo[i].aliveCounter = ZM_IBSS_PEER_ALIVE_COUNTER; /* it is already stored */ return 1; } } // Check if there's still space for new comer if ( wd->sta.oppositeCount == ZM_MAX_OPPOSITE_COUNT ) { return -1; } // Find an unused slot for new peer station for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++) { if ( wd->sta.oppositeInfo[i].valid == 0 ) { break; } } *pFoundIdx = i; return 0; } s8_t zfStaFindOppositeByMACAddr(zdev_t* dev, u16_t *sa, u8_t *pFoundIdx) { u32_t oppositeCount; u32_t i; zmw_get_wlan_dev(dev); oppositeCount = wd->sta.oppositeCount; for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++) { if ( oppositeCount == 0 ) { break; } if ( wd->sta.oppositeInfo[i].valid == 0 ) { continue; } oppositeCount--; if ( zfMemoryIsEqual((u8_t*) sa, wd->sta.oppositeInfo[i].macAddr, 6) ) { *pFoundIdx = (u8_t)i; return 0; } } *pFoundIdx = 0; return 1; } static void zfStaInitCommonOppositeInfo(zdev_t* dev, int i) { zmw_get_wlan_dev(dev); /* set the default rate to the highest rate */ wd->sta.oppositeInfo[i].valid = 1; wd->sta.oppositeInfo[i].aliveCounter = ZM_IBSS_PEER_ALIVE_COUNTER; wd->sta.oppositeCount++; #ifdef ZM_ENABLE_IBSS_WPA2PSK /* Set parameters for new opposite peer station !!! */ wd->sta.oppositeInfo[i].camIdx = 0xff; // Not set key in this location wd->sta.oppositeInfo[i].pkInstalled = 0; wd->sta.oppositeInfo[i].wpaState = ZM_STA_WPA_STATE_INIT ; // No encryption #endif } int zfStaSetOppositeInfoFromBSSInfo(zdev_t* dev, struct zsBssInfo* pBssInfo) { int i; u8_t* dst; u16_t sa[3]; int res; u32_t oneTxStreamCap; zmw_get_wlan_dev(dev); zfMemoryCopy((u8_t*) sa, pBssInfo->macaddr, 6); res = zfStaFindFreeOpposite(dev, sa, &i); if ( res != 0 ) { goto zlReturn; } dst = wd->sta.oppositeInfo[i].macAddr; zfMemoryCopy(dst, (u8_t *)sa, 6); oneTxStreamCap = (zfHpCapability(dev) & ZM_HP_CAP_11N_ONE_TX_STREAM); if (pBssInfo->extSupportedRates[1] != 0) { /* TODO : Handle 11n */ if (pBssInfo->frequency < 3000) { /* 2.4GHz */ if (pBssInfo->EnableHT == 1) zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 1, pBssInfo->SG40); else zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 1, pBssInfo->SG40); } else { /* 5GHz */ if (pBssInfo->EnableHT == 1) zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 0, pBssInfo->SG40); else zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 0, pBssInfo->SG40); } } else { /* TODO : Handle 11n */ if (pBssInfo->frequency < 3000) { /* 2.4GHz */ if (pBssInfo->EnableHT == 1) zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 1, pBssInfo->SG40); else zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 0, 1, pBssInfo->SG40); } else { /* 5GHz */ if (pBssInfo->EnableHT == 1) zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 0, pBssInfo->SG40); else zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 0, pBssInfo->SG40); } } zfStaInitCommonOppositeInfo(dev, i); zlReturn: return 0; } int zfStaSetOppositeInfoFromRxBuf(zdev_t* dev, zbuf_t* buf) { int i; u8_t* dst; u16_t sa[3]; int res = 0; u16_t offset; u8_t bSupportExtRate; u32_t rtsctsRate = 0xffffffff; /* CTS:OFDM 6M, RTS:OFDM 6M */ u32_t oneTxStreamCap; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); sa[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET); sa[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+2); sa[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+4); zmw_enter_critical_section(dev); res = zfStaFindFreeOpposite(dev, sa, &i); if ( res != 0 ) { goto zlReturn; } dst = wd->sta.oppositeInfo[i].macAddr; zfCopyFromRxBuffer(dev, buf, dst, ZM_WLAN_HEADER_A2_OFFSET, 6); if ( (wd->sta.currentFrequency < 3000) && !(wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) ) { bSupportExtRate = 0; } else { bSupportExtRate = 1; } if ( (bSupportExtRate == 1) && (wd->sta.currentFrequency < 3000) && (wd->wlanMode == ZM_MODE_IBSS) && (wd->wfc.bIbssGMode == 0) ) { bSupportExtRate = 0; } wd->sta.connection_11b = 0; oneTxStreamCap = (zfHpCapability(dev) & ZM_HP_CAP_11N_ONE_TX_STREAM); if ( ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE)) != 0xffff) && (bSupportExtRate == 1) ) { /* TODO : Handle 11n */ if (wd->sta.currentFrequency < 3000) { /* 2.4GHz */ if (wd->sta.EnableHT == 1) { //11ng zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 1, wd->sta.SG40); } else { //11g zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 1, wd->sta.SG40); } rtsctsRate = 0x00001bb; /* CTS:CCK 1M, RTS:OFDM 6M */ } else { /* 5GHz */ if (wd->sta.EnableHT == 1) { //11na zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 0, wd->sta.SG40); } else { //11a zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 0, wd->sta.SG40); } rtsctsRate = 0x10b01bb; /* CTS:OFDM 6M, RTS:OFDM 6M */ } } else { /* TODO : Handle 11n */ if (wd->sta.currentFrequency < 3000) { /* 2.4GHz */ if (wd->sta.EnableHT == 1) { //11ng zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 1, wd->sta.SG40); rtsctsRate = 0x00001bb; /* CTS:CCK 1M, RTS:OFDM 6M */ } else { //11b zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 0, 1, wd->sta.SG40); rtsctsRate = 0x0; /* CTS:CCK 1M, RTS:CCK 1M */ wd->sta.connection_11b = 1; } } else { /* 5GHz */ if (wd->sta.EnableHT == 1) { //11na zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, (oneTxStreamCap!=0)?3:2, 0, wd->sta.SG40); } else { //11a zfRateCtrlInitCell(dev, &wd->sta.oppositeInfo[i].rcCell, 1, 0, wd->sta.SG40); } rtsctsRate = 0x10b01bb; /* CTS:OFDM 6M, RTS:OFDM 6M */ } } zfStaInitCommonOppositeInfo(dev, i); zlReturn: zmw_leave_critical_section(dev); if (rtsctsRate != 0xffffffff) { zfHpSetRTSCTSRate(dev, rtsctsRate); } return res; } void zfStaProtErpMonitor(zdev_t* dev, zbuf_t* buf) { u16_t offset; u8_t erp; u8_t bssid[6]; zmw_get_wlan_dev(dev); if ( (wd->wlanMode == ZM_MODE_INFRASTRUCTURE)&&(zfStaIsConnected(dev)) ) { ZM_MAC_WORD_TO_BYTE(wd->sta.bssid, bssid); if (zfRxBufferEqualToStr(dev, buf, bssid, ZM_WLAN_HEADER_A2_OFFSET, 6)) { if ( (offset=zfFindElement(dev, buf, ZM_WLAN_EID_ERP)) != 0xffff ) { erp = zmw_rx_buf_readb(dev, buf, offset+2); if ( erp & ZM_BIT_1 ) { //zm_debug_msg0("protection mode on"); if (wd->sta.bProtectionMode == FALSE) { wd->sta.bProtectionMode = TRUE; zfHpSetSlotTime(dev, 0); } } else { //zm_debug_msg0("protection mode off"); if (wd->sta.bProtectionMode == TRUE) { wd->sta.bProtectionMode = FALSE; zfHpSetSlotTime(dev, 1); } } } } //Check the existence of Non-N AP //Follow the check the "pBssInfo->EnableHT" if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY)) != 0xffff) {} else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTCAPABILITY)) != 0xffff) {} else {wd->sta.NonNAPcount++;} } } void zfStaUpdateWmeParameter(zdev_t* dev, zbuf_t* buf) { u16_t tmp; u16_t aifs[5]; u16_t cwmin[5]; u16_t cwmax[5]; u16_t txop[5]; u8_t acm; u8_t ac; u16_t len; u16_t i; u16_t offset; u8_t rxWmeParameterSetCount; zmw_get_wlan_dev(dev); /* Update if WME parameter set count is changed */ /* If connect to WME AP */ if (wd->sta.wmeConnected != 0) { /* Find WME parameter element */ if ((offset = zfFindWifiElement(dev, buf, 2, 1)) != 0xffff) { if ((len = zmw_rx_buf_readb(dev, buf, offset+1)) >= 7) { rxWmeParameterSetCount=zmw_rx_buf_readb(dev, buf, offset+8); if (rxWmeParameterSetCount != wd->sta.wmeParameterSetCount) { zm_msg0_mm(ZM_LV_0, "wmeParameterSetCount changed!"); wd->sta.wmeParameterSetCount = rxWmeParameterSetCount; /* retrieve WME parameter and update TxQ parameters */ acm = 0xf; for (i=0; i<4; i++) { if (len >= (8+(i*4)+4)) { tmp=zmw_rx_buf_readb(dev, buf, offset+10+i*4); ac = (tmp >> 5) & 0x3; if ((tmp & 0x10) == 0) { acm &= (~(1<> 4)]; txop[ac]=zmw_rx_buf_readh(dev, buf, offset+12+i*4); } } if ((acm & 0x4) != 0) { cwmin[2] = cwmin[0]; cwmax[2] = cwmax[0]; aifs[2] = aifs[0]; txop[2] = txop[0]; } if ((acm & 0x8) != 0) { cwmin[3] = cwmin[2]; cwmax[3] = cwmax[2]; aifs[3] = aifs[2]; txop[3] = txop[2]; } cwmin[4] = 3; cwmax[4] = 7; aifs[4] = 28; if ((cwmin[2]+aifs[2]) > ((cwmin[0]+aifs[0])+1)) { wd->sta.ac0PriorityHigherThanAc2 = 1; } else { wd->sta.ac0PriorityHigherThanAc2 = 0; } zfHpUpdateQosParameter(dev, cwmin, cwmax, aifs, txop); } } } } //if (wd->sta.wmeConnected != 0) } /* process 802.11h Dynamic Frequency Selection */ void zfStaUpdateDot11HDFS(zdev_t* dev, zbuf_t* buf) { zmw_get_wlan_dev(dev); /* Channel Switch Announcement Element Format +------+----------+------+-------------------+------------------+--------------------+ |Format|Element ID|Length|Channel Switch Mode|New Channel Number|Channel Switch Count| +------+----------+------+-------------------+------------------+--------------------+ |Bytes | 1 | 1 | 1 | 1 | 1 | +------+----------+------+-------------------+------------------+--------------------+ |Value | 37 | 3 | 0 or 1 |unsigned integer |unsigned integer | +------+----------+------+-------------------+------------------+--------------------+ */ //u8_t length, channel, is5G; u16_t offset; /* get EID(Channel Switch Announcement) */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_CHANNEL_SWITCH_ANNOUNCE)) == 0xffff ) { //zm_debug_msg0("EID(Channel Switch Announcement) not found"); return; } else if ( zmw_rx_buf_readb(dev, buf, offset+1) == 0x3 ) { zm_debug_msg0("EID(Channel Switch Announcement) found"); //length = zmw_rx_buf_readb(dev, buf, offset+1); //zfCopyFromRxBuffer(dev, buf, pBssInfo->supportedRates, offset, length+2); //Chanell Switch Mode set to 1, driver should disable transmit immediate //we do this by poll CCA high if (zmw_rx_buf_readb(dev, buf, offset+2) == 0x1 ) { //use ZM_OID_INTERNAL_WRITE,ZM_CMD_RESET to notice firmware flush quene and stop dma, //then restart rx dma but not tx dma if (wd->sta.DFSDisableTx != TRUE) { /* TODO : zfHpResetTxRx would cause Rx hang */ //zfHpResetTxRx(dev); wd->sta.DFSDisableTx = TRUE; /* Trgger Rx DMA */ zfHpStartRecv(dev); } //Adapter->ZD80211HSetting.DisableTxBy80211H=TRUE; //AcquireCtrOfPhyReg(Adapter); //ZD1205_WRITE_REGISTER(Adapter,CR24, 0x0); //ReleaseDoNotSleep(Adapter); } if (zmw_rx_buf_readb(dev, buf, offset+4) <= 0x2 ) { //Channel Switch //if Channel Switch Count = 0 , STA should change channel immediately. //if Channel Switch Count > 0 , STA should change channel after TBTT*count //But it won't be accurate to let driver calculate TBTT*count, and the value of //Channel Switch Count will decrease by one each when continue receving beacon //So we change channel here when we receive count <=2. zfHpDeleteAllowChannel(dev, wd->sta.currentFrequency); wd->frequency = zfChNumToFreq(dev, zmw_rx_buf_readb(dev, buf, offset+3), 0); //zfHpAddAllowChannel(dev, wd->frequency); zm_debug_msg1("CWY - jump to frequency = ", wd->frequency); zfCoreSetFrequency(dev, wd->frequency); wd->sta.DFSDisableTx = FALSE; /* Increase rxBeaconCount to prevent beacon lost */ if (zfStaIsConnected(dev)) { wd->sta.rxBeaconCount = 1 << 6; // 2 times of check would pass } //start tx dma to transmit packet //if (zmw_rx_buf_readb(dev, buf, offset+3) != wd->frequency) //{ // //ZDDbgPrint(("Radar Detect by AP\n")); // zfCoreSetFrequency(); // ProcessRadarDetectEvent(Adapter); // Set_RF_Channel(Adapter, SwRfd->Rfd->RxBuffer[index+3], (UCHAR)Adapter->RF_Mode, 1); // Adapter->CardSetting.Channel = SwRfd->Rfd->RxBuffer[index+3]; // Adapter->SaveChannel = Adapter->CardSetting.Channel; // Adapter->UtilityChannel = Adapter->CardSetting.Channel; //} } } } /* TODO : process 802.11h Transmission Power Control */ void zfStaUpdateDot11HTPC(zdev_t* dev, zbuf_t* buf) { } /* IBSS power-saving mode */ void zfStaIbssPSCheckState(zdev_t* dev, zbuf_t* buf) { u8_t i, frameCtrl; zmw_get_wlan_dev(dev); if ( !zfStaIsConnected(dev) ) { return; } if ( wd->wlanMode != ZM_MODE_IBSS ) { return ; } /* check BSSID */ if ( !zfRxBufferEqualToStr(dev, buf, (u8_t*) wd->sta.bssid, ZM_WLAN_HEADER_A3_OFFSET, 6) ) { return; } frameCtrl = zmw_rx_buf_readb(dev, buf, 1); /* check power management bit */ if ( frameCtrl & ZM_BIT_4 ) { for(i=1; ista.staPSList.entity[i].bUsed ) { continue; } /* check source address */ if ( zfRxBufferEqualToStr(dev, buf, wd->sta.staPSList.entity[i].macAddr, ZM_WLAN_HEADER_A2_OFFSET, 6) ) { return; } } for(i=1; ista.staPSList.entity[i].bUsed ) { wd->sta.staPSList.entity[i].bUsed = TRUE; wd->sta.staPSList.entity[i].bDataQueued = FALSE; break; } } if ( i == ZM_MAX_PS_STA ) { /* STA list is full */ return; } zfCopyFromRxBuffer(dev, buf, wd->sta.staPSList.entity[i].macAddr, ZM_WLAN_HEADER_A2_OFFSET, 6); if ( wd->sta.staPSList.count == 0 ) { // enable ATIM window //zfEnableAtimWindow(dev); } wd->sta.staPSList.count++; } else if ( wd->sta.staPSList.count ) { for(i=1; ista.staPSList.entity[i].bUsed ) { if ( zfRxBufferEqualToStr(dev, buf, wd->sta.staPSList.entity[i].macAddr, ZM_WLAN_HEADER_A2_OFFSET, 6) ) { wd->sta.staPSList.entity[i].bUsed = FALSE; wd->sta.staPSList.count--; if ( wd->sta.staPSList.entity[i].bDataQueued ) { /* send queued data */ } } } } if ( wd->sta.staPSList.count == 0 ) { /* disable ATIM window */ //zfDisableAtimWindow(dev); } } } /* IBSS power-saving mode */ u8_t zfStaIbssPSQueueData(zdev_t* dev, zbuf_t* buf) { u8_t i; u16_t da[3]; zmw_get_wlan_dev(dev); if ( !zfStaIsConnected(dev) ) { return 0; } if ( wd->wlanMode != ZM_MODE_IBSS ) { return 0; } if ( wd->sta.staPSList.count == 0 && wd->sta.powerSaveMode <= ZM_STA_PS_NONE ) { return 0; } /* DA */ #ifdef ZM_ENABLE_NATIVE_WIFI da[0] = zmw_tx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET); da[1] = zmw_tx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET + 2); da[2] = zmw_tx_buf_readh(dev, buf, ZM_WLAN_HEADER_A1_OFFSET + 4); #else da[0] = zmw_tx_buf_readh(dev, buf, 0); da[1] = zmw_tx_buf_readh(dev, buf, 2); da[2] = zmw_tx_buf_readh(dev, buf, 4); #endif if ( ZM_IS_MULTICAST_OR_BROADCAST(da) ) { wd->sta.staPSList.entity[0].bDataQueued = TRUE; wd->sta.ibssPSDataQueue[wd->sta.ibssPSDataCount++] = buf; return 1; } // Unicast packet... for(i=1; ista.staPSList.entity[i].macAddr, (u8_t*) da, 6) ) { wd->sta.staPSList.entity[i].bDataQueued = TRUE; wd->sta.ibssPSDataQueue[wd->sta.ibssPSDataCount++] = buf; return 1; } } #if 0 if ( wd->sta.powerSaveMode > ZM_STA_PS_NONE ) { wd->sta.staPSDataQueue[wd->sta.staPSDataCount++] = buf; return 1; } #endif return 0; } /* IBSS power-saving mode */ void zfStaIbssPSSend(zdev_t* dev) { u8_t i; u16_t bcastAddr[3] = {0xffff, 0xffff, 0xffff}; zmw_get_wlan_dev(dev); if ( !zfStaIsConnected(dev) ) { return ; } if ( wd->wlanMode != ZM_MODE_IBSS ) { return ; } for(i=0; ista.staPSList.entity[i].bDataQueued ) { if ( i == 0 ) { zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ATIM, bcastAddr, 0, 0, 0); } else if ( wd->sta.staPSList.entity[i].bUsed ) { // Send ATIM to prevent the peer to go to sleep zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ATIM, (u16_t*) wd->sta.staPSList.entity[i].macAddr, 0, 0, 0); } wd->sta.staPSList.entity[i].bDataQueued = FALSE; } } for(i=0; ista.ibssPSDataCount; i++) { zfTxSendEth(dev, wd->sta.ibssPSDataQueue[i], 0, ZM_EXTERNAL_ALLOC_BUF, 0); } wd->sta.ibssPrevPSDataCount = wd->sta.ibssPSDataCount; wd->sta.ibssPSDataCount = 0; } void zfStaReconnect(zdev_t* dev) { zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE && wd->wlanMode != ZM_MODE_IBSS ) { return; } if ( (zfStaIsConnected(dev))||(zfStaIsConnecting(dev)) ) { return; } if ( wd->sta.bChannelScan ) { return; } /* Recover zero SSID length */ if ( (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) && (wd->ws.ssidLen == 0)) { zm_debug_msg0("zfStaReconnect: NOT Support!! Set SSID to any BSS"); /* ANY BSS */ zmw_enter_critical_section(dev); wd->sta.ssid[0] = 0; wd->sta.ssidLen = 0; zmw_leave_critical_section(dev); } // RAY: To ensure no TX pending before re-connecting zfFlushVtxq(dev); zfWlanEnable(dev); zfScanMgrScanAck(dev); } void zfStaTimer100ms(zdev_t* dev) { zmw_get_wlan_dev(dev); if ( (wd->tick % 10) == 0 ) { zfPushVtxq(dev); // zfPowerSavingMgrMain(dev); } } void zfStaCheckRxBeacon(zdev_t* dev) { zmw_get_wlan_dev(dev); if (( wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) && (zfStaIsConnected(dev))) { if (wd->beaconInterval == 0) { wd->beaconInterval = 100; } if ( (wd->tick % ((wd->beaconInterval * 10) / ZM_MS_PER_TICK)) == 0 ) { /* Check rxBeaconCount */ if (wd->sta.rxBeaconCount == 0) { if (wd->sta.beaconMissState == 1) { /*notify AP that we left*/ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, wd->sta.bssid, 3, 0, 0); /* Beacon Lost */ zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_BEACON_MISS, wd->sta.bssid, 0); } else { wd->sta.beaconMissState = 1; /* Reset channel */ zfCoreSetFrequencyExV2(dev, wd->frequency, wd->BandWidth40, wd->ExtOffset, NULL, 1); } } else { wd->sta.beaconMissState = 0; } wd->sta.rxBeaconCount = 0; } } } void zfStaCheckConnectTimeout(zdev_t* dev) { zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); if ( wd->wlanMode != ZM_MODE_INFRASTRUCTURE ) { return; } if ( !zfStaIsConnecting(dev) ) { return; } zmw_enter_critical_section(dev); if ( (wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_OPEN)|| (wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_SHARE_1)|| (wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_SHARE_2)|| (wd->sta.connectState == ZM_STA_CONN_STATE_ASSOCIATE) ) { if ( (wd->tick - wd->sta.connectTimer) > ZM_INTERVAL_CONNECT_TIMEOUT ) { if ( wd->sta.connectByReasso ) { wd->sta.failCntOfReasso++; if ( wd->sta.failCntOfReasso > 2 ) { wd->sta.connectByReasso = FALSE; } } wd->sta.connectState = ZM_STA_CONN_STATE_NONE; zm_debug_msg1("connect timeout, state = ", wd->sta.connectState); //zfiWlanDisable(dev); goto failed; } } zmw_leave_critical_section(dev); return; failed: zmw_leave_critical_section(dev); if(wd->sta.authMode == ZM_AUTH_MODE_AUTO) { // Fix some AP not send authentication failed message to sta and lead to connect timeout ! wd->sta.connectTimeoutCount++; } zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_TIMEOUT, wd->sta.bssid, 2); return; } void zfMmStaTimeTick(zdev_t* dev) { zmw_get_wlan_dev(dev); /* airopeek */ if (wd->wlanMode != ZM_MODE_AP && !wd->swSniffer) { if ( wd->tick & 1 ) { zfTimerCheckAndHandle(dev); } zfStaCheckRxBeacon(dev); zfStaTimer100ms(dev); zfStaCheckConnectTimeout(dev); zfPowerSavingMgrMain(dev); } #ifdef ZM_ENABLE_AGGREGATION /* * add by honda */ zfAggScanAndClear(dev, wd->tick); #endif } void zfStaSendBeacon(zdev_t* dev) { zbuf_t* buf; u16_t offset, seq; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); //zm_debug_msg0("\n"); /* TBD : Maximum size of beacon */ if ((buf = zfwBufAllocate(dev, 1024)) == NULL) { zm_debug_msg0("Allocate beacon buffer failed"); return; } offset = 0; /* wlan header */ /* Frame control */ zmw_tx_buf_writeh(dev, buf, offset, 0x0080); offset+=2; /* Duration */ zmw_tx_buf_writeh(dev, buf, offset, 0x0000); offset+=2; /* Address 1 */ zmw_tx_buf_writeh(dev, buf, offset, 0xffff); offset+=2; zmw_tx_buf_writeh(dev, buf, offset, 0xffff); offset+=2; zmw_tx_buf_writeh(dev, buf, offset, 0xffff); offset+=2; /* Address 2 */ zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[0]); offset+=2; zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[1]); offset+=2; zmw_tx_buf_writeh(dev, buf, offset, wd->macAddr[2]); offset+=2; /* Address 3 */ zmw_tx_buf_writeh(dev, buf, offset, wd->sta.bssid[0]); offset+=2; zmw_tx_buf_writeh(dev, buf, offset, wd->sta.bssid[1]); offset+=2; zmw_tx_buf_writeh(dev, buf, offset, wd->sta.bssid[2]); offset+=2; /* Sequence number */ zmw_enter_critical_section(dev); seq = ((wd->mmseq++)<<4); zmw_leave_critical_section(dev); zmw_tx_buf_writeh(dev, buf, offset, seq); offset+=2; /* 24-31 Time Stamp : hardware will fill this field */ offset+=8; /* Beacon Interval */ zmw_tx_buf_writeh(dev, buf, offset, wd->beaconInterval); offset+=2; /* Capability */ zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[0]); zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.capability[1]); /* SSID */ offset = zfStaAddIeSsid(dev, buf, offset); if(wd->frequency <= ZM_CH_G_14) // 2.4 GHz b+g { /* Support Rate */ offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_CCK); /* DS parameter set */ offset = zfMmAddIeDs(dev, buf, offset); offset = zfStaAddIeIbss(dev, buf, offset); if( wd->wfc.bIbssGMode && (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) ) // Only accompany with enabling a mode . { /* ERP Information */ wd->erpElement = 0; offset = zfMmAddIeErp(dev, buf, offset); } /* TODO : country information */ /* RSN */ if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK ) { offset = zfwStaAddIeWpaRsn(dev, buf, offset, ZM_WLAN_FRAME_TYPE_AUTH); } if( wd->wfc.bIbssGMode && (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) ) // Only accompany with enabling a mode . { /* Enable G Mode */ /* Extended Supported Rates */ offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_EXTENDED_RATE, ZM_RATE_SET_OFDM); } } else // 5GHz a { /* Support Rate a Mode */ offset = zfMmAddIeSupportRate(dev, buf, offset, ZM_WLAN_EID_SUPPORT_RATE, ZM_RATE_SET_OFDM); /* DS parameter set */ offset = zfMmAddIeDs(dev, buf, offset); offset = zfStaAddIeIbss(dev, buf, offset); /* TODO : country information */ /* RSN */ if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK ) { offset = zfwStaAddIeWpaRsn(dev, buf, offset, ZM_WLAN_FRAME_TYPE_AUTH); } } if ( wd->wlanMode != ZM_MODE_IBSS ) { /* TODO : Need to check if it is ok */ /* HT Capabilities Info */ offset = zfMmAddHTCapability(dev, buf, offset); /* Extended HT Capabilities Info */ offset = zfMmAddExtendedHTCapability(dev, buf, offset); } if ( wd->sta.ibssAdditionalIESize ) offset = zfStaAddIbssAdditionalIE(dev, buf, offset); /* 1212 : write to beacon fifo */ /* 1221 : write to share memory */ zfHpSendBeacon(dev, buf, offset); /* Free beacon buffer */ //zfwBufFree(dev, buf, 0); } void zfStaSignalStatistic(zdev_t* dev, u8_t SignalStrength, u8_t SignalQuality) //CWYang(+) { zmw_get_wlan_dev(dev); /* Add Your Code to Do Works Like Moving Average Here */ wd->SignalStrength = (wd->SignalStrength * 7 + SignalStrength * 3)/10; wd->SignalQuality = (wd->SignalQuality * 7 + SignalQuality * 3)/10; } struct zsBssInfo* zfStaFindBssInfo(zdev_t* dev, zbuf_t* buf, struct zsWlanProbeRspFrameHeader *pProbeRspHeader) { u8_t i; u8_t j; u8_t k; u8_t isMatched, length, channel; u16_t offset, frequency; struct zsBssInfo* pBssInfo; zmw_get_wlan_dev(dev); if ((pBssInfo = wd->sta.bssList.head) == NULL) { return NULL; } for( i=0; ista.bssList.bssCount; i++ ) { //zm_debug_msg2("check pBssInfo = ", pBssInfo); /* Check BSSID */ for( j=0; j<6; j++ ) { if ( pBssInfo->bssid[j] != pProbeRspHeader->bssid[j] ) { break; } } /* Check SSID */ if (j == 6) { if (pProbeRspHeader->ssid[1] <= 32) { /* compare length and ssid */ isMatched = 1; if((pProbeRspHeader->ssid[1] != 0) && (pBssInfo->ssid[1] != 0)) { for( k=1; kssid[1] + 1; k++ ) { if ( pBssInfo->ssid[k] != pProbeRspHeader->ssid[k] ) { isMatched = 0; break; } } } } else { isMatched = 0; } } else { isMatched = 0; } /* Check channel */ /* Add check channel to solve the bug #31222 */ if (isMatched) { if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_DS)) != 0xffff) { if ((length = zmw_rx_buf_readb(dev, buf, offset+1)) == 1) { channel = zmw_rx_buf_readb(dev, buf, offset+2); if (zfHpIsAllowedChannel(dev, zfChNumToFreq(dev, channel, 0)) == 0) { frequency = 0; } else { frequency = zfChNumToFreq(dev, channel, 0);; } } else { frequency = 0; } } else { frequency = wd->sta.currentFrequency; } if (frequency != 0) { if ( ((frequency > 3000) && (pBssInfo->frequency > 3000)) || ((frequency < 3000) && (pBssInfo->frequency < 3000)) ) { /* redundant */ break; } } } pBssInfo = pBssInfo->next; } if ( i == wd->sta.bssList.bssCount ) { pBssInfo = NULL; } return pBssInfo; } u8_t zfStaInitBssInfo(zdev_t* dev, zbuf_t* buf, struct zsWlanProbeRspFrameHeader *pProbeRspHeader, struct zsBssInfo* pBssInfo, struct zsAdditionInfo* AddInfo, u8_t type) { u8_t length, channel, is5G; u16_t i, offset; u8_t apQosInfo; u16_t eachIElength = 0; u16_t accumulateLen = 0; zmw_get_wlan_dev(dev); if ((type == 1) && ((pBssInfo->flag & ZM_BSS_INFO_VALID_BIT) != 0)) { goto zlUpdateRssi; } /* get SSID */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID)) == 0xffff ) { zm_debug_msg0("EID(SSID) not found"); goto zlError; } length = zmw_rx_buf_readb(dev, buf, offset+1); { u8_t Show_Flag = 0; zfwGetShowZeroLengthSSID(dev, &Show_Flag); if(Show_Flag) { if (length > ZM_MAX_SSID_LENGTH ) { zm_debug_msg0("EID(SSID) is invalid"); goto zlError; } } else { if ( length == 0 || length > ZM_MAX_SSID_LENGTH ) { zm_debug_msg0("EID(SSID) is invalid"); goto zlError; } } } zfCopyFromRxBuffer(dev, buf, pBssInfo->ssid, offset, length+2); /* get DS parameter */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_DS)) != 0xffff ) { length = zmw_rx_buf_readb(dev, buf, offset+1); if ( length != 1 ) { zm_msg0_mm(ZM_LV_0, "Abnormal DS Param Set IE"); goto zlError; } channel = zmw_rx_buf_readb(dev, buf, offset+2); if (zfHpIsAllowedChannel(dev, zfChNumToFreq(dev, channel, 0)) == 0) { goto zlError2; } pBssInfo->frequency = zfChNumToFreq(dev, channel, 0); // auto check pBssInfo->channel = channel; } else { /* DS parameter not found */ pBssInfo->frequency = wd->sta.currentFrequency; pBssInfo->channel = zfChFreqToNum(wd->sta.currentFrequency, &is5G); } /* initialize security type */ pBssInfo->securityType = ZM_SECURITY_TYPE_NONE; /* get macaddr */ for( i=0; i<6; i++ ) { pBssInfo->macaddr[i] = pProbeRspHeader->sa[i]; } /* get bssid */ for( i=0; i<6; i++ ) { pBssInfo->bssid[i] = pProbeRspHeader->bssid[i]; } /* get timestamp */ for( i=0; i<8; i++ ) { pBssInfo->timeStamp[i] = pProbeRspHeader->timeStamp[i]; } /* get beacon interval */ pBssInfo->beaconInterval[0] = pProbeRspHeader->beaconInterval[0]; pBssInfo->beaconInterval[1] = pProbeRspHeader->beaconInterval[1]; /* get capability */ pBssInfo->capability[0] = pProbeRspHeader->capability[0]; pBssInfo->capability[1] = pProbeRspHeader->capability[1]; /* Copy frame body */ offset = 36; // Copy from the start of variable IE pBssInfo->frameBodysize = zfwBufGetSize(dev, buf)-offset; if (pBssInfo->frameBodysize > (ZM_MAX_PROBE_FRAME_BODY_SIZE-1)) { pBssInfo->frameBodysize = ZM_MAX_PROBE_FRAME_BODY_SIZE-1; } accumulateLen = 0; do { eachIElength = zmw_rx_buf_readb(dev, buf, offset + accumulateLen+1) + 2; //Len+(EID+Data) if ( (eachIElength >= 2) && ((accumulateLen + eachIElength) <= pBssInfo->frameBodysize) ) { zfCopyFromRxBuffer(dev, buf, pBssInfo->frameBody+accumulateLen, offset+accumulateLen, eachIElength); accumulateLen+=(u16_t)eachIElength; } else { zm_msg0_mm(ZM_LV_1, "probersp frameBodysize abnormal"); break; } } while(accumulateLen < pBssInfo->frameBodysize); pBssInfo->frameBodysize = accumulateLen; /* get supported rates */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_SUPPORT_RATE)) == 0xffff ) { zm_debug_msg0("EID(supported rates) not found"); goto zlError; } length = zmw_rx_buf_readb(dev, buf, offset+1); if ( length == 0 || length > ZM_MAX_SUPP_RATES_IE_SIZE) { zm_msg0_mm(ZM_LV_0, "Supported rates IE length abnormal"); goto zlError; } zfCopyFromRxBuffer(dev, buf, pBssInfo->supportedRates, offset, length+2); /* get Country information */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_COUNTRY)) != 0xffff ) { length = zmw_rx_buf_readb(dev, buf, offset+1); if (length > ZM_MAX_COUNTRY_INFO_SIZE) { length = ZM_MAX_COUNTRY_INFO_SIZE; } zfCopyFromRxBuffer(dev, buf, pBssInfo->countryInfo, offset, length+2); /* check 802.11d support data */ if (wd->sta.b802_11D) { zfHpGetRegulationTablefromISO(dev, (u8_t *)&pBssInfo->countryInfo, 3); /* only set regulatory one time */ wd->sta.b802_11D = 0; } } /* get ERP information */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_ERP)) != 0xffff ) { pBssInfo->erp = zmw_rx_buf_readb(dev, buf, offset+2); } /* get extended supported rates */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_RATE)) != 0xffff ) { length = zmw_rx_buf_readb(dev, buf, offset+1); if (length > ZM_MAX_SUPP_RATES_IE_SIZE) { zm_msg0_mm(ZM_LV_0, "Extended rates IE length abnormal"); goto zlError; } zfCopyFromRxBuffer(dev, buf, pBssInfo->extSupportedRates, offset, length+2); } else { pBssInfo->extSupportedRates[0] = 0; pBssInfo->extSupportedRates[1] = 0; } /* get WPA IE */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_WPA_IE)) != 0xffff ) { length = zmw_rx_buf_readb(dev, buf, offset+1); if (length > ZM_MAX_IE_SIZE) { length = ZM_MAX_IE_SIZE; } zfCopyFromRxBuffer(dev, buf, pBssInfo->wpaIe, offset, length+2); pBssInfo->securityType = ZM_SECURITY_TYPE_WPA; } else { pBssInfo->wpaIe[1] = 0; } /* get WPS IE */ if ((offset = zfFindWifiElement(dev, buf, 4, 0xff)) != 0xffff) { length = zmw_rx_buf_readb(dev, buf, offset+1); if (length > ZM_MAX_WPS_IE_SIZE ) { length = ZM_MAX_WPS_IE_SIZE; } zfCopyFromRxBuffer(dev, buf, pBssInfo->wscIe, offset, length+2); } else { pBssInfo->wscIe[1] = 0; } /* get SuperG IE */ if ((offset = zfFindSuperGElement(dev, buf, ZM_WLAN_EID_VENDOR_PRIVATE)) != 0xffff) { pBssInfo->apCap |= ZM_SuperG_AP; } /* get XR IE */ if ((offset = zfFindXRElement(dev, buf, ZM_WLAN_EID_VENDOR_PRIVATE)) != 0xffff) { pBssInfo->apCap |= ZM_XR_AP; } /* get RSN IE */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_RSN_IE)) != 0xffff ) { length = zmw_rx_buf_readb(dev, buf, offset+1); if (length > ZM_MAX_IE_SIZE) { length = ZM_MAX_IE_SIZE; } zfCopyFromRxBuffer(dev, buf, pBssInfo->rsnIe, offset, length+2); pBssInfo->securityType = ZM_SECURITY_TYPE_WPA; } else { pBssInfo->rsnIe[1] = 0; } #ifdef ZM_ENABLE_CENC /* get CENC IE */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_CENC_IE)) != 0xffff ) { length = zmw_rx_buf_readb(dev, buf, offset+1); if (length > ZM_MAX_IE_SIZE ) { length = ZM_MAX_IE_SIZE; } zfCopyFromRxBuffer(dev, buf, pBssInfo->cencIe, offset, length+2); pBssInfo->securityType = ZM_SECURITY_TYPE_CENC; pBssInfo->capability[0] &= 0xffef; } else { pBssInfo->cencIe[1] = 0; } #endif //ZM_ENABLE_CENC /* get WME Parameter IE, probe rsp may contain WME parameter element */ //if ( wd->bQoSEnable ) { if ((offset = zfFindWifiElement(dev, buf, 2, 1)) != 0xffff) { apQosInfo = zmw_rx_buf_readb(dev, buf, offset+8) & 0x80; pBssInfo->wmeSupport = 1 | apQosInfo; } else if ((offset = zfFindWifiElement(dev, buf, 2, 0)) != 0xffff) { apQosInfo = zmw_rx_buf_readb(dev, buf, offset+8) & 0x80; pBssInfo->wmeSupport = 1 | apQosInfo; } else { pBssInfo->wmeSupport = 0; } } //CWYang(+) if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY)) != 0xffff) { /* 11n AP */ pBssInfo->EnableHT = 1; if (zmw_rx_buf_readb(dev, buf, offset+1) & 0x02) { pBssInfo->enableHT40 = 1; } else { pBssInfo->enableHT40 = 0; } if (zmw_rx_buf_readb(dev, buf, offset+1) & 0x40) { pBssInfo->SG40 = 1; } else { pBssInfo->SG40 = 0; } } else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTCAPABILITY)) != 0xffff) { /* 11n AP */ pBssInfo->EnableHT = 1; pBssInfo->apCap |= ZM_All11N_AP; if (zmw_rx_buf_readb(dev, buf, offset+2) & 0x02) { pBssInfo->enableHT40 = 1; } else { pBssInfo->enableHT40 = 0; } if (zmw_rx_buf_readb(dev, buf, offset+2) & 0x40) { pBssInfo->SG40 = 1; } else { pBssInfo->SG40 = 0; } } else { pBssInfo->EnableHT = 0; } /* HT information */ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) != 0xffff) { /* atheros pre n */ pBssInfo->extChOffset = zmw_rx_buf_readb(dev, buf, offset+2) & 0x03; } else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTINFORMATION)) != 0xffff) { /* pre n 2.0 standard */ pBssInfo->extChOffset = zmw_rx_buf_readb(dev, buf, offset+3) & 0x03; } else { pBssInfo->extChOffset = 0; } if ( (pBssInfo->enableHT40 == 1) && ((pBssInfo->extChOffset != 1) && (pBssInfo->extChOffset != 3)) ) { pBssInfo->enableHT40 = 0; } if (pBssInfo->enableHT40 == 1) { if (zfHpIsAllowedChannel(dev, pBssInfo->frequency+((pBssInfo->extChOffset==1)?20:-20)) == 0) { /* if extension channel is not an allowed channel, treat AP as non-HT mode */ pBssInfo->EnableHT = 0; pBssInfo->enableHT40 = 0; pBssInfo->extChOffset = 0; } } /* get ATH Extended Capability */ if ( ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) != 0xffff)&& ((offset = zfFindBrdcmMrvlRlnkExtCap(dev, buf)) == 0xffff)) { pBssInfo->athOwlAp = 1; } else { pBssInfo->athOwlAp = 0; } /* get Broadcom Extended Capability */ if ( (pBssInfo->EnableHT == 1) //((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) != 0xffff) && ((offset = zfFindBroadcomExtCap(dev, buf)) != 0xffff) ) { pBssInfo->broadcomHTAp = 1; } else { pBssInfo->broadcomHTAp = 0; } /* get Marvel Extended Capability */ if ((offset = zfFindMarvelExtCap(dev, buf)) != 0xffff) { pBssInfo->marvelAp = 1; } else { pBssInfo->marvelAp = 0; } /* get ATIM window */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_IBSS)) != 0xffff ) { pBssInfo->atimWindow = zmw_rx_buf_readh(dev, buf,offset+2); } /* Fit for support mode */ if (pBssInfo->frequency > 3000) { if (wd->supportMode & ZM_WIRELESS_MODE_5_N) { #if 0 if (wd->supportMode & ZM_WIRELESS_MODE_5_54) { /* support mode: a, n */ /* do nothing */ } else { /* support mode: n */ /* reject non-n bss info */ if (!pBssInfo->EnableHT) { goto zlError2; } } #endif } else { if (wd->supportMode & ZM_WIRELESS_MODE_5_54) { /* support mode: a */ /* delete n mode information */ pBssInfo->EnableHT = 0; pBssInfo->enableHT40 = 0; pBssInfo->apCap &= (~ZM_All11N_AP); pBssInfo->extChOffset = 0; pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, ZM_WLAN_EID_HT_CAPABILITY); pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, ZM_WLAN_PREN2_EID_HTCAPABILITY); pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY); pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, ZM_WLAN_PREN2_EID_HTINFORMATION); } else { /* support mode: none */ goto zlError2; } } } else { if (wd->supportMode & ZM_WIRELESS_MODE_24_N) { #if 0 if (wd->supportMode & ZM_WIRELESS_MODE_24_54) { if (wd->supportMode & ZM_WIRELESS_MODE_24_11) { /* support mode: b, g, n */ /* do nothing */ } else { /* support mode: g, n */ /* reject b-only bss info */ if ( (!pBssInfo->EnableHT) && (pBssInfo->extSupportedRates[1] == 0) ) { goto zlError2; } } } else { if (wd->supportMode & ZM_WIRELESS_MODE_24_11) { /* support mode: b, n */ /* 1. reject g-only bss info * 2. if non g-only, delete g mode information */ if ( !pBssInfo->EnableHT ) { if ( zfIsGOnlyMode(dev, pBssInfo->frequency, pBssInfo->supportedRates) || zfIsGOnlyMode(dev, pBssInfo->frequency, pBssInfo->extSupportedRates) ) { goto zlError2; } else { zfGatherBMode(dev, pBssInfo->supportedRates, pBssInfo->extSupportedRates); pBssInfo->erp = 0; pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, ZM_WLAN_EID_ERP); pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, ZM_WLAN_EID_EXTENDED_RATE); pBssInfo->frameBodysize = zfUpdateElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, pBssInfo->supportedRates); } } } else { /* support mode: n */ /* reject non-n bss info */ if (!pBssInfo->EnableHT) { goto zlError2; } } } #endif } else { /* delete n mode information */ pBssInfo->EnableHT = 0; pBssInfo->enableHT40 = 0; pBssInfo->apCap &= (~ZM_All11N_AP); pBssInfo->extChOffset = 0; pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, ZM_WLAN_EID_HT_CAPABILITY); pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, ZM_WLAN_PREN2_EID_HTCAPABILITY); pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY); pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, ZM_WLAN_PREN2_EID_HTINFORMATION); if (wd->supportMode & ZM_WIRELESS_MODE_24_54) { #if 0 if (wd->supportMode & ZM_WIRELESS_MODE_24_11) { /* support mode: b, g */ /* delete n mode information */ } else { /* support mode: g */ /* delete n mode information */ /* reject b-only bss info */ if (pBssInfo->extSupportedRates[1] == 0) { goto zlError2; } } #endif } else { if (wd->supportMode & ZM_WIRELESS_MODE_24_11) { /* support mode: b */ /* delete n mode information */ if ( zfIsGOnlyMode(dev, pBssInfo->frequency, pBssInfo->supportedRates) || zfIsGOnlyMode(dev, pBssInfo->frequency, pBssInfo->extSupportedRates) ) { goto zlError2; } else { zfGatherBMode(dev, pBssInfo->supportedRates, pBssInfo->extSupportedRates); pBssInfo->erp = 0; pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, ZM_WLAN_EID_ERP); pBssInfo->frameBodysize = zfRemoveElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, ZM_WLAN_EID_EXTENDED_RATE); pBssInfo->frameBodysize = zfUpdateElement(dev, pBssInfo->frameBody, pBssInfo->frameBodysize, pBssInfo->supportedRates); } } else { /* support mode: none */ goto zlError2; } } } } pBssInfo->flag |= ZM_BSS_INFO_VALID_BIT; zlUpdateRssi: /* Update Timer information */ pBssInfo->tick = wd->tick; /* Update ERP information */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_ERP)) != 0xffff ) { pBssInfo->erp = zmw_rx_buf_readb(dev, buf, offset+2); } if( (s8_t)pBssInfo->signalStrength < (s8_t)AddInfo->Tail.Data.SignalStrength1 ) { /* Update signal strength */ pBssInfo->signalStrength = (u8_t)AddInfo->Tail.Data.SignalStrength1; /* Update signal quality */ pBssInfo->signalQuality = (u8_t)(AddInfo->Tail.Data.SignalStrength1 * 2); /* Update the sorting value */ pBssInfo->sortValue = zfComputeBssInfoWeightValue(dev, (pBssInfo->supportedRates[6] + pBssInfo->extSupportedRates[0]), pBssInfo->EnableHT, pBssInfo->enableHT40, pBssInfo->signalStrength); } return 0; zlError: return 1; zlError2: return 2; } void zfStaProcessBeacon(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo) //CWYang(m) { /* Parse TIM and send PS-POLL in power saving mode */ struct zsWlanBeaconFrameHeader* pBeaconHeader; struct zsBssInfo* pBssInfo; u8_t pBuf[sizeof(struct zsWlanBeaconFrameHeader)]; u8_t bssid[6]; int res; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); /* sta routine jobs */ zfStaProtErpMonitor(dev, buf); /* check protection mode */ if (zfStaIsConnected(dev)) { ZM_MAC_WORD_TO_BYTE(wd->sta.bssid, bssid); if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) { if ( zfRxBufferEqualToStr(dev, buf, bssid, ZM_WLAN_HEADER_A2_OFFSET, 6) ) { zfPowerSavingMgrProcessBeacon(dev, buf); zfStaUpdateWmeParameter(dev, buf); if (wd->sta.DFSEnable) zfStaUpdateDot11HDFS(dev, buf); if (wd->sta.TPCEnable) zfStaUpdateDot11HTPC(dev, buf); /* update signal strength and signal quality */ zfStaSignalStatistic(dev, AddInfo->Tail.Data.SignalStrength1, AddInfo->Tail.Data.SignalQuality); //CWYang(+) wd->sta.rxBeaconCount++; } } else if ( wd->wlanMode == ZM_MODE_IBSS ) { if ( zfRxBufferEqualToStr(dev, buf, bssid, ZM_WLAN_HEADER_A3_OFFSET, 6) ) { int res; struct zsPartnerNotifyEvent event; zm_debug_msg0("20070916 Receive opposite Beacon!"); zmw_enter_critical_section(dev); wd->sta.ibssReceiveBeaconCount++; zmw_leave_critical_section(dev); res = zfStaSetOppositeInfoFromRxBuf(dev, buf); if ( res == 0 ) { // New peer station found. Notify the wrapper now zfInitPartnerNotifyEvent(dev, buf, &event); if (wd->zfcbIbssPartnerNotify != NULL) { wd->zfcbIbssPartnerNotify(dev, 1, &event); } } /* update signal strength and signal quality */ zfStaSignalStatistic(dev, AddInfo->Tail.Data.SignalStrength1, AddInfo->Tail.Data.SignalQuality); //CWYang(+) } //else if ( wd->sta.ibssPartnerStatus == ZM_IBSS_PARTNER_LOST ) // Why does this happen in IBSS?? The impact of Vista since // we need to tell it the BSSID #if 0 else if ( wd->sta.oppositeCount == 0 ) { /* IBSS merge if SSID matched */ if ( (offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID)) != 0xffff ) { if ( (wd->sta.ssidLen == zmw_buf_readb(dev, buf, offset+1))&& (zfRxBufferEqualToStr(dev, buf, wd->sta.ssid, offset+2, wd->sta.ssidLen)) ) { capabilityInfo = zmw_buf_readh(dev, buf, 34); if ( capabilityInfo & ZM_BIT_1 ) { if ( (wd->sta.capability[0] & ZM_BIT_4) == (capabilityInfo & ZM_BIT_4) ) { zm_debug_msg0("IBSS merge"); zfCopyFromRxBuffer(dev, buf, bssid, ZM_WLAN_HEADER_A3_OFFSET, 6); zfUpdateBssid(dev, bssid); } } } } } #endif } } /* return if not channel scan */ if ( !wd->sta.bChannelScan ) { goto zlReturn; } zfCopyFromRxBuffer(dev, buf, pBuf, 0, sizeof(struct zsWlanBeaconFrameHeader)); pBeaconHeader = (struct zsWlanBeaconFrameHeader*) pBuf; zmw_enter_critical_section(dev); //zm_debug_msg1("bss count = ", wd->sta.bssList.bssCount); pBssInfo = zfStaFindBssInfo(dev, buf, pBeaconHeader); if ( pBssInfo == NULL ) { /* Allocate a new entry if BSS not in the scan list */ pBssInfo = zfBssInfoAllocate(dev); if (pBssInfo != NULL) { res = zfStaInitBssInfo(dev, buf, pBeaconHeader, pBssInfo, AddInfo, 0); //zfDumpSSID(pBssInfo->ssid[1], &(pBssInfo->ssid[2])); if ( res != 0 ) { zfBssInfoFree(dev, pBssInfo); } else { zfBssInfoInsertToList(dev, pBssInfo); } } } else { res = zfStaInitBssInfo(dev, buf, pBeaconHeader, pBssInfo, AddInfo, 1); if (res == 2) { zfBssInfoRemoveFromList(dev, pBssInfo); zfBssInfoFree(dev, pBssInfo); } else if ( wd->wlanMode == ZM_MODE_IBSS ) { int idx; // It would reset the alive counter if the peer station is found! zfStaFindFreeOpposite(dev, (u16_t *)pBssInfo->macaddr, &idx); } } zmw_leave_critical_section(dev); zlReturn: return; } void zfAuthFreqCompleteCb(zdev_t* dev) { zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); zmw_enter_critical_section(dev); if (wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_COMPLETED) { zm_debug_msg0("ZM_STA_CONN_STATE_ASSOCIATE"); wd->sta.connectTimer = wd->tick; wd->sta.connectState = ZM_STA_CONN_STATE_ASSOCIATE; } zmw_leave_critical_section(dev); return; } /************************************************************************/ /* */ /* FUNCTION DESCRIPTION zfProcessAuth */ /* Process authenticate management frame. */ /* */ /* INPUTS */ /* dev : device pointer */ /* buf : auth frame buffer */ /* */ /* OUTPUTS */ /* none */ /* */ /* AUTHOR */ /* Stephen Chen ZyDAS Technology Corporation 2005.10 */ /* */ /************************************************************************/ /* Note : AP allows one authenticating STA at a time, does not */ /* support multiple authentication process. Make sure */ /* authentication state machine will not be blocked due */ /* to incompleted authentication handshake. */ void zfStaProcessAuth(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId) { struct zsWlanAuthFrameHeader* pAuthFrame; u8_t pBuf[sizeof(struct zsWlanAuthFrameHeader)]; u32_t p1, p2; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); if ( !zfStaIsConnecting(dev) ) { return; } pAuthFrame = (struct zsWlanAuthFrameHeader*) pBuf; zfCopyFromRxBuffer(dev, buf, pBuf, 0, sizeof(struct zsWlanAuthFrameHeader)); if ( wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_OPEN ) { if ( (zmw_le16_to_cpu(pAuthFrame->seq) == 2)&& (zmw_le16_to_cpu(pAuthFrame->algo) == 0)&& (zmw_le16_to_cpu(pAuthFrame->status) == 0) ) { zmw_enter_critical_section(dev); wd->sta.connectTimer = wd->tick; zm_debug_msg0("ZM_STA_CONN_STATE_AUTH_COMPLETED"); wd->sta.connectState = ZM_STA_CONN_STATE_AUTH_COMPLETED; zmw_leave_critical_section(dev); //Set channel according to AP's configuration //Move to here because of Cisco 11n AP feature zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40, wd->ExtOffset, zfAuthFreqCompleteCb); /* send association frame */ if ( wd->sta.connectByReasso ) { zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_REASOCREQ, wd->sta.bssid, 0, 0, 0); } else { zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ASOCREQ, wd->sta.bssid, 0, 0, 0); } } else { zm_debug_msg1("authentication failed, status = ", pAuthFrame->status); if (wd->sta.authMode == ZM_AUTH_MODE_AUTO) { wd->sta.bIsSharedKey = 1; zfStaStartConnect(dev, wd->sta.bIsSharedKey); } else { zm_debug_msg0("ZM_STA_STATE_DISCONNECT"); zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED, wd->sta.bssid, 3); } } } else if ( wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_SHARE_1 ) { if ( (zmw_le16_to_cpu(pAuthFrame->algo) == 1) && (zmw_le16_to_cpu(pAuthFrame->seq) == 2) && (zmw_le16_to_cpu(pAuthFrame->status) == 0)) //&& (pAuthFrame->challengeText[1] <= 255) ) { zfMemoryCopy(wd->sta.challengeText, pAuthFrame->challengeText, pAuthFrame->challengeText[1]+2); /* send the 3rd authentication frame */ p1 = 0x30001; p2 = 0; zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_AUTH, wd->sta.bssid, p1, p2, 0); zmw_enter_critical_section(dev); wd->sta.connectTimer = wd->tick; zm_debug_msg0("ZM_STA_SUB_STATE_AUTH_SHARE_2"); wd->sta.connectState = ZM_STA_CONN_STATE_AUTH_SHARE_2; zmw_leave_critical_section(dev); } else { zm_debug_msg1("authentication failed, status = ", pAuthFrame->status); zm_debug_msg0("ZM_STA_STATE_DISCONNECT"); zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED, wd->sta.bssid, 3); } } else if ( wd->sta.connectState == ZM_STA_CONN_STATE_AUTH_SHARE_2 ) { if ( (zmw_le16_to_cpu(pAuthFrame->algo) == 1)&& (zmw_le16_to_cpu(pAuthFrame->seq) == 4)&& (zmw_le16_to_cpu(pAuthFrame->status) == 0) ) { //Set channel according to AP's configuration //Move to here because of Cisco 11n AP feature zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40, wd->ExtOffset, NULL); /* send association frame */ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_ASOCREQ, wd->sta.bssid, 0, 0, 0); zmw_enter_critical_section(dev); wd->sta.connectTimer = wd->tick; zm_debug_msg0("ZM_STA_SUB_STATE_ASSOCIATE"); wd->sta.connectState = ZM_STA_CONN_STATE_ASSOCIATE; zmw_leave_critical_section(dev); } else { zm_debug_msg1("authentication failed, status = ", pAuthFrame->status); zm_debug_msg0("ZM_STA_STATE_DISCONNECT"); zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED, wd->sta.bssid, 3); } } else { zm_debug_msg0("unknown case"); } } void zfStaProcessAsocReq(zdev_t* dev, zbuf_t* buf, u16_t* src, u16_t apId) { return; } void zfStaProcessAsocRsp(zdev_t* dev, zbuf_t* buf) { struct zsWlanAssoFrameHeader* pAssoFrame; u8_t pBuf[sizeof(struct zsWlanAssoFrameHeader)]; u16_t offset; u32_t i; u32_t oneTxStreamCap; zmw_get_wlan_dev(dev); if ( !zfStaIsConnecting(dev) ) { return; } pAssoFrame = (struct zsWlanAssoFrameHeader*) pBuf; zfCopyFromRxBuffer(dev, buf, pBuf, 0, sizeof(struct zsWlanAssoFrameHeader)); if ( wd->sta.connectState == ZM_STA_CONN_STATE_ASSOCIATE ) { if ( pAssoFrame->status == 0 ) { zm_debug_msg0("ZM_STA_STATE_CONNECTED"); if (wd->sta.EnableHT == 1) { wd->sta.wmeConnected = 1; } if ((wd->sta.wmeEnabled & ZM_STA_WME_ENABLE_BIT) != 0) //WME enabled { /* Asoc rsp may contain WME parameter element */ if ((offset = zfFindWifiElement(dev, buf, 2, 1)) != 0xffff) { zm_debug_msg0("WME enable"); wd->sta.wmeConnected = 1; if ((wd->sta.wmeEnabled & ZM_STA_UAPSD_ENABLE_BIT) != 0) { if ((zmw_rx_buf_readb(dev, buf, offset+8) & 0x80) != 0) { zm_debug_msg0("UAPSD enable"); wd->sta.qosInfo = wd->sta.wmeQosInfo; } } zfStaUpdateWmeParameter(dev, buf); } } //Store asoc response frame body, for VISTA only wd->sta.asocRspFrameBodySize = zfwBufGetSize(dev, buf)-24; if (wd->sta.asocRspFrameBodySize > ZM_CACHED_FRAMEBODY_SIZE) { wd->sta.asocRspFrameBodySize = ZM_CACHED_FRAMEBODY_SIZE; } for (i=0; ista.asocRspFrameBodySize; i++) { wd->sta.asocRspFrameBody[i] = zmw_rx_buf_readb(dev, buf, i+24); } zfStaStoreAsocRspIe(dev, buf); if (wd->sta.EnableHT && ((wd->sta.ie.HtCap.HtCapInfo & HTCAP_SupChannelWidthSet) != 0) && (wd->ExtOffset != 0)) { wd->sta.htCtrlBandwidth = 1; } else { wd->sta.htCtrlBandwidth = 0; } //Set channel according to AP's configuration //zfCoreSetFrequencyEx(dev, wd->frequency, wd->BandWidth40, // wd->ExtOffset, NULL); if (wd->sta.EnableHT == 1) { wd->addbaComplete = 0; if ((wd->sta.SWEncryptEnable & ZM_SW_TKIP_ENCRY_EN) == 0 && (wd->sta.SWEncryptEnable & ZM_SW_WEP_ENCRY_EN) == 0) { wd->addbaCount = 1; zfAggSendAddbaRequest(dev, wd->sta.bssid, 0, 0); zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_ADDBA, 100); } } /* set RIFS support */ if(wd->sta.ie.HtInfo.ChannelInfo & ExtHtCap_RIFSMode) { wd->sta.HT2040 = 1; // zfHpSetRifs(dev, wd->sta.EnableHT, 1, (wd->sta.currentFrequency < 3000)? 1:0); } wd->sta.aid = pAssoFrame->aid & 0x3fff; wd->sta.oppositeCount = 0; /* reset opposite count */ zfStaSetOppositeInfoFromRxBuf(dev, buf); wd->sta.rxBeaconCount = 16; zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTED); wd->sta.connPowerInHalfDbm = zfHpGetTransmitPower(dev); if (wd->zfcbConnectNotify != NULL) { if (wd->sta.EnableHT != 0) /* 11n */ { oneTxStreamCap = (zfHpCapability(dev) & ZM_HP_CAP_11N_ONE_TX_STREAM); if (wd->sta.htCtrlBandwidth == 1) /* HT40*/ { if(oneTxStreamCap) /* one Tx stream */ { if (wd->sta.SG40) { wd->CurrentTxRateKbps = 150000; wd->CurrentRxRateKbps = 300000; } else { wd->CurrentTxRateKbps = 135000; wd->CurrentRxRateKbps = 270000; } } else /* Two Tx streams */ { if (wd->sta.SG40) { wd->CurrentTxRateKbps = 300000; wd->CurrentRxRateKbps = 300000; } else { wd->CurrentTxRateKbps = 270000; wd->CurrentRxRateKbps = 270000; } } } else /* HT20 */ { if(oneTxStreamCap) /* one Tx stream */ { wd->CurrentTxRateKbps = 650000; wd->CurrentRxRateKbps = 130000; } else /* Two Tx streams */ { wd->CurrentTxRateKbps = 130000; wd->CurrentRxRateKbps = 130000; } } } else /* 11abg */ { if (wd->sta.connection_11b != 0) { wd->CurrentTxRateKbps = 11000; wd->CurrentRxRateKbps = 11000; } else { wd->CurrentTxRateKbps = 54000; wd->CurrentRxRateKbps = 54000; } } wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_CONNECT, wd->sta.bssid); } wd->sta.connectByReasso = TRUE; wd->sta.failCntOfReasso = 0; zfPowerSavingMgrConnectNotify(dev); /* Disable here because fixed rate is only for test, TBD. */ //if (wd->sta.EnableHT) //{ // wd->txMCS = 7; //Rate = 65Mbps // wd->txMT = 2; // Ht rate // wd->enableAggregation = 2; // Enable Aggregation //} } else { zm_debug_msg1("association failed, status = ", pAssoFrame->status); zm_debug_msg0("ZM_STA_STATE_DISCONNECT"); wd->sta.connectByReasso = FALSE; zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_ASOC_FAILED, wd->sta.bssid, 3); } } } void zfStaStoreAsocRspIe(zdev_t* dev, zbuf_t* buf) { u16_t offset; u32_t i; u16_t length; u8_t *htcap; u8_t asocBw40 = 0; u8_t asocExtOffset = 0; zmw_get_wlan_dev(dev); for (i=0; ista.asocRspFrameBodySize; i++) { wd->sta.asocRspFrameBody[i] = zmw_rx_buf_readb(dev, buf, i+24); } /* HT capabilities: 28 octets */ if ( ((wd->sta.currentFrequency > 3000) && !(wd->supportMode & ZM_WIRELESS_MODE_5_N)) || ((wd->sta.currentFrequency < 3000) && !(wd->supportMode & ZM_WIRELESS_MODE_24_N)) ) { /* not 11n AP */ htcap = (u8_t *)&wd->sta.ie.HtCap; for (i=0; i<28; i++) { htcap[i] = 0; } wd->BandWidth40 = 0; wd->ExtOffset = 0; return; } if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_HT_CAPABILITY)) != 0xffff) { /* atheros pre n */ zm_debug_msg0("atheros pre n"); htcap = (u8_t *)&wd->sta.ie.HtCap; htcap[0] = zmw_rx_buf_readb(dev, buf, offset); htcap[1] = 26; for (i=1; i<=26; i++) { htcap[i+1] = zmw_rx_buf_readb(dev, buf, offset + i); zm_msg2_mm(ZM_LV_1, "ASOC: HT Capabilities, htcap=", htcap[i+1]); } } else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTCAPABILITY)) != 0xffff) { /* pre n 2.0 standard */ zm_debug_msg0("pre n 2.0 standard"); htcap = (u8_t *)&wd->sta.ie.HtCap; for (i=0; i<28; i++) { htcap[i] = zmw_rx_buf_readb(dev, buf, offset + i); zm_msg2_mm(ZM_LV_1, "ASOC: HT Capabilities, htcap=", htcap[i]); } } else { /* not 11n AP */ htcap = (u8_t *)&wd->sta.ie.HtCap; for (i=0; i<28; i++) { htcap[i] = 0; } wd->BandWidth40 = 0; wd->ExtOffset = 0; return; } asocBw40 = (u8_t)((wd->sta.ie.HtCap.HtCapInfo & HTCAP_SupChannelWidthSet) >> 1); /* HT information */ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_EXTENDED_HT_CAPABILITY)) != 0xffff) { /* atheros pre n */ zm_debug_msg0("atheros pre n HTINFO"); length = 22; htcap = (u8_t *)&wd->sta.ie.HtInfo; htcap[0] = zmw_rx_buf_readb(dev, buf, offset); htcap[1] = 22; for (i=1; i<=22; i++) { htcap[i+1] = zmw_rx_buf_readb(dev, buf, offset + i); zm_msg2_mm(ZM_LV_1, "ASOC: HT Info, htinfo=", htcap[i+1]); } } else if ((offset = zfFindElement(dev, buf, ZM_WLAN_PREN2_EID_HTINFORMATION)) != 0xffff) { /* pre n 2.0 standard */ zm_debug_msg0("pre n 2.0 standard HTINFO"); length = zmw_rx_buf_readb(dev, buf, offset + 1); htcap = (u8_t *)&wd->sta.ie.HtInfo; for (i=0; i<24; i++) { htcap[i] = zmw_rx_buf_readb(dev, buf, offset + i); zm_msg2_mm(ZM_LV_1, "ASOC: HT Info, htinfo=", htcap[i]); } } else { zm_debug_msg0("no HTINFO"); htcap = (u8_t *)&wd->sta.ie.HtInfo; for (i=0; i<24; i++) { htcap[i] = 0; } } asocExtOffset = wd->sta.ie.HtInfo.ChannelInfo & ExtHtCap_ExtChannelOffsetBelow; if ((wd->sta.EnableHT == 1) && (asocBw40 == 1) && ((asocExtOffset == 1) || (asocExtOffset == 3))) { wd->BandWidth40 = asocBw40; wd->ExtOffset = asocExtOffset; } else { wd->BandWidth40 = 0; wd->ExtOffset = 0; } return; } void zfStaProcessDeauth(zdev_t* dev, zbuf_t* buf) { u16_t apMacAddr[3]; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); /* STA : if SA=connected AP then disconnect with AP */ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) { apMacAddr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET); apMacAddr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+2); apMacAddr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+4); if ((apMacAddr[0] == wd->sta.bssid[0]) && (apMacAddr[1] == wd->sta.bssid[1]) && (apMacAddr[2] == wd->sta.bssid[2])) { if (zfwBufGetSize(dev, buf) >= 24+2) //not a malformed frame { if ( zfStaIsConnected(dev) ) { zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_DEAUTH, wd->sta.bssid, 2); } else if (zfStaIsConnecting(dev)) { zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_AUTH_FAILED, wd->sta.bssid, 3); } else { } } } } else if ( wd->wlanMode == ZM_MODE_IBSS ) { u16_t peerMacAddr[3]; u8_t peerIdx; s8_t res; if ( zfStaIsConnected(dev) ) { peerMacAddr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET); peerMacAddr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+2); peerMacAddr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+4); zmw_enter_critical_section(dev); res = zfStaFindOppositeByMACAddr(dev, peerMacAddr, &peerIdx); if ( res == 0 ) { wd->sta.oppositeInfo[peerIdx].aliveCounter = 0; } zmw_leave_critical_section(dev); } } } void zfStaProcessDisasoc(zdev_t* dev, zbuf_t* buf) { u16_t apMacAddr[3]; zmw_get_wlan_dev(dev); /* STA : if SA=connected AP then disconnect with AP */ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) { apMacAddr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET); apMacAddr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+2); apMacAddr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A3_OFFSET+4); if ((apMacAddr[0] == wd->sta.bssid[0]) && (apMacAddr[1] == wd->sta.bssid[1]) && (apMacAddr[2] == wd->sta.bssid[2])) { if (zfwBufGetSize(dev, buf) >= 24+2) //not a malformed frame { if ( zfStaIsConnected(dev) ) { zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_DISASOC, wd->sta.bssid, 2); } else { zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_ASOC_FAILED, wd->sta.bssid, 3); } } } } } /************************************************************************/ /* */ /* FUNCTION DESCRIPTION zfProcessProbeReq */ /* Process probe request management frame. */ /* */ /* INPUTS */ /* dev : device pointer */ /* buf : auth frame buffer */ /* */ /* OUTPUTS */ /* none */ /* */ /* AUTHOR */ /* Stephen Chen ZyDAS Technology Corporation 2005.10 */ /* */ /************************************************************************/ void zfStaProcessProbeReq(zdev_t* dev, zbuf_t* buf, u16_t* src) { u16_t offset; u8_t len; u16_t i, j; u16_t sendFlag; zmw_get_wlan_dev(dev); /* check mode : AP/IBSS */ if ((wd->wlanMode != ZM_MODE_AP) || (wd->wlanMode != ZM_MODE_IBSS)) { zm_msg0_mm(ZM_LV_3, "Ignore probe req"); return; } /* check SSID */ if ((offset = zfFindElement(dev, buf, ZM_WLAN_EID_SSID)) == 0xffff) { zm_msg0_mm(ZM_LV_3, "probe req SSID not found"); return; } len = zmw_rx_buf_readb(dev, buf, offset+1); for (i=0; iap.apBitmap & (i<ap.hideSsid[i] == 0)) { sendFlag = 1; } /* Not broadcast SSID */ else if (wd->ap.ssidLen[i] == len) { for (j=0; jap.ssid[i][j]) { break; } } if (j == len) { sendFlag = 1; } } if (sendFlag == 1) { /* Send probe response */ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBERSP, src, i, 0, 0); } } } } void zfStaProcessProbeRsp(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* AddInfo) { /* return if not channel scan */ // Probe response is sent with unicast. Is this required? // IBSS would send probe request and the code below would prevent // the probe response from handling. #if 0 zmw_get_wlan_dev(dev); if ( !wd->sta.bChannelScan ) { return; } #endif zfProcessProbeRsp(dev, buf, AddInfo); } void zfIBSSSetupBssDesc(zdev_t *dev) { #ifdef ZM_ENABLE_IBSS_WPA2PSK u8_t i; #endif struct zsBssInfo *pBssInfo; u16_t offset = 0; zmw_get_wlan_dev(dev); pBssInfo = &wd->sta.ibssBssDesc; zfZeroMemory((u8_t *)pBssInfo, sizeof(struct zsBssInfo)); pBssInfo->signalStrength = 100; zfMemoryCopy((u8_t *)pBssInfo->macaddr, (u8_t *)wd->macAddr,6); zfMemoryCopy((u8_t *)pBssInfo->bssid, (u8_t *)wd->sta.bssid, 6); pBssInfo->beaconInterval[0] = (u8_t)(wd->beaconInterval) ; pBssInfo->beaconInterval[1] = (u8_t)((wd->beaconInterval) >> 8) ; pBssInfo->capability[0] = wd->sta.capability[0]; pBssInfo->capability[1] = wd->sta.capability[1]; pBssInfo->ssid[0] = ZM_WLAN_EID_SSID; pBssInfo->ssid[1] = wd->sta.ssidLen; zfMemoryCopy((u8_t *)&pBssInfo->ssid[2], (u8_t *)wd->sta.ssid, wd->sta.ssidLen); zfMemoryCopy((u8_t *)&pBssInfo->frameBody[offset], (u8_t *)pBssInfo->ssid, wd->sta.ssidLen + 2); offset += wd->sta.ssidLen + 2; /* support rate */ /* DS parameter set */ pBssInfo->channel = zfChFreqToNum(wd->frequency, NULL); pBssInfo->frequency = wd->frequency; pBssInfo->atimWindow = wd->sta.atimWindow; #ifdef ZM_ENABLE_IBSS_WPA2PSK if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK ) { u8_t rsn[64]= { /* Element ID */ 0x30, /* Length */ 0x14, /* Version */ 0x01, 0x00, /* Group Cipher Suite, default=TKIP */ 0x00, 0x0f, 0xac, 0x04, /* Pairwise Cipher Suite Count */ 0x01, 0x00, /* Pairwise Cipher Suite, default=TKIP */ 0x00, 0x0f, 0xac, 0x02, /* Authentication and Key Management Suite Count */ 0x01, 0x00, /* Authentication type, default=PSK */ 0x00, 0x0f, 0xac, 0x02, /* RSN capability */ 0x00, 0x00 }; /* Overwrite Group Cipher Suite by AP's setting */ zfMemoryCopy(rsn+4, zgWpa2AesOui, 4); if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES ) { /* Overwrite Pairwise Cipher Suite by AES */ zfMemoryCopy(rsn+10, zgWpa2AesOui, 4); } // RSN element id pBssInfo->frameBody[offset++] = ZM_WLAN_EID_RSN_IE ; // RSN length pBssInfo->frameBody[offset++] = rsn[1] ; // RSN information for(i=0; iframeBody[offset++] = rsn[i+2] ; } zfMemoryCopy(pBssInfo->rsnIe, rsn, rsn[1]+2); } #endif } void zfIbssConnectNetwork(zdev_t* dev) { struct zsBssInfo* pBssInfo; struct zsBssInfo tmpBssInfo; u8_t macAddr[6], bssid[6], bssNotFound = TRUE; u16_t i, j=100; u16_t k; struct zsPartnerNotifyEvent event; u32_t channelFlags; u16_t oppositeWepStatus; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); /* change state to CONNECTING and stop the channel scanning */ zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTING); zfPowerSavingMgrWakeup(dev); /* Set TxQs CWMIN, CWMAX, AIFS and TXO to WME STA default. */ zfUpdateDefaultQosParameter(dev, 0); wd->sta.bProtectionMode = FALSE; zfHpSetSlotTime(dev, 1); /* ESS bit off */ wd->sta.capability[0] &= ~ZM_BIT_0; /* IBSS bit on */ wd->sta.capability[0] |= ZM_BIT_1; /* not not use short slot time */ wd->sta.capability[1] &= ~ZM_BIT_2; wd->sta.wmeConnected = 0; wd->sta.psMgr.tempWakeUp = 0; wd->sta.qosInfo = 0; wd->sta.EnableHT = 0; wd->BandWidth40 = 0; wd->ExtOffset = 0; if ( wd->sta.bssList.bssCount ) { //Reorder BssList by RSSI--CWYang(+) zfBssInfoReorderList(dev); zmw_enter_critical_section(dev); pBssInfo = wd->sta.bssList.head; for(i=0; ista.bssList.bssCount; i++) { // 20070806 #1 Privacy bit if ( pBssInfo->capability[0] & ZM_BIT_4 ) { // Privacy Ibss network // zm_debug_msg0("Privacy bit on"); oppositeWepStatus = ZM_ENCRYPTION_WEP_ENABLED; if ( pBssInfo->rsnIe[1] != 0 ) { if ( (pBssInfo->rsnIe[7] == 0x01) || (pBssInfo->rsnIe[7] == 0x05) ) { // WEP-40 & WEP-104 // zm_debug_msg0("WEP40 or WEP104"); oppositeWepStatus = ZM_ENCRYPTION_WEP_ENABLED; } else if ( pBssInfo->rsnIe[7] == 0x02 ) { // TKIP // zm_debug_msg0("TKIP"); oppositeWepStatus = ZM_ENCRYPTION_TKIP; } else if ( pBssInfo->rsnIe[7] == 0x04 ) { // AES // zm_debug_msg0("CCMP-AES"); oppositeWepStatus = ZM_ENCRYPTION_AES; } } } else { // zm_debug_msg0("Privacy bit off"); oppositeWepStatus = ZM_ENCRYPTION_WEP_DISABLED; } if ( (zfMemoryIsEqual(&(pBssInfo->ssid[2]), wd->sta.ssid, wd->sta.ssidLen))&& (wd->sta.ssidLen == pBssInfo->ssid[1])&& (oppositeWepStatus == wd->sta.wepStatus) ) { /* Check support mode */ if (pBssInfo->frequency > 3000) { if ( (pBssInfo->EnableHT == 1) || (pBssInfo->apCap & ZM_All11N_AP) ) //11n AP { channelFlags = CHANNEL_A_HT; if (pBssInfo->enableHT40 == 1) { channelFlags |= CHANNEL_HT40; } } else { channelFlags = CHANNEL_A; } } else { if ( (pBssInfo->EnableHT == 1) || (pBssInfo->apCap & ZM_All11N_AP) ) //11n AP { channelFlags = CHANNEL_G_HT; if(pBssInfo->enableHT40 == 1) { channelFlags |= CHANNEL_HT40; } } else { if (pBssInfo->extSupportedRates[1] == 0) { channelFlags = CHANNEL_B; } else { channelFlags = CHANNEL_G; } } } if ( ((channelFlags == CHANNEL_B) && (wd->connectMode & ZM_BIT_0)) || ((channelFlags == CHANNEL_G) && (wd->connectMode & ZM_BIT_1)) || ((channelFlags == CHANNEL_A) && (wd->connectMode & ZM_BIT_2)) || ((channelFlags & CHANNEL_HT20) && (wd->connectMode & ZM_BIT_3)) ) { pBssInfo = pBssInfo->next; continue; } /* Bypass DFS channel */ if (zfHpIsDfsChannelNCS(dev, pBssInfo->frequency)) { zm_debug_msg0("Bypass DFS channel"); continue; } /* check IBSS bit */ if ( pBssInfo->capability[0] & ZM_BIT_1 ) { /* may check timestamp here */ j = i; break; } } pBssInfo = pBssInfo->next; } if ((j < wd->sta.bssList.bssCount) && (pBssInfo != NULL)) { zfwMemoryCopy((u8_t*)&tmpBssInfo, (u8_t*)(pBssInfo), sizeof(struct zsBssInfo)); pBssInfo = &tmpBssInfo; } else { pBssInfo = NULL; } zmw_leave_critical_section(dev); //if ( j < wd->sta.bssList.bssCount ) if (pBssInfo != NULL) { int res; zm_debug_msg0("IBSS found"); /* Found IBSS, reset bssNotFoundCount */ zmw_enter_critical_section(dev); wd->sta.bssNotFoundCount = 0; zmw_leave_critical_section(dev); bssNotFound = FALSE; wd->sta.atimWindow = pBssInfo->atimWindow; wd->frequency = pBssInfo->frequency; //wd->sta.flagFreqChanging = 1; zfCoreSetFrequency(dev, wd->frequency); zfUpdateBssid(dev, pBssInfo->bssid); zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_ZERO); zfUpdateSupportRate(dev, pBssInfo->supportedRates); zfUpdateSupportRate(dev, pBssInfo->extSupportedRates); wd->beaconInterval = pBssInfo->beaconInterval[0] + (((u16_t) pBssInfo->beaconInterval[1]) << 8); if (wd->beaconInterval == 0) { wd->beaconInterval = 100; } /* rsn information element */ if ( pBssInfo->rsnIe[1] != 0 ) { zfMemoryCopy(wd->sta.rsnIe, pBssInfo->rsnIe, pBssInfo->rsnIe[1]+2); #ifdef ZM_ENABLE_IBSS_WPA2PSK /* If not use RSNA , run traditional */ zmw_enter_critical_section(dev); wd->sta.ibssWpa2Psk = 1; zmw_leave_critical_section(dev); #endif } else { wd->sta.rsnIe[1] = 0; } /* privacy bit */ if ( pBssInfo->capability[0] & ZM_BIT_4 ) { wd->sta.capability[0] |= ZM_BIT_4; } else { wd->sta.capability[0] &= ~ZM_BIT_4; } /* preamble type */ wd->preambleTypeInUsed = wd->preambleType; if ( wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_AUTO ) { if (pBssInfo->capability[0] & ZM_BIT_5) { wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_SHORT; } else { wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_LONG; } } if (wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_LONG) { wd->sta.capability[0] &= ~ZM_BIT_5; } else { wd->sta.capability[0] |= ZM_BIT_5; } wd->sta.beaconFrameBodySize = pBssInfo->frameBodysize + 12; if (wd->sta.beaconFrameBodySize > ZM_CACHED_FRAMEBODY_SIZE) { wd->sta.beaconFrameBodySize = ZM_CACHED_FRAMEBODY_SIZE; } for (k=0; k<8; k++) { wd->sta.beaconFrameBody[k] = pBssInfo->timeStamp[k]; } wd->sta.beaconFrameBody[8] = pBssInfo->beaconInterval[0]; wd->sta.beaconFrameBody[9] = pBssInfo->beaconInterval[1]; wd->sta.beaconFrameBody[10] = pBssInfo->capability[0]; wd->sta.beaconFrameBody[11] = pBssInfo->capability[1]; //for (k=12; ksta.beaconFrameBodySize; k++) for (k=0; kframeBodysize; k++) { wd->sta.beaconFrameBody[k+12] = pBssInfo->frameBody[k]; } zmw_enter_critical_section(dev); res = zfStaSetOppositeInfoFromBSSInfo(dev, pBssInfo); if ( res == 0 ) { zfMemoryCopy(event.bssid, (u8_t *)(pBssInfo->bssid), 6); zfMemoryCopy(event.peerMacAddr, (u8_t *)(pBssInfo->macaddr), 6); } zmw_leave_critical_section(dev); //zfwIbssPartnerNotify(dev, 1, &event); goto connect_done; } } /* IBSS not found */ if ( bssNotFound ) { #ifdef ZM_ENABLE_IBSS_WPA2PSK u16_t offset ; #endif if ( wd->sta.ibssJoinOnly ) { zm_debug_msg0("IBSS join only...retry..."); goto retry_ibss; } if(wd->sta.bssNotFoundCount<2) { zmw_enter_critical_section(dev); zm_debug_msg1("IBSS not found, do sitesurvey!! bssNotFoundCount=", wd->sta.bssNotFoundCount); wd->sta.bssNotFoundCount++; zmw_leave_critical_section(dev); goto retry_ibss; } else { zmw_enter_critical_section(dev); /* Fail IBSS found, TODO create IBSS */ wd->sta.bssNotFoundCount = 0; zmw_leave_critical_section(dev); } if (zfHpIsDfsChannel(dev, wd->frequency)) { wd->frequency = zfHpFindFirstNonDfsChannel(dev, wd->frequency > 3000); } if( wd->ws.autoSetFrequency == 0 ) { /* Auto set frequency */ zm_debug_msg1("Create Ad Hoc Network Band ", wd->ws.adhocMode); wd->frequency = zfFindCleanFrequency(dev, wd->ws.adhocMode); wd->ws.autoSetFrequency = 0xff; } zm_debug_msg1("IBSS not found, created one in channel ", wd->frequency); wd->sta.ibssBssIsCreator = 1; //wd->sta.flagFreqChanging = 1; zfCoreSetFrequency(dev, wd->frequency); if (wd->sta.bDesiredBssid == TRUE) { for (k=0; k<6; k++) { bssid[k] = wd->sta.desiredBssid[k]; } } else { #if 1 macAddr[0] = (wd->macAddr[0] & 0xff); macAddr[1] = (wd->macAddr[0] >> 8); macAddr[2] = (wd->macAddr[1] & 0xff); macAddr[3] = (wd->macAddr[1] >> 8); macAddr[4] = (wd->macAddr[2] & 0xff); macAddr[5] = (wd->macAddr[2] >> 8); zfGenerateRandomBSSID(dev, (u8_t *)wd->macAddr, (u8_t *)bssid); #else for (k=0; k<6; k++) { bssid[k] = (u8_t) zfGetRandomNumber(dev, 0); } bssid[0] &= ~ZM_BIT_0; bssid[0] |= ZM_BIT_1; #endif } zfUpdateBssid(dev, bssid); //wd->sta.atimWindow = 0x0a; /* rate information */ if(wd->frequency <= ZM_CH_G_14) // 2.4 GHz b+g { if ( wd->wfc.bIbssGMode && (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) ) { zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_IBSS_AG); } else { zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_IBSS_B); } } else { zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_IBSS_AG); } if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_DISABLED ) { wd->sta.capability[0] &= ~ZM_BIT_4; } else { wd->sta.capability[0] |= ZM_BIT_4; } wd->preambleTypeInUsed = wd->preambleType; if (wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_LONG) { wd->sta.capability[0] &= ~ZM_BIT_5; } else { wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_SHORT; wd->sta.capability[0] |= ZM_BIT_5; } zfIBSSSetupBssDesc(dev); #ifdef ZM_ENABLE_IBSS_WPA2PSK // 20070411 Add WPA2PSK information to its IBSS network !!! offset = 0 ; /* timestamp */ offset += 8 ; /* beacon interval */ wd->sta.beaconFrameBody[offset++] = (u8_t)(wd->beaconInterval) ; wd->sta.beaconFrameBody[offset++] = (u8_t)((wd->beaconInterval) >> 8) ; /* capability information */ wd->sta.beaconFrameBody[offset++] = wd->sta.capability[0] ; wd->sta.beaconFrameBody[offset++] = wd->sta.capability[1] ; #if 0 /* ssid */ // ssid element id wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_SSID ; // ssid length wd->sta.beaconFrameBody[offset++] = wd->sta.ssidLen ; // ssid information for(i=0; ista.ssidLen; i++) { wd->sta.beaconFrameBody[offset++] = wd->sta.ssid[i] ; } /* support rate */ rateSet = ZM_RATE_SET_CCK ; if ( (rateSet == ZM_RATE_SET_OFDM)&&((wd->gRate & 0xff) == 0) ) { offset += 0 ; } else { // support rate element id wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_SUPPORT_RATE ; // support rate length lenOffset = offset++; // support rate information for (i=0; i<4; i++) { if ((wd->bRate & (0x1<sta.beaconFrameBody[offset++] = zg11bRateTbl[i]+((wd->bRateBasic & (0x1<sta.beaconFrameBody[lenOffset] = len ; } /* DS parameter set */ // DS parameter set elemet id wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_DS ; // DS parameter set length wd->sta.beaconFrameBody[offset++] = 1 ; // DS parameter set information wd->sta.beaconFrameBody[offset++] = zfChFreqToNum(wd->frequency, NULL) ; /* IBSS parameter set */ // IBSS parameter set element id wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_IBSS ; // IBSS parameter set length wd->sta.beaconFrameBody[offset++] = 2 ; // IBSS parameter set information wd->sta.beaconFrameBody[offset] = wd->sta.atimWindow ; offset += 2 ; /* ERP Information and Extended Supported Rates */ if ( wd->wfc.bIbssGMode && (wd->supportMode & (ZM_WIRELESS_MODE_24_54|ZM_WIRELESS_MODE_24_N)) ) { /* ERP Information */ wd->erpElement = 0; // ERP element id wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_ERP ; // ERP length wd->sta.beaconFrameBody[offset++] = 1 ; // ERP information wd->sta.beaconFrameBody[offset++] = wd->erpElement ; /* Extended Supported Rates */ if ( (rateSet == ZM_RATE_SET_OFDM)&&((wd->gRate & 0xff) == 0) ) { offset += 0 ; } else { len = 0 ; // Extended Supported Rates element id wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_EXTENDED_RATE ; // Extended Supported Rates length lenOffset = offset++ ; // Extended Supported Rates information for (i=0; i<8; i++) { if ((wd->gRate & (0x1<sta.beaconFrameBody[offset++] = zg11gRateTbl[i]+((wd->gRateBasic & (0x1<sta.beaconFrameBody[lenOffset] = len ; } } #endif /* RSN : important information influence the result of creating an IBSS network */ if ( wd->sta.authMode == ZM_AUTH_MODE_WPA2PSK ) { u8_t frameType = ZM_WLAN_FRAME_TYPE_AUTH ; u8_t rsn[64]= { /* Element ID */ 0x30, /* Length */ 0x14, /* Version */ 0x01, 0x00, /* Group Cipher Suite, default=TKIP */ 0x00, 0x0f, 0xac, 0x04, /* Pairwise Cipher Suite Count */ 0x01, 0x00, /* Pairwise Cipher Suite, default=TKIP */ 0x00, 0x0f, 0xac, 0x02, /* Authentication and Key Management Suite Count */ 0x01, 0x00, /* Authentication type, default=PSK */ 0x00, 0x0f, 0xac, 0x02, /* RSN capability */ 0x00, 0x00 }; /* Overwrite Group Cipher Suite by AP's setting */ zfMemoryCopy(rsn+4, zgWpa2AesOui, 4); if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES ) { /* Overwrite Pairwise Cipher Suite by AES */ zfMemoryCopy(rsn+10, zgWpa2AesOui, 4); } // RSN element id wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_RSN_IE ; // RSN length wd->sta.beaconFrameBody[offset++] = rsn[1] ; // RSN information for(i=0; ista.beaconFrameBody[offset++] = rsn[i+2] ; zfMemoryCopy(wd->sta.rsnIe, rsn, rsn[1]+2); #ifdef ZM_ENABLE_IBSS_WPA2PSK /* If not use RSNA , run traditional */ zmw_enter_critical_section(dev); wd->sta.ibssWpa2Psk = 1; zmw_leave_critical_section(dev); #endif } #if 0 /* HT Capabilities Info */ { u8_t OUI[3] = { 0x0 , 0x90 , 0x4C } ; wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_WPA_IE ; wd->sta.beaconFrameBody[offset++] = wd->sta.HTCap.Data.Length + 4 ; for (i = 0; i < 3; i++) { wd->sta.beaconFrameBody[offset++] = OUI[i] ; } wd->sta.beaconFrameBody[offset++] = wd->sta.HTCap.Data.ElementID ; for (i = 0; i < 26; i++) { wd->sta.beaconFrameBody[offset++] = wd->sta.HTCap.Byte[i+2] ; } } /* Extended HT Capabilities Info */ { u8_t OUI[3] = { 0x0 , 0x90 , 0x4C } ; wd->sta.beaconFrameBody[offset++] = ZM_WLAN_EID_WPA_IE ; wd->sta.beaconFrameBody[offset++] = wd->sta.ExtHTCap.Data.Length + 4 ; for (i = 0; i < 3; i++) { wd->sta.beaconFrameBody[offset++] = OUI[i] ; } wd->sta.beaconFrameBody[offset++] = wd->sta.ExtHTCap.Data.ElementID ; for (i = 0; i < 22; i++) { wd->sta.beaconFrameBody[offset++] = wd->sta.ExtHTCap.Byte[i+2] ; } } #endif wd->sta.beaconFrameBodySize = offset ; if (wd->sta.beaconFrameBodySize > ZM_CACHED_FRAMEBODY_SIZE) { wd->sta.beaconFrameBodySize = ZM_CACHED_FRAMEBODY_SIZE; } // 20070416 Let Create IBSS network could enter the zfwIbssPartnerNotify function // bssNotFound = FALSE ; printk("The capability info 1 = %02x\n", wd->sta.capability[0]) ; printk("The capability info 2 = %02x\n", wd->sta.capability[1]) ; for(k=0; ksta.beaconFrameBodySize; k++) { printk("%02x ", wd->sta.beaconFrameBody[k]) ; } #if 0 zmw_enter_critical_section(dev); zfMemoryCopy(event.bssid, (u8_t *)bssid, 6); zfMemoryCopy(event.peerMacAddr, (u8_t *)wd->macAddr, 6); zmw_leave_critical_section(dev); #endif #endif //zmw_enter_critical_section(dev); //wd->sta.ibssPartnerStatus = ZM_IBSS_PARTNER_LOST; //zmw_leave_critical_section(dev); } else { wd->sta.ibssBssIsCreator = 0; } connect_done: zfHpEnableBeacon(dev, ZM_MODE_IBSS, wd->beaconInterval, wd->dtim, (u8_t)wd->sta.atimWindow); zfStaSendBeacon(dev); // Refresh Beacon content for ZD1211B HalPlus zfHpSetAtimWindow(dev, wd->sta.atimWindow); // Start the IBSS timer to monitor for new stations zmw_enter_critical_section(dev); zfTimerSchedule(dev, ZM_EVENT_IBSS_MONITOR, ZM_TICK_IBSS_MONITOR); zmw_leave_critical_section(dev); if (wd->zfcbConnectNotify != NULL) { wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_CONNECT, wd->sta.bssid); } zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTED); wd->sta.connPowerInHalfDbm = zfHpGetTransmitPower(dev); #ifdef ZM_ENABLE_IBSS_DELAYED_JOIN_INDICATION if ( !bssNotFound ) { wd->sta.ibssDelayedInd = 1; zfMemoryCopy((u8_t *)&wd->sta.ibssDelayedIndEvent, (u8_t *)&event, sizeof(struct zsPartnerNotifyEvent)); } #else if ( !bssNotFound ) { if (wd->zfcbIbssPartnerNotify != NULL) { wd->zfcbIbssPartnerNotify(dev, 1, &event); } } #endif return; retry_ibss: zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTING); zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_NOT_FOUND, wd->sta.bssid, 0); return; } void zfStaProcessAtim(zdev_t* dev, zbuf_t* buf) { zmw_get_wlan_dev(dev); zm_debug_msg0("Receiving Atim window notification"); wd->sta.recvAtim = 1; } static struct zsBssInfo* zfInfraFindAPToConnect(zdev_t* dev, struct zsBssInfo* candidateBss) { struct zsBssInfo* pBssInfo; struct zsBssInfo* pNowBssInfo=NULL; u16_t i; u16_t ret, apWepStatus; u32_t k; u32_t channelFlags; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); zmw_enter_critical_section(dev); pBssInfo = wd->sta.bssList.head; for(i=0; ista.bssList.bssCount; i++) { if ( pBssInfo->capability[0] & ZM_BIT_4 ) { apWepStatus = ZM_ENCRYPTION_WEP_ENABLED; } else { apWepStatus = ZM_ENCRYPTION_WEP_DISABLED; } if ( ((zfMemoryIsEqual(&(pBssInfo->ssid[2]), wd->sta.ssid, wd->sta.ssidLen))&& (wd->sta.ssidLen == pBssInfo->ssid[1]))|| ((wd->sta.ssidLen == 0)&& /* connect to any BSS: AP's ans STA's WEP status must match */ (wd->sta.wepStatus == apWepStatus )&& (pBssInfo->securityType != ZM_SECURITY_TYPE_WPA) )) { if ( wd->sta.ssidLen == 0 ) { zm_debug_msg0("ANY BSS found"); } if ( ((wd->sta.wepStatus == ZM_ENCRYPTION_WEP_DISABLED && apWepStatus == ZM_ENCRYPTION_WEP_ENABLED) || (wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED && (apWepStatus == ZM_ENCRYPTION_WEP_DISABLED && wd->sta.dropUnencryptedPkts == 1))) && (wd->sta.authMode >= ZM_AUTH_MODE_OPEN && wd->sta.authMode <= ZM_AUTH_MODE_AUTO) ) { zm_debug_msg0("Privacy policy is inconsistent"); pBssInfo = pBssInfo->next; continue; } /* for WPA negative test */ if ( !zfCheckAuthentication(dev, pBssInfo) ) { pBssInfo = pBssInfo->next; continue; } /* Check bssid */ if (wd->sta.bDesiredBssid == TRUE) { for (k=0; k<6; k++) { if (wd->sta.desiredBssid[k] != pBssInfo->bssid[k]) { zm_msg0_mm(ZM_LV_1, "desired bssid not matched 1"); break; } } if (k != 6) { zm_msg0_mm(ZM_LV_1, "desired bssid not matched 2"); pBssInfo = pBssInfo->next; continue; } } /* Check support mode */ if (pBssInfo->frequency > 3000) { if ( (pBssInfo->EnableHT == 1) || (pBssInfo->apCap & ZM_All11N_AP) ) //11n AP { channelFlags = CHANNEL_A_HT; if (pBssInfo->enableHT40 == 1) { channelFlags |= CHANNEL_HT40; } } else { channelFlags = CHANNEL_A; } } else { if ( (pBssInfo->EnableHT == 1) || (pBssInfo->apCap & ZM_All11N_AP) ) //11n AP { channelFlags = CHANNEL_G_HT; if(pBssInfo->enableHT40 == 1) { channelFlags |= CHANNEL_HT40; } } else { if (pBssInfo->extSupportedRates[1] == 0) { channelFlags = CHANNEL_B; } else { channelFlags = CHANNEL_G; } } } if ( ((channelFlags == CHANNEL_B) && (wd->connectMode & ZM_BIT_0)) || ((channelFlags == CHANNEL_G) && (wd->connectMode & ZM_BIT_1)) || ((channelFlags == CHANNEL_A) && (wd->connectMode & ZM_BIT_2)) || ((channelFlags & CHANNEL_HT20) && (wd->connectMode & ZM_BIT_3)) ) { pBssInfo = pBssInfo->next; continue; } /* Skip if AP in blocking list */ if ((ret = zfStaIsApInBlockingList(dev, pBssInfo->bssid)) == TRUE) { zm_msg0_mm(ZM_LV_0, "Candidate AP in blocking List, skip if there's stilla choice!"); pNowBssInfo = pBssInfo; pBssInfo = pBssInfo->next; continue; } if ( pBssInfo->capability[0] & ZM_BIT_0 ) // check if infra-BSS { pNowBssInfo = pBssInfo; wd->sta.apWmeCapability = pBssInfo->wmeSupport; goto done; } } pBssInfo = pBssInfo->next; } done: if (pNowBssInfo != NULL) { zfwMemoryCopy((void*)candidateBss, (void*)pNowBssInfo, sizeof(struct zsBssInfo)); pNowBssInfo = candidateBss; } zmw_leave_critical_section(dev); return pNowBssInfo; } void zfInfraConnectNetwork(zdev_t* dev) { struct zsBssInfo* pBssInfo; struct zsBssInfo* pNowBssInfo=NULL; struct zsBssInfo candidateBss; //u16_t i, j=100, quality=10000; //u8_t ret=FALSE, apWepStatus; u8_t ret=FALSE; u16_t k; u8_t density = ZM_MPDU_DENSITY_NONE; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); /* Reset bssNotFoundCount for Ad-Hoc:IBSS */ /* Need review : IbssConn -> InfraConn -> IbssConn etc, flag/counter reset? */ zmw_enter_critical_section(dev); wd->sta.bssNotFoundCount = 0; zmw_leave_critical_section(dev); /* Set TxQs CWMIN, CWMAX, AIFS and TXO to WME STA default. */ zfUpdateDefaultQosParameter(dev, 0); zfStaRefreshBlockList(dev, 0); /* change state to CONNECTING and stop the channel scanning */ zfChangeAdapterState(dev, ZM_STA_STATE_CONNECTING); zfPowerSavingMgrWakeup(dev); wd->sta.wmeConnected = 0; wd->sta.psMgr.tempWakeUp = 0; wd->sta.qosInfo = 0; zfQueueFlush(dev, wd->sta.uapsdQ); wd->sta.connectState = ZM_STA_CONN_STATE_NONE; //Reorder BssList by RSSI--CWYang(+) zfBssInfoReorderList(dev); pNowBssInfo = zfInfraFindAPToConnect(dev, &candidateBss); if (wd->sta.SWEncryptEnable != 0) { if (wd->sta.bSafeMode == 0) { zfStaDisableSWEncryption(dev);//Quickly reboot } } if ( pNowBssInfo != NULL ) { //zm_assert(pNowBssInfo != NULL); pBssInfo = pNowBssInfo; wd->sta.ssidLen = pBssInfo->ssid[1]; zfMemoryCopy(wd->sta.ssid, &(pBssInfo->ssid[2]), pBssInfo->ssid[1]); wd->frequency = pBssInfo->frequency; //wd->sta.flagFreqChanging = 1; //zfCoreSetFrequency(dev, wd->frequency); zfUpdateBssid(dev, pBssInfo->bssid); zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_ZERO); zfUpdateSupportRate(dev, pBssInfo->supportedRates); zfUpdateSupportRate(dev, pBssInfo->extSupportedRates); wd->beaconInterval = pBssInfo->beaconInterval[0] + (((u16_t) pBssInfo->beaconInterval[1]) << 8); if (wd->beaconInterval == 0) { wd->beaconInterval = 100; } /* ESS bit on */ wd->sta.capability[0] |= ZM_BIT_0; /* IBSS bit off */ wd->sta.capability[0] &= ~ZM_BIT_1; /* 11n AP flag */ wd->sta.EnableHT = pBssInfo->EnableHT; wd->sta.SG40 = pBssInfo->SG40; #ifdef ZM_ENABLE_CENC if ( pBssInfo->securityType == ZM_SECURITY_TYPE_CENC ) { wd->sta.wmeEnabled = 0; //Disable WMM in CENC cencInit(dev); cencSetCENCMode(dev, NdisCENC_PSK); wd->sta.wpaState = ZM_STA_WPA_STATE_INIT; /* CENC */ if ( pBssInfo->cencIe[1] != 0 ) { //wd->sta.wepStatus = ZM_ENCRYPTION_CENC; //wd->sta.encryMode = ZM_CENC; zfwCencHandleBeaconProbrespon(dev, (u8_t *)&pBssInfo->cencIe, (u8_t *)&pBssInfo->ssid, (u8_t *)&pBssInfo->macaddr); zfMemoryCopy(wd->sta.cencIe, pBssInfo->cencIe, pBssInfo->cencIe[1]+2); } else { wd->sta.cencIe[1] = 0; } } #endif //ZM_ENABLE_CENC if ( pBssInfo->securityType == ZM_SECURITY_TYPE_WPA ) { wd->sta.wpaState = ZM_STA_WPA_STATE_INIT; if ( wd->sta.wepStatus == ZM_ENCRYPTION_TKIP ) { wd->sta.encryMode = ZM_TKIP; /* Turn on software encryption/decryption for TKIP */ if (wd->sta.EnableHT == 1) { zfStaEnableSWEncryption(dev, (ZM_SW_TKIP_ENCRY_EN|ZM_SW_TKIP_DECRY_EN)); } /* Do not support TKIP in 11n mode */ //wd->sta.EnableHT = 0; //pBssInfo->enableHT40 = 0; } else if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES ) { wd->sta.encryMode = ZM_AES; /* If AP supports HT mode */ if (wd->sta.EnableHT) { /* Set MPDU density to 8 us*/ density = ZM_MPDU_DENSITY_8US; } } if ( pBssInfo->wpaIe[1] != 0 ) { zfMemoryCopy(wd->sta.wpaIe, pBssInfo->wpaIe, pBssInfo->wpaIe[1]+2); } else { wd->sta.wpaIe[1] = 0; } if ( pBssInfo->rsnIe[1] != 0 ) { zfMemoryCopy(wd->sta.rsnIe, pBssInfo->rsnIe, pBssInfo->rsnIe[1]+2); } else { wd->sta.rsnIe[1] = 0; } } /* check preamble bit */ wd->preambleTypeInUsed = wd->preambleType; if ( wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_AUTO ) { if (pBssInfo->capability[0] & ZM_BIT_5) { wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_SHORT; } else { wd->preambleTypeInUsed = ZM_PREAMBLE_TYPE_LONG; } } if (wd->preambleTypeInUsed == ZM_PREAMBLE_TYPE_LONG) { wd->sta.capability[0] &= ~ZM_BIT_5; } else { wd->sta.capability[0] |= ZM_BIT_5; } /* check 802.11n 40MHz Setting */ if ((pBssInfo->enableHT40 == 1) && ((pBssInfo->extChOffset == 1) || (pBssInfo->extChOffset == 3))) { wd->BandWidth40 = pBssInfo->enableHT40; wd->ExtOffset = pBssInfo->extChOffset; } else { wd->BandWidth40 = 0; wd->ExtOffset = 0; } /* check 802.11H support bit */ /* check Owl Ap */ if ( pBssInfo->athOwlAp & ZM_BIT_0 ) { /* In this function, FW retry will be enable, ZM_MAC_REG_RETRY_MAX will be set to 0. */ zfHpDisableHwRetry(dev); wd->sta.athOwlAp = 1; /* Set MPDU density to 8 us*/ density = ZM_MPDU_DENSITY_8US; } else { /* In this function, FW retry will be disable, ZM_MAC_REG_RETRY_MAX will be set to 3. */ zfHpEnableHwRetry(dev); wd->sta.athOwlAp = 0; } wd->reorder = 1; /* Set MPDU density */ zfHpSetMPDUDensity(dev, density); /* check short slot time bit */ if ( pBssInfo->capability[1] & ZM_BIT_2 ) { wd->sta.capability[1] |= ZM_BIT_2; } if ( pBssInfo->erp & ZM_BIT_1 ) { //zm_debug_msg0("protection mode on"); wd->sta.bProtectionMode = TRUE; zfHpSetSlotTime(dev, 0); } else { //zm_debug_msg0("protection mode off"); wd->sta.bProtectionMode = FALSE; zfHpSetSlotTime(dev, 1); } if (pBssInfo->marvelAp == 1) { wd->sta.enableDrvBA = 0; /* * 8701 : NetGear 3500 (MARVELL) * Downlink issue : set slottime to 20. */ zfHpSetSlotTimeRegister(dev, 0); } else { wd->sta.enableDrvBA = 1; /* * This is not good for here do reset slot time. * I think it should reset when leave MARVELL ap * or enter disconnect state etc. */ zfHpSetSlotTimeRegister(dev, 1); } //Store probe response frame body, for VISTA only wd->sta.beaconFrameBodySize = pBssInfo->frameBodysize + 12; if (wd->sta.beaconFrameBodySize > ZM_CACHED_FRAMEBODY_SIZE) { wd->sta.beaconFrameBodySize = ZM_CACHED_FRAMEBODY_SIZE; } for (k=0; k<8; k++) { wd->sta.beaconFrameBody[k] = pBssInfo->timeStamp[k]; } wd->sta.beaconFrameBody[8] = pBssInfo->beaconInterval[0]; wd->sta.beaconFrameBody[9] = pBssInfo->beaconInterval[1]; wd->sta.beaconFrameBody[10] = pBssInfo->capability[0]; wd->sta.beaconFrameBody[11] = pBssInfo->capability[1]; for (k=0; k<(wd->sta.beaconFrameBodySize - 12); k++) { wd->sta.beaconFrameBody[k+12] = pBssInfo->frameBody[k]; } if ( ( pBssInfo->capability[0] & ZM_BIT_4 )&& (( wd->sta.authMode == ZM_AUTH_MODE_OPEN )|| ( wd->sta.authMode == ZM_AUTH_MODE_SHARED_KEY)|| (wd->sta.authMode == ZM_AUTH_MODE_AUTO)) ) { /* privacy enabled */ if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_DISABLED ) { zm_debug_msg0("Adapter is no WEP, try to connect to WEP AP"); ret = FALSE; } /* Do not support WEP in 11n mode */ if ( wd->sta.wepStatus == ZM_ENCRYPTION_WEP_ENABLED ) { /* Turn on software encryption/decryption for WEP */ if (wd->sta.EnableHT == 1) { zfStaEnableSWEncryption(dev, (ZM_SW_WEP_ENCRY_EN|ZM_SW_WEP_DECRY_EN)); } //wd->sta.EnableHT = 0; //wd->BandWidth40 = 0; //wd->ExtOffset = 0; } wd->sta.capability[0] |= ZM_BIT_4; if ( wd->sta.authMode == ZM_AUTH_MODE_AUTO ) { /* Try to use open and shared-key authehtication alternatively */ if ( (wd->sta.connectTimeoutCount % 2) == 0 ) wd->sta.bIsSharedKey = 0; else wd->sta.bIsSharedKey = 1; } else if ( wd->sta.authMode != ZM_AUTH_MODE_SHARED_KEY ) { /* open or auto */ //zfStaStartConnect(dev, 0); wd->sta.bIsSharedKey = 0; } else if ( wd->sta.authMode != ZM_AUTH_MODE_OPEN ) { /* shared key */ //zfStaStartConnect(dev, 1) ; wd->sta.bIsSharedKey = 1; } } else { if ( (pBssInfo->securityType == ZM_SECURITY_TYPE_WPA)|| (pBssInfo->capability[0] & ZM_BIT_4) ) { wd->sta.capability[0] |= ZM_BIT_4; /* initialize WPA related parameters */ } else { wd->sta.capability[0] &= (~ZM_BIT_4); } /* authentication with open system */ //zfStaStartConnect(dev, 0); wd->sta.bIsSharedKey = 0; } /* Improve WEP/TKIP performace with HT AP, detail information please look bug#32495 */ /* if ( (pBssInfo->broadcomHTAp == 1) && (wd->sta.SWEncryptEnable != 0) ) { zfHpSetTTSIFSTime(dev, 0xa); } else { zfHpSetTTSIFSTime(dev, 0x8); } */ } else { zm_debug_msg0("Desired SSID not found"); goto zlConnectFailed; } zfCoreSetFrequencyV2(dev, wd->frequency, zfStaStartConnectCb); return; zlConnectFailed: zfStaConnectFail(dev, ZM_STATUS_MEDIA_DISCONNECT_NOT_FOUND, wd->sta.bssid, 0); return; } u8_t zfCheckWPAAuth(zdev_t* dev, struct zsBssInfo* pBssInfo) { u8_t ret=TRUE; u8_t pmkCount; u8_t i; u16_t encAlgoType = 0; zmw_get_wlan_dev(dev); if ( wd->sta.wepStatus == ZM_ENCRYPTION_TKIP ) { encAlgoType = ZM_TKIP; } else if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES ) { encAlgoType = ZM_AES; } switch(wd->sta.authMode) { case ZM_AUTH_MODE_WPA: case ZM_AUTH_MODE_WPAPSK: if ( pBssInfo->wpaIe[1] == 0 ) { ret = FALSE; break; } pmkCount = pBssInfo->wpaIe[12]; for(i=0; i < pmkCount; i++) { if ( pBssInfo->wpaIe[17 + 4*i] == encAlgoType ) { ret = TRUE; goto done; } } ret = FALSE; break; case ZM_AUTH_MODE_WPA2: case ZM_AUTH_MODE_WPA2PSK: if ( pBssInfo->rsnIe[1] == 0 ) { ret = FALSE; break; } pmkCount = pBssInfo->rsnIe[8]; for(i=0; i < pmkCount; i++) { if ( pBssInfo->rsnIe[13 + 4*i] == encAlgoType ) { ret = TRUE; goto done; } } ret = FALSE; break; } done: return ret; } u8_t zfCheckAuthentication(zdev_t* dev, struct zsBssInfo* pBssInfo) { u8_t ret=TRUE; u16_t encAlgoType; u16_t UnicastCipherNum; zmw_get_wlan_dev(dev); /* Connecting to ANY has been checked */ if ( wd->sta.ssidLen == 0 ) { return ret; } switch(wd->sta.authMode) //switch(wd->ws.authMode)//Quickly reboot { case ZM_AUTH_MODE_WPA_AUTO: case ZM_AUTH_MODE_WPAPSK_AUTO: encAlgoType = 0; if(pBssInfo->rsnIe[1] != 0) { UnicastCipherNum = (pBssInfo->rsnIe[8]) + (pBssInfo->rsnIe[9] << 8); /* If there is only one unicast cipher */ if (UnicastCipherNum == 1) { encAlgoType = pBssInfo->rsnIe[13]; //encAlgoType = pBssInfo->rsnIe[7]; } else { u16_t ii; u16_t desiredCipher = 0; u16_t IEOffSet = 13; /* Enumerate all the supported unicast cipher */ for (ii = 0; ii < UnicastCipherNum; ii++) { if (pBssInfo->rsnIe[IEOffSet+ii*4] > desiredCipher) { desiredCipher = pBssInfo->rsnIe[IEOffSet+ii*4]; } } encAlgoType = desiredCipher; } if ( encAlgoType == 0x02 ) { wd->sta.wepStatus = ZM_ENCRYPTION_TKIP; if ( wd->sta.authMode == ZM_AUTH_MODE_WPA_AUTO ) { wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA2; } else //ZM_AUTH_MODE_WPAPSK_AUTO { wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA2PSK; } } else if ( encAlgoType == 0x04 ) { wd->sta.wepStatus = ZM_ENCRYPTION_AES; if ( wd->sta.authMode == ZM_AUTH_MODE_WPA_AUTO ) { wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA2; } else //ZM_AUTH_MODE_WPAPSK_AUTO { wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA2PSK; } } else { ret = FALSE; } } else if(pBssInfo->wpaIe[1] != 0) { UnicastCipherNum = (pBssInfo->wpaIe[12]) + (pBssInfo->wpaIe[13] << 8); /* If there is only one unicast cipher */ if (UnicastCipherNum == 1) { encAlgoType = pBssInfo->wpaIe[17]; //encAlgoType = pBssInfo->wpaIe[11]; } else { u16_t ii; u16_t desiredCipher = 0; u16_t IEOffSet = 17; /* Enumerate all the supported unicast cipher */ for (ii = 0; ii < UnicastCipherNum; ii++) { if (pBssInfo->wpaIe[IEOffSet+ii*4] > desiredCipher) { desiredCipher = pBssInfo->wpaIe[IEOffSet+ii*4]; } } encAlgoType = desiredCipher; } if ( encAlgoType == 0x02 ) { wd->sta.wepStatus = ZM_ENCRYPTION_TKIP; if ( wd->sta.authMode == ZM_AUTH_MODE_WPA_AUTO ) { wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA; } else //ZM_AUTH_MODE_WPAPSK_AUTO { wd->sta.currentAuthMode = ZM_AUTH_MODE_WPAPSK; } } else if ( encAlgoType == 0x04 ) { wd->sta.wepStatus = ZM_ENCRYPTION_AES; if ( wd->sta.authMode == ZM_AUTH_MODE_WPA_AUTO ) { wd->sta.currentAuthMode = ZM_AUTH_MODE_WPA; } else //ZM_AUTH_MODE_WPAPSK_AUTO { wd->sta.currentAuthMode = ZM_AUTH_MODE_WPAPSK; } } else { ret = FALSE; } } else { ret = FALSE; } break; case ZM_AUTH_MODE_WPA: case ZM_AUTH_MODE_WPAPSK: case ZM_AUTH_MODE_WPA_NONE: case ZM_AUTH_MODE_WPA2: case ZM_AUTH_MODE_WPA2PSK: { if ( pBssInfo->securityType != ZM_SECURITY_TYPE_WPA ) { ret = FALSE; } ret = zfCheckWPAAuth(dev, pBssInfo); } break; case ZM_AUTH_MODE_OPEN: case ZM_AUTH_MODE_SHARED_KEY: case ZM_AUTH_MODE_AUTO: { if ( pBssInfo->wscIe[1] ) { // If the AP is a Jumpstart AP, it's ok!! Ray break; } else if ( pBssInfo->securityType == ZM_SECURITY_TYPE_WPA ) { ret = FALSE; } } break; default: break; } return ret; } u8_t zfStaIsConnected(zdev_t* dev) { zmw_get_wlan_dev(dev); if ( wd->sta.adapterState == ZM_STA_STATE_CONNECTED ) { return TRUE; } return FALSE; } u8_t zfStaIsConnecting(zdev_t* dev) { zmw_get_wlan_dev(dev); if ( wd->sta.adapterState == ZM_STA_STATE_CONNECTING ) { return TRUE; } return FALSE; } u8_t zfStaIsDisconnect(zdev_t* dev) { zmw_get_wlan_dev(dev); if ( wd->sta.adapterState == ZM_STA_STATE_DISCONNECT ) { return TRUE; } return FALSE; } u8_t zfChangeAdapterState(zdev_t* dev, u8_t newState) { u8_t ret = TRUE; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); //if ( newState == wd->sta.adapterState ) //{ // return FALSE; //} switch(newState) { case ZM_STA_STATE_DISCONNECT: zfResetSupportRate(dev, ZM_DEFAULT_SUPPORT_RATE_DISCONNECT); #if 1 zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL); #else if ( wd->sta.bChannelScan ) { /* stop the action of channel scanning */ wd->sta.bChannelScan = FALSE; ret = TRUE; break; } #endif break; case ZM_STA_STATE_CONNECTING: #if 1 zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL); #else if ( wd->sta.bChannelScan ) { /* stop the action of channel scanning */ wd->sta.bChannelScan = FALSE; ret = TRUE; break; } #endif break; case ZM_STA_STATE_CONNECTED: break; default: break; } //if ( ret ) //{ zmw_enter_critical_section(dev); wd->sta.adapterState = newState; zmw_leave_critical_section(dev); zm_debug_msg1("change adapter state = ", newState); //} return ret; } /************************************************************************/ /* */ /* FUNCTION DESCRIPTION zfStaMmAddIeSsid */ /* Add information element SSID to buffer. */ /* */ /* INPUTS */ /* dev : device pointer */ /* buf : buffer to add information element */ /* offset : add information element from this offset */ /* */ /* OUTPUTS */ /* buffer offset after adding information element */ /* */ /* AUTHOR */ /* Ji-Huang Lee ZyDAS Technology Corporation 2005.11 */ /* */ /************************************************************************/ u16_t zfStaAddIeSsid(zdev_t* dev, zbuf_t* buf, u16_t offset) { u16_t i; zmw_get_wlan_dev(dev); /* Element ID */ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SSID); /* Element Length */ zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.ssidLen); /* Information : SSID */ for (i=0; ista.ssidLen; i++) { zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.ssid[i]); } return offset; } /************************************************************************/ /* */ /* FUNCTION DESCRIPTION zfStaMmAddIeWpa */ /* Add information element SSID to buffer. */ /* */ /* INPUTS */ /* dev : device pointer */ /* buf : buffer to add information element */ /* offset : add information element from this offset */ /* */ /* OUTPUTS */ /* buffer offset after adding information element */ /* */ /* AUTHOR */ /* Ji-Huang Lee ZyDAS Technology Corporation 2006.01 */ /* */ /************************************************************************/ u16_t zfStaAddIeWpaRsn(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t frameType) { u32_t i; u8_t ssn[64]={ /* Element ID */ 0xdd, /* Length */ 0x18, /* OUI type */ 0x00, 0x50, 0xf2, 0x01, /* Version */ 0x01, 0x00, /* Group Cipher Suite, default=TKIP */ 0x00, 0x50, 0xf2, 0x02, /* Pairwise Cipher Suite Count */ 0x01, 0x00, /* Pairwise Cipher Suite, default=TKIP */ 0x00, 0x50, 0xf2, 0x02, /* Authentication and Key Management Suite Count */ 0x01, 0x00, /* Authentication type, default=PSK */ 0x00, 0x50, 0xf2, 0x02, /* WPA capability */ 0x00, 0x00 }; u8_t rsn[64]={ /* Element ID */ 0x30, /* Length */ 0x14, /* Version */ 0x01, 0x00, /* Group Cipher Suite, default=TKIP */ 0x00, 0x0f, 0xac, 0x02, /* Pairwise Cipher Suite Count */ 0x01, 0x00, /* Pairwise Cipher Suite, default=TKIP */ 0x00, 0x0f, 0xac, 0x02, /* Authentication and Key Management Suite Count */ 0x01, 0x00, /* Authentication type, default=PSK */ 0x00, 0x0f, 0xac, 0x02, /* RSN capability */ 0x00, 0x00 }; zmw_get_wlan_dev(dev); if ( wd->sta.currentAuthMode == ZM_AUTH_MODE_WPAPSK ) { /* Overwrite Group Cipher Suite by AP's setting */ zfMemoryCopy(ssn+8, wd->sta.wpaIe+8, 4); if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES ) { /* Overwrite Pairwise Cipher Suite by AES */ zfMemoryCopy(ssn+14, zgWpaAesOui, 4); } zfCopyToIntTxBuffer(dev, buf, ssn, offset, ssn[1]+2); zfMemoryCopy(wd->sta.wpaIe, ssn, ssn[1]+2); offset += (ssn[1]+2); } else if ( wd->sta.currentAuthMode == ZM_AUTH_MODE_WPA ) { /* Overwrite Group Cipher Suite by AP's setting */ zfMemoryCopy(ssn+8, wd->sta.wpaIe+8, 4); /* Overwrite Key Management Suite by WPA-Radius */ zfMemoryCopy(ssn+20, zgWpaRadiusOui, 4); if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES ) { /* Overwrite Pairwise Cipher Suite by AES */ zfMemoryCopy(ssn+14, zgWpaAesOui, 4); } zfCopyToIntTxBuffer(dev, buf, ssn, offset, ssn[1]+2); zfMemoryCopy(wd->sta.wpaIe, ssn, ssn[1]+2); offset += (ssn[1]+2); } else if ( wd->sta.currentAuthMode == ZM_AUTH_MODE_WPA2PSK ) { /* Overwrite Group Cipher Suite by AP's setting */ zfMemoryCopy(rsn+4, wd->sta.rsnIe+4, 4); if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES ) { /* Overwrite Pairwise Cipher Suite by AES */ zfMemoryCopy(rsn+10, zgWpa2AesOui, 4); } if ( frameType == ZM_WLAN_FRAME_TYPE_REASOCREQ ) { for(i=0; ista.pmkidInfo.bssidCount; i++) { if ( zfMemoryIsEqual((u8_t*) wd->sta.pmkidInfo.bssidInfo[i].bssid, (u8_t*) wd->sta.bssid, 6) ) { /* matched */ break; } if ( i < wd->sta.pmkidInfo.bssidCount ) { // Fill PMKID Count in RSN information element rsn[22] = 0x01; rsn[23] = 0x00; // Fill PMKID in RSN information element zfMemoryCopy(rsn+24, wd->sta.pmkidInfo.bssidInfo[i].pmkid, 16); rsn[1] += 18; } } } zfCopyToIntTxBuffer(dev, buf, rsn, offset, rsn[1]+2); zfMemoryCopy(wd->sta.rsnIe, rsn, rsn[1]+2); offset += (rsn[1]+2); } else if ( wd->sta.currentAuthMode == ZM_AUTH_MODE_WPA2 ) { /* Overwrite Group Cipher Suite by AP's setting */ zfMemoryCopy(rsn+4, wd->sta.rsnIe+4, 4); /* Overwrite Key Management Suite by WPA2-Radius */ zfMemoryCopy(rsn+16, zgWpa2RadiusOui, 4); if ( wd->sta.wepStatus == ZM_ENCRYPTION_AES ) { /* Overwrite Pairwise Cipher Suite by AES */ zfMemoryCopy(rsn+10, zgWpa2AesOui, 4); } if (( frameType == ZM_WLAN_FRAME_TYPE_REASOCREQ || ( frameType == ZM_WLAN_FRAME_TYPE_ASOCREQ ))) { if (wd->sta.pmkidInfo.bssidCount != 0) { // Fill PMKID Count in RSN information element rsn[22] = 1; rsn[23] = 0; /* * The caller is respnsible to give us the relevant PMKID. * We'll only accept 1 PMKID for now. */ for(i=0; ista.pmkidInfo.bssidCount; i++) { if ( zfMemoryIsEqual((u8_t*) wd->sta.pmkidInfo.bssidInfo[i].bssid, (u8_t*) wd->sta.bssid, 6) ) { zfMemoryCopy(rsn+24, wd->sta.pmkidInfo.bssidInfo[i].pmkid, 16); break; } } rsn[1] += 18; } } zfCopyToIntTxBuffer(dev, buf, rsn, offset, rsn[1]+2); zfMemoryCopy(wd->sta.rsnIe, rsn, rsn[1]+2); offset += (rsn[1]+2); } return offset; } /************************************************************************/ /* */ /* FUNCTION DESCRIPTION zfStaAddIeIbss */ /* Add information element IBSS parameter to buffer. */ /* */ /* INPUTS */ /* dev : device pointer */ /* buf : buffer to add information element */ /* offset : add information element from this offset */ /* */ /* OUTPUTS */ /* buffer offset after adding information element */ /* */ /* AUTHOR */ /* Ji-Huang Lee ZyDAS Technology Corporation 2005.12 */ /* */ /************************************************************************/ u16_t zfStaAddIeIbss(zdev_t* dev, zbuf_t* buf, u16_t offset) { zmw_get_wlan_dev(dev); /* Element ID */ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_IBSS); /* Element Length */ zmw_tx_buf_writeb(dev, buf, offset++, 2); /* ATIM window */ zmw_tx_buf_writeh(dev, buf, offset, wd->sta.atimWindow); offset += 2; return offset; } /************************************************************************/ /* */ /* FUNCTION DESCRIPTION zfStaAddIeWmeInfo */ /* Add WME Information Element to buffer. */ /* */ /* INPUTS */ /* dev : device pointer */ /* buf : buffer to add information element */ /* offset : add information element from this offset */ /* */ /* OUTPUTS */ /* buffer offset after adding information element */ /* */ /* AUTHOR */ /* Stephen Chen ZyDAS Technology Corporation 2006.6 */ /* */ /************************************************************************/ u16_t zfStaAddIeWmeInfo(zdev_t* dev, zbuf_t* buf, u16_t offset, u8_t qosInfo) { /* Element ID */ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_WIFI_IE); /* Element Length */ zmw_tx_buf_writeb(dev, buf, offset++, 7); /* OUI */ zmw_tx_buf_writeb(dev, buf, offset++, 0x00); zmw_tx_buf_writeb(dev, buf, offset++, 0x50); zmw_tx_buf_writeb(dev, buf, offset++, 0xF2); zmw_tx_buf_writeb(dev, buf, offset++, 0x02); zmw_tx_buf_writeb(dev, buf, offset++, 0x00); zmw_tx_buf_writeb(dev, buf, offset++, 0x01); /* QoS Info */ zmw_tx_buf_writeb(dev, buf, offset++, qosInfo); return offset; } /************************************************************************/ /* */ /* FUNCTION DESCRIPTION zfStaAddIePowerCap */ /* Add information element Power capability to buffer. */ /* */ /* INPUTS */ /* dev : device pointer */ /* buf : buffer to add information element */ /* offset : add information element from this offset */ /* */ /* OUTPUTS */ /* buffer offset after adding information element */ /* */ /* AUTHOR */ /* Sharon 2007.12 */ /* */ /************************************************************************/ u16_t zfStaAddIePowerCap(zdev_t* dev, zbuf_t* buf, u16_t offset) { u8_t MaxTxPower; u8_t MinTxPower; zmw_get_wlan_dev(dev); /* Element ID */ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_POWER_CAPABILITY); /* Element Length */ zmw_tx_buf_writeb(dev, buf, offset++, 2); MinTxPower = (u8_t)(zfHpGetMinTxPower(dev)/2); MaxTxPower = (u8_t)(zfHpGetMaxTxPower(dev)/2); /* Min Transmit Power Cap */ zmw_tx_buf_writeh(dev, buf, offset++, MinTxPower); /* Max Transmit Power Cap */ zmw_tx_buf_writeh(dev, buf, offset++, MaxTxPower); return offset; } /************************************************************************/ /* */ /* FUNCTION DESCRIPTION zfStaAddIeSupportCh */ /* Add information element supported channels to buffer. */ /* */ /* INPUTS */ /* dev : device pointer */ /* buf : buffer to add information element */ /* offset : add information element from this offset */ /* */ /* OUTPUTS */ /* buffer offset after adding information element */ /* */ /* AUTHOR */ /* Sharon 2007.12 */ /* */ /************************************************************************/ u16_t zfStaAddIeSupportCh(zdev_t* dev, zbuf_t* buf, u16_t offset) { u8_t i; u16_t count_24G = 0; u16_t count_5G = 0; u16_t channelNum; u8_t length; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); zmw_enter_critical_section(dev); for (i = 0; i < wd->regulationTable.allowChannelCnt; i++) { if (wd->regulationTable.allowChannel[i].channel < 3000) { // 2.4Hz count_24G++; } else { // 5GHz count_5G++; } } length = (u8_t)(count_5G * 2 + 2); //5G fill by pair, 2,4G (continuous channels) fill 2 bytes /* Element ID */ zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_SUPPORTED_CHANNELS ); /* Element Length */ zmw_tx_buf_writeb(dev, buf, offset++, length); // 2.4GHz (continuous channels) /* First channel number */ zmw_tx_buf_writeh(dev, buf, offset++, 1); //Start from channle 1 /* Number of channels */ zmw_tx_buf_writeh(dev, buf, offset++, count_24G); for (i = 0; i < wd->regulationTable.allowChannelCnt ; i++) { if (wd->regulationTable.allowChannel[i].channel > 4000 && wd->regulationTable.allowChannel[i].channel < 5000) { // 5GHz 4000 -5000Mhz channelNum = (wd->regulationTable.allowChannel[i].channel-4000)/5; /* First channel number */ zmw_tx_buf_writeh(dev, buf, offset++, channelNum); /* Number of channels */ zmw_tx_buf_writeh(dev, buf, offset++, 1); } else if (wd->regulationTable.allowChannel[i].channel >= 5000) { // 5GHz >5000Mhz channelNum = (wd->regulationTable.allowChannel[i].channel-5000)/5; /* First channel number */ zmw_tx_buf_writeh(dev, buf, offset++, channelNum); /* Number of channels */ zmw_tx_buf_writeh(dev, buf, offset++, 1); } } zmw_leave_critical_section(dev); return offset; } void zfStaStartConnectCb(zdev_t* dev) { zmw_get_wlan_dev(dev); zfStaStartConnect(dev, wd->sta.bIsSharedKey); } void zfStaStartConnect(zdev_t* dev, u8_t bIsSharedKey) { u32_t p1, p2; u8_t newConnState; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); /* p1_low = algorithm number, p1_high = transaction sequence number */ if ( bIsSharedKey ) { //wd->sta.connectState = ZM_STA_CONN_STATE_AUTH_SHARE_1; newConnState = ZM_STA_CONN_STATE_AUTH_SHARE_1; zm_debug_msg0("ZM_STA_CONN_STATE_AUTH_SHARE_1"); p1 = ZM_AUTH_ALGO_SHARED_KEY; } else { //wd->sta.connectState = ZM_STA_CONN_STATE_AUTH_OPEN; newConnState = ZM_STA_CONN_STATE_AUTH_OPEN; zm_debug_msg0("ZM_STA_CONN_STATE_AUTH_OPEN"); if( wd->sta.leapEnabled ) p1 = ZM_AUTH_ALGO_LEAP; else p1 = ZM_AUTH_ALGO_OPEN_SYSTEM; } /* status code */ p2 = 0x0; zmw_enter_critical_section(dev); wd->sta.connectTimer = wd->tick; wd->sta.connectState = newConnState; zmw_leave_critical_section(dev); /* send the 1st authentication frame */ zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_AUTH, wd->sta.bssid, p1, p2, 0); return; } void zfSendNullData(zdev_t* dev, u8_t type) { zbuf_t* buf; //u16_t addrTblSize; //struct zsAddrTbl addrTbl; u16_t err; u16_t hlen; u16_t header[(34+8+1)/2]; u16_t bcastAddr[3] = {0xffff,0xffff,0xffff}; u16_t *dstAddr; zmw_get_wlan_dev(dev); if ((buf = zfwBufAllocate(dev, 1024)) == NULL) { zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!"); return; } zfwBufSetSize(dev, buf, 0); //zm_msg2_mm(ZM_LV_2, "buf->len=", buf->len); if ( wd->wlanMode == ZM_MODE_IBSS) { dstAddr = bcastAddr; } else { dstAddr = wd->sta.bssid; } if (wd->sta.wmeConnected != 0) { /* If connect to a WMM AP, Send QoS Null data */ hlen = zfTxGenMmHeader(dev, ZM_WLAN_FRAME_TYPE_QOS_NULL, dstAddr, header, 0, buf, 0, 0); } else { hlen = zfTxGenMmHeader(dev, ZM_WLAN_FRAME_TYPE_NULL, dstAddr, header, 0, buf, 0, 0); } if (wd->wlanMode == ZM_MODE_INFRASTRUCTURE) { header[4] |= 0x0100; //TODS bit } if ( type == 1 ) { header[4] |= 0x1000; } /* Get buffer DMA address */ //if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0) //if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0) //{ // goto zlError; //} /*increase unicast frame counter*/ wd->commTally.txUnicastFrm++; if ((err = zfHpSend(dev, header, hlen, NULL, 0, NULL, 0, buf, 0, ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS) { goto zlError; } return; zlError: zfwBufFree(dev, buf, 0); return; } void zfSendPSPoll(zdev_t* dev) { zbuf_t* buf; //u16_t addrTblSize; //struct zsAddrTbl addrTbl; u16_t err; u16_t hlen; u16_t header[(8+24+1)/2]; zmw_get_wlan_dev(dev); if ((buf = zfwBufAllocate(dev, 1024)) == NULL) { zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!"); return; } zfwBufSetSize(dev, buf, 0); //zm_msg2_mm(ZM_LV_2, "buf->len=", buf->len); zfTxGenMmHeader(dev, ZM_WLAN_FRAME_TYPE_PSPOLL, wd->sta.bssid, header, 0, buf, 0, 0); header[0] = 20; header[4] |= 0x1000; header[5] = wd->sta.aid | 0xc000; //Both bit-14 and bit-15 are 1 hlen = 16 + 8; /* Get buffer DMA address */ //if ((addrTblSize = zfwBufMapDma(dev, buf, &addrTbl)) == 0) //if ((addrTblSize = zfwMapTxDma(dev, buf, &addrTbl)) == 0) //{ // goto zlError; //} if ((err = zfHpSend(dev, header, hlen, NULL, 0, NULL, 0, buf, 0, ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS) { goto zlError; } return; zlError: zfwBufFree(dev, buf, 0); return; } void zfSendBA(zdev_t* dev, u16_t start_seq, u8_t *bitmap) { zbuf_t* buf; //u16_t addrTblSize; //struct zsAddrTbl addrTbl; u16_t err; u16_t hlen; u16_t header[(8+24+1)/2]; u16_t i, offset = 0; zmw_get_wlan_dev(dev); if ((buf = zfwBufAllocate(dev, 1024)) == NULL) { zm_msg0_mm(ZM_LV_0, "Alloc mm buf Fail!"); return; } zfwBufSetSize(dev, buf, 12); // 28 = FC 2 + DU 2 + RA 6 + TA 6 + BAC 2 + SEQ 2 + BitMap 8 // 12 = BAC 2 + SEQ 2 + BitMap 8 //zm_msg2_mm(ZM_LV_2, "buf->len=", buf->len); zfTxGenMmHeader(dev, ZM_WLAN_FRAME_TYPE_BA, wd->sta.bssid, header, 0, buf, 0, 0); header[0] = 32; /* MAC header 16 + BA control 2 + BA info 10 + FCS 4*/ header[1] = 0x4; /* No ACK */ /* send by OFDM 6M */ header[2] = (u16_t)(zcRateToPhyCtrl[4] & 0xffff); header[3] = (u16_t)(zcRateToPhyCtrl[4]>>16) & 0xffff; hlen = 16 + 8; /* MAC header 16 + control 8*/ offset = 0; zmw_tx_buf_writeh(dev, buf, offset, 0x05); /*compressed bitmap on*/ offset+=2; zmw_tx_buf_writeh(dev, buf, offset, start_seq); offset+=2; for (i=0; i<8; i++) { zmw_tx_buf_writeb(dev, buf, offset, bitmap[i]); offset++; } if ((err = zfHpSend(dev, header, hlen, NULL, 0, NULL, 0, buf, 0, ZM_INTERNAL_ALLOC_BUF, 0, 0xff)) != ZM_SUCCESS) { goto zlError; } return; zlError: zfwBufFree(dev, buf, 0); return; } void zfStaGetTxRate(zdev_t* dev, u16_t* macAddr, u32_t* phyCtrl, u16_t* rcProbingFlag) { u8_t addr[6], i; u8_t rate; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); ZM_MAC_WORD_TO_BYTE(macAddr, addr); *phyCtrl = 0; if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) { zmw_enter_critical_section(dev); rate = (u8_t)zfRateCtrlGetTxRate(dev, &wd->sta.oppositeInfo[0].rcCell, rcProbingFlag); //#ifdef ZM_FB50 //rate = 27; //#endif *phyCtrl = zcRateToPhyCtrl[rate]; zmw_leave_critical_section(dev); } else { zmw_enter_critical_section(dev); for(i=0; ista.oppositeCount; i++) { if ( addr[0] && 0x01 == 1 ) // The default beacon transmitted rate is CCK and 1 Mbps , but the a mode should use // OFDM modulation and 6Mbps to transmit beacon. { //rate = (u8_t)zfRateCtrlGetTxRate(dev, &wd->sta.oppositeInfo[i].rcCell, rcProbingFlag); rate = wd->sta.oppositeInfo[i].rcCell.operationRateSet[0]; *phyCtrl = zcRateToPhyCtrl[rate]; break; } else if ( zfMemoryIsEqual(addr, wd->sta.oppositeInfo[i].macAddr, 6) ) { rate = (u8_t)zfRateCtrlGetTxRate(dev, &wd->sta.oppositeInfo[i].rcCell, rcProbingFlag); *phyCtrl = zcRateToPhyCtrl[rate]; break; } } zmw_leave_critical_section(dev); } return; } struct zsMicVar* zfStaGetRxMicKey(zdev_t* dev, zbuf_t* buf) { u8_t keyIndex; u8_t da0; zmw_get_wlan_dev(dev); /* if need not check MIC, return NULL */ if ( ((wd->sta.encryMode != ZM_TKIP)&&(wd->sta.encryMode != ZM_AES))|| (wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK) ) { return NULL; } da0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A1_OFFSET); if ((zmw_rx_buf_readb(dev, buf, 0) & 0x80) == 0x80) keyIndex = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_IV_OFFSET+5); /* Qos Packet*/ else keyIndex = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_IV_OFFSET+3); /* normal Packet*/ keyIndex = (keyIndex & 0xc0) >> 6; return (&wd->sta.rxMicKey[keyIndex]); } struct zsMicVar* zfStaGetTxMicKey(zdev_t* dev, zbuf_t* buf) { zmw_get_wlan_dev(dev); /* if need not check MIC, return NULL */ //if ( ((wd->sta.encryMode != ZM_TKIP)&&(wd->sta.encryMode != ZM_AES))|| // (wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK) ) if ( (wd->sta.encryMode != ZM_TKIP) || (wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK) ) { return NULL; } return (&wd->sta.txMicKey); } u16_t zfStaRxValidateFrame(zdev_t* dev, zbuf_t* buf) { u8_t frameType, frameCtrl; u8_t da0; //u16_t sa[3]; u16_t ret; u16_t i; //u8_t sa0; zmw_get_wlan_dev(dev); frameType = zmw_rx_buf_readb(dev, buf, 0); da0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A1_OFFSET); //sa0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A2_OFFSET); if ( (!zfStaIsConnected(dev))&&((frameType & 0xf) == ZM_WLAN_DATA_FRAME) ) { return ZM_ERR_DATA_BEFORE_CONNECTED; } if ( (zfStaIsConnected(dev))&&((frameType & 0xf) == ZM_WLAN_DATA_FRAME) ) { /* check BSSID */ if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) { /* Big Endian and Little Endian Compatibility */ u16_t mac[3]; mac[0] = zmw_cpu_to_le16(wd->sta.bssid[0]); mac[1] = zmw_cpu_to_le16(wd->sta.bssid[1]); mac[2] = zmw_cpu_to_le16(wd->sta.bssid[2]); if ( !zfRxBufferEqualToStr(dev, buf, (u8_t *)mac, ZM_WLAN_HEADER_A2_OFFSET, 6) ) { /*We will get lots of garbage data, especially in AES mode.*/ /*To avoid sending too many deauthentication frames in STA mode, mark it.*/ #if 0 /* If unicast frame, send deauth to the transmitter */ if (( da0 & 0x01 ) == 0) { for (i=0; i<3; i++) { sa[i] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET+(i*2)); } /* If mutilcast address, don't send deauthentication*/ if (( sa0 & 0x01 ) == 0) zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_DEAUTH, sa, 7, 0, 0); } #endif return ZM_ERR_DATA_BSSID_NOT_MATCHED; } } else if ( wd->wlanMode == ZM_MODE_IBSS ) { /* Big Endian and Little Endian Compatibility */ u16_t mac[3]; mac[0] = zmw_cpu_to_le16(wd->sta.bssid[0]); mac[1] = zmw_cpu_to_le16(wd->sta.bssid[1]); mac[2] = zmw_cpu_to_le16(wd->sta.bssid[2]); if ( !zfRxBufferEqualToStr(dev, buf, (u8_t *)mac, ZM_WLAN_HEADER_A3_OFFSET, 6) ) { return ZM_ERR_DATA_BSSID_NOT_MATCHED; } } frameCtrl = zmw_rx_buf_readb(dev, buf, 1); /* check security bit */ if ( wd->sta.dropUnencryptedPkts && (wd->sta.wepStatus != ZM_ENCRYPTION_WEP_DISABLED )&& ( !(frameCtrl & ZM_BIT_6) ) ) { /* security on, but got data without encryption */ #if 1 ret = ZM_ERR_DATA_NOT_ENCRYPTED; if ( wd->sta.pStaRxSecurityCheckCb != NULL ) { ret = wd->sta.pStaRxSecurityCheckCb(dev, buf); } else { ret = ZM_ERR_DATA_NOT_ENCRYPTED; } if (ret == ZM_ERR_DATA_NOT_ENCRYPTED) { wd->commTally.swRxDropUnencryptedCount++; } return ret; #else if ( (wd->sta.wepStatus != ZM_ENCRYPTION_TKIP)&& (wd->sta.wepStatus != ZM_ENCRYPTION_AES) ) { return ZM_ERR_DATA_NOT_ENCRYPTED; } #endif } } return ZM_SUCCESS; } void zfStaMicFailureHandling(zdev_t* dev, zbuf_t* buf) { u8_t da0; u8_t micNotify = 1; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); if ( wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK ) { return; } zmw_enter_critical_section(dev); wd->sta.cmMicFailureCount++; if ( wd->sta.cmMicFailureCount == 1 ) { zm_debug_msg0("get the first MIC failure"); //zfTimerSchedule(dev, ZM_EVENT_CM_TIMER, ZM_TICK_CM_TIMEOUT); /* Timer Resolution on WinXP is 15/16 ms */ /* Decrease Time offset for Counter Measure */ zfTimerSchedule(dev, ZM_EVENT_CM_TIMER, ZM_TICK_CM_TIMEOUT - ZM_TICK_CM_TIMEOUT_OFFSET); } else if ( wd->sta.cmMicFailureCount == 2 ) { zm_debug_msg0("get the second MIC failure"); /* reserve 2 second for OS to send MIC failure report to AP */ wd->sta.cmDisallowSsidLength = wd->sta.ssidLen; zfMemoryCopy(wd->sta.cmDisallowSsid, wd->sta.ssid, wd->sta.ssidLen); //wd->sta.cmMicFailureCount = 0; zfTimerCancel(dev, ZM_EVENT_CM_TIMER); //zfTimerSchedule(dev, ZM_EVENT_CM_DISCONNECT, ZM_TICK_CM_DISCONNECT); /* Timer Resolution on WinXP is 15/16 ms */ /* Decrease Time offset for Counter Measure */ zfTimerSchedule(dev, ZM_EVENT_CM_DISCONNECT, ZM_TICK_CM_DISCONNECT - ZM_TICK_CM_DISCONNECT_OFFSET); } else { micNotify = 0; } zmw_leave_critical_section(dev); if (micNotify == 1) { da0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A1_OFFSET); if ( da0 & 0x01 ) { if (wd->zfcbMicFailureNotify != NULL) { wd->zfcbMicFailureNotify(dev, wd->sta.bssid, ZM_MIC_GROUP_ERROR); } } else { if (wd->zfcbMicFailureNotify != NULL) { wd->zfcbMicFailureNotify(dev, wd->sta.bssid, ZM_MIC_PAIRWISE_ERROR); } } } } u8_t zfStaBlockWlanScan(zdev_t* dev) { u8_t ret=FALSE; zmw_get_wlan_dev(dev); if ( wd->sta.bChannelScan ) { return TRUE; } return ret; } void zfStaResetStatus(zdev_t* dev, u8_t bInit) { u8_t i; zmw_get_wlan_dev(dev); zfHpDisableBeacon(dev); wd->dtim = 1; wd->sta.capability[0] = 0x01; wd->sta.capability[1] = 0x00; /* 802.11h */ if (wd->sta.DFSEnable || wd->sta.TPCEnable) wd->sta.capability[1] |= ZM_BIT_0; /* release queued packets */ for(i=0; ista.ibssPSDataCount; i++) { zfwBufFree(dev, wd->sta.ibssPSDataQueue[i], 0); } for(i=0; ista.staPSDataCount; i++) { zfwBufFree(dev, wd->sta.staPSDataQueue[i], 0); } wd->sta.ibssPSDataCount = 0; wd->sta.staPSDataCount = 0; zfZeroMemory((u8_t*) &wd->sta.staPSList, sizeof(struct zsStaPSList)); wd->sta.wmeConnected = 0; wd->sta.psMgr.tempWakeUp = 0; wd->sta.qosInfo = 0; zfQueueFlush(dev, wd->sta.uapsdQ); return; } void zfStaIbssMonitoring(zdev_t* dev, u8_t reset) { u16_t i; u16_t oppositeCount; struct zsPartnerNotifyEvent event; zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); //zm_debug_msg1("zfStaIbssMonitoring %d", wd->sta.oppositeCount); zmw_enter_critical_section(dev); if ( wd->sta.oppositeCount == 0 ) { goto done; } if ( wd->sta.bChannelScan ) { goto done; } oppositeCount = wd->sta.oppositeCount; for(i=0; i < ZM_MAX_OPPOSITE_COUNT; i++) { if ( oppositeCount == 0 ) { break; } if ( reset ) { wd->sta.oppositeInfo[i].valid = 0; } if ( wd->sta.oppositeInfo[i].valid == 0 ) { continue; } oppositeCount--; if ( wd->sta.oppositeInfo[i].aliveCounter ) { zm_debug_msg1("Setting alive to ", wd->sta.oppositeInfo[i].aliveCounter); zmw_leave_critical_section(dev); if ( wd->sta.oppositeInfo[i].aliveCounter != ZM_IBSS_PEER_ALIVE_COUNTER ) { zfSendMmFrame(dev, ZM_WLAN_FRAME_TYPE_PROBEREQ, (u16_t*)wd->sta.oppositeInfo[i].macAddr, 1, 0, 0); } zmw_enter_critical_section(dev); wd->sta.oppositeInfo[i].aliveCounter--; } else { zm_debug_msg0("zfStaIbssMonitoring remove the peer station"); zfMemoryCopy(event.bssid, (u8_t *)(wd->sta.bssid), 6); zfMemoryCopy(event.peerMacAddr, wd->sta.oppositeInfo[i].macAddr, 6); wd->sta.oppositeInfo[i].valid = 0; wd->sta.oppositeCount--; if (wd->zfcbIbssPartnerNotify != NULL) { zmw_leave_critical_section(dev); wd->zfcbIbssPartnerNotify(dev, 0, &event); zmw_enter_critical_section(dev); } } } done: if ( reset == 0 ) { zfTimerSchedule(dev, ZM_EVENT_IBSS_MONITOR, ZM_TICK_IBSS_MONITOR); } zmw_leave_critical_section(dev); } void zfInitPartnerNotifyEvent(zdev_t* dev, zbuf_t* buf, struct zsPartnerNotifyEvent *event) { u16_t *peerMacAddr; zmw_get_wlan_dev(dev); peerMacAddr = (u16_t *)event->peerMacAddr; zfMemoryCopy(event->bssid, (u8_t *)(wd->sta.bssid), 6); peerMacAddr[0] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET); peerMacAddr[1] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET + 2); peerMacAddr[2] = zmw_rx_buf_readh(dev, buf, ZM_WLAN_HEADER_A2_OFFSET + 4); } void zfStaInitOppositeInfo(zdev_t* dev) { int i; zmw_get_wlan_dev(dev); for(i=0; ista.oppositeInfo[i].valid = 0; wd->sta.oppositeInfo[i].aliveCounter = ZM_IBSS_PEER_ALIVE_COUNTER; } } #ifdef ZM_ENABLE_CENC u16_t zfStaAddIeCenc(zdev_t* dev, zbuf_t* buf, u16_t offset) { zmw_get_wlan_dev(dev); if (wd->sta.cencIe[1] != 0) { zfCopyToIntTxBuffer(dev, buf, wd->sta.cencIe, offset, wd->sta.cencIe[1]+2); offset += (wd->sta.cencIe[1]+2); } return offset; } #endif //ZM_ENABLE_CENC u16_t zfStaProcessAction(zdev_t* dev, zbuf_t* buf) { u8_t category, actionDetails; zmw_get_wlan_dev(dev); category = zmw_rx_buf_readb(dev, buf, 24); actionDetails = zmw_rx_buf_readb(dev, buf, 25); switch (category) { case 0: //Spectrum Management switch(actionDetails) { case 0: //Measurement Request break; case 1: //Measurement Report //ProcessActionSpectrumFrame_MeasurementReport(Adapter,pActionBody+3); break; case 2: //TPC request //if (wd->sta.TPCEnable) // zfStaUpdateDot11HTPC(dev, buf); break; case 3: //TPC report //if (wd->sta.TPCEnable) // zfStaUpdateDot11HTPC(dev, buf); break; case 4: //Channel Switch Announcement if (wd->sta.DFSEnable) zfStaUpdateDot11HDFS(dev, buf); break; default: zm_debug_msg1("Action Frame contain not support action field ", actionDetails); break; } break; case ZM_WLAN_BLOCK_ACK_ACTION_FRAME: zfAggBlockAckActionFrame(dev, buf); break; case 17: //Qos Management break; } return 0; } /* Determine the time not send beacon , if more than some value , re-write the beacon start address */ void zfReWriteBeaconStartAddress(zdev_t* dev) { zmw_get_wlan_dev(dev); zmw_declare_for_critical_section(); zmw_enter_critical_section(dev); wd->tickIbssSendBeacon++; // Increase 1 per 10ms . zmw_leave_critical_section(dev); if ( wd->tickIbssSendBeacon == 40 ) { // DbgPrint("20070727"); zfHpEnableBeacon(dev, ZM_MODE_IBSS, wd->beaconInterval, wd->dtim, (u8_t)wd->sta.atimWindow); zmw_enter_critical_section(dev); wd->tickIbssSendBeacon = 0; zmw_leave_critical_section(dev); } } struct zsTkipSeed* zfStaGetRxSeed(zdev_t* dev, zbuf_t* buf) { u8_t keyIndex; u8_t da0; zmw_get_wlan_dev(dev); /* if need not check MIC, return NULL */ if ( ((wd->sta.encryMode != ZM_TKIP)&&(wd->sta.encryMode != ZM_AES))|| (wd->sta.wpaState < ZM_STA_WPA_STATE_PK_OK) ) { return NULL; } da0 = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_A1_OFFSET); if ((zmw_rx_buf_readb(dev, buf, 0) & 0x80) == 0x80) keyIndex = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_IV_OFFSET+5); /* Qos Packet*/ else keyIndex = zmw_rx_buf_readb(dev, buf, ZM_WLAN_HEADER_IV_OFFSET+3); /* normal Packet*/ keyIndex = (keyIndex & 0xc0) >> 6; return (&wd->sta.rxSeed[keyIndex]); } void zfStaEnableSWEncryption(zdev_t *dev, u8_t value) { zmw_get_wlan_dev(dev); wd->sta.SWEncryptEnable = value; zfHpSWDecrypt(dev, 1); zfHpSWEncrypt(dev, 1); } void zfStaDisableSWEncryption(zdev_t *dev) { zmw_get_wlan_dev(dev); wd->sta.SWEncryptEnable = 0; zfHpSWDecrypt(dev, 0); zfHpSWEncrypt(dev, 0); } u16_t zfComputeBssInfoWeightValue(zdev_t *dev, u8_t isBMode, u8_t isHT, u8_t isHT40, u8_t signalStrength) { u8_t weightOfB = 0; u8_t weightOfAGBelowThr = 0; u8_t weightOfAGUpThr = 15; u8_t weightOfN20BelowThr = 15; u8_t weightOfN20UpThr = 30; u8_t weightOfN40BelowThr = 16; u8_t weightOfN40UpThr = 32; zmw_get_wlan_dev(dev); if( isBMode == 0 ) return (signalStrength + weightOfB); // pure b mode , do not add the weight value for this AP ! else { if( isHT == 0 && isHT40 == 0 ) { // a , g , b/g mode ! add the weight value 15 for this AP if it's signal strength is more than some value ! if( signalStrength < 18 ) // -77 dBm return signalStrength + weightOfAGBelowThr; else return (signalStrength + weightOfAGUpThr); } else if( isHT == 1 && isHT40 == 0 ) { // 80211n mode use 20MHz if( signalStrength < 23 ) // -72 dBm return (signalStrength + weightOfN20BelowThr); else return (signalStrength + weightOfN20UpThr); } else // isHT == 1 && isHT40 == 1 { // 80211n mode use 40MHz if( signalStrength < 16 ) // -79 dBm return (signalStrength + weightOfN40BelowThr); else return (signalStrength + weightOfN40UpThr); } } } u16_t zfStaAddIbssAdditionalIE(zdev_t* dev, zbuf_t* buf, u16_t offset) { u16_t i; zmw_get_wlan_dev(dev); for (i=0; ista.ibssAdditionalIESize; i++) { zmw_tx_buf_writeb(dev, buf, offset++, wd->sta.ibssAdditionalIE[i]); } return offset; }