| /* |
| * 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" |
| |
| u8_t zfQueryOppositeRate(zdev_t* dev, u8_t dst_mac[6], u8_t frameType) |
| { |
| zmw_get_wlan_dev(dev); |
| |
| /* For AP's rate adaption */ |
| if ( wd->wlanMode == ZM_MODE_AP ) |
| { |
| return 0; |
| } |
| |
| /* For STA's rate adaption */ |
| if ( (frameType & 0x0c) == ZM_WLAN_DATA_FRAME ) |
| { |
| if ( ZM_IS_MULTICAST(dst_mac) ) |
| { |
| return wd->sta.mTxRate; |
| } |
| else |
| { |
| return wd->sta.uTxRate; |
| } |
| } |
| |
| return wd->sta.mmTxRate; |
| } |
| |
| void zfCopyToIntTxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* src, |
| u16_t offset, u16_t length) |
| { |
| u16_t i; |
| |
| for(i=0; i<length;i++) |
| { |
| zmw_tx_buf_writeb(dev, buf, offset+i, src[i]); |
| } |
| } |
| |
| void zfCopyToRxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* src, |
| u16_t offset, u16_t length) |
| { |
| u16_t i; |
| |
| for(i=0; i<length;i++) |
| { |
| zmw_rx_buf_writeb(dev, buf, offset+i, src[i]); |
| } |
| } |
| |
| void zfCopyFromIntTxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* dst, |
| u16_t offset, u16_t length) |
| { |
| u16_t i; |
| |
| for(i=0; i<length; i++) |
| { |
| dst[i] = zmw_tx_buf_readb(dev, buf, offset+i); |
| } |
| } |
| |
| void zfCopyFromRxBuffer(zdev_t* dev, zbuf_t* buf, u8_t* dst, |
| u16_t offset, u16_t length) |
| { |
| u16_t i; |
| |
| for(i=0; i<length; i++) |
| { |
| dst[i] = zmw_rx_buf_readb(dev, buf, offset+i); |
| } |
| } |
| |
| #if 1 |
| void zfMemoryCopy(u8_t* dst, u8_t* src, u16_t length) |
| { |
| zfwMemoryCopy(dst, src, length); |
| } |
| |
| void zfMemoryMove(u8_t* dst, u8_t* src, u16_t length) |
| { |
| zfwMemoryMove(dst, src, length); |
| } |
| |
| void zfZeroMemory(u8_t* va, u16_t length) |
| { |
| zfwZeroMemory(va, length); |
| } |
| |
| u8_t zfMemoryIsEqual(u8_t* m1, u8_t* m2, u16_t length) |
| { |
| return zfwMemoryIsEqual(m1, m2, length); |
| } |
| #endif |
| |
| u8_t zfRxBufferEqualToStr(zdev_t* dev, zbuf_t* buf, |
| const u8_t* str, u16_t offset, u16_t length) |
| { |
| u16_t i; |
| u8_t ch; |
| |
| for(i=0; i<length; i++) |
| { |
| ch = zmw_rx_buf_readb(dev, buf, offset+i); |
| if ( ch != str[i] ) |
| { |
| return FALSE; |
| } |
| } |
| |
| return TRUE; |
| } |
| |
| void zfTxBufferCopy(zdev_t*dev, zbuf_t* dst, zbuf_t* src, |
| u16_t dstOffset, u16_t srcOffset, u16_t length) |
| { |
| u16_t i; |
| |
| for(i=0; i<length; i++) |
| { |
| zmw_tx_buf_writeb(dev, dst, dstOffset+i, |
| zmw_tx_buf_readb(dev, src, srcOffset+i)); |
| } |
| } |
| |
| void zfRxBufferCopy(zdev_t*dev, zbuf_t* dst, zbuf_t* src, |
| u16_t dstOffset, u16_t srcOffset, u16_t length) |
| { |
| u16_t i; |
| |
| for(i=0; i<length; i++) |
| { |
| zmw_rx_buf_writeb(dev, dst, dstOffset+i, |
| zmw_rx_buf_readb(dev, src, srcOffset+i)); |
| } |
| } |
| |
| |
| void zfCollectHWTally(zdev_t*dev, u32_t* rsp, u8_t id) |
| { |
| zmw_get_wlan_dev(dev); |
| |
| zmw_declare_for_critical_section(); |
| |
| zmw_enter_critical_section(dev); |
| |
| if (id == 0) |
| { |
| wd->commTally.Hw_UnderrunCnt += (0xFFFF & rsp[1]); |
| wd->commTally.Hw_TotalRxFrm += rsp[2]; |
| wd->commTally.Hw_CRC32Cnt += rsp[3]; |
| wd->commTally.Hw_CRC16Cnt += rsp[4]; |
| #ifdef ZM_ENABLE_NATIVE_WIFI |
| /* These code are here to satisfy Vista DTM */ |
| wd->commTally.Hw_DecrypErr_UNI += ((rsp[5]>50) && (rsp[5]<60))?50:rsp[5]; |
| #else |
| wd->commTally.Hw_DecrypErr_UNI += rsp[5]; |
| #endif |
| wd->commTally.Hw_RxFIFOOverrun += rsp[6]; |
| wd->commTally.Hw_DecrypErr_Mul += rsp[7]; |
| wd->commTally.Hw_RetryCnt += rsp[8]; |
| wd->commTally.Hw_TotalTxFrm += rsp[9]; |
| wd->commTally.Hw_RxTimeOut +=rsp[10]; |
| |
| wd->commTally.Tx_MPDU += rsp[11]; |
| wd->commTally.BA_Fail += rsp[12]; |
| wd->commTally.Hw_Tx_AMPDU += rsp[13]; |
| wd->commTally.Hw_Tx_MPDU += rsp[14]; |
| wd->commTally.RateCtrlTxMPDU += rsp[11]; |
| wd->commTally.RateCtrlBAFail += rsp[12]; |
| } |
| else |
| { |
| wd->commTally.Hw_RxMPDU += rsp[1]; |
| wd->commTally.Hw_RxDropMPDU += rsp[2]; |
| wd->commTally.Hw_RxDelMPDU += rsp[3]; |
| |
| wd->commTally.Hw_RxPhyMiscError += rsp[4]; |
| wd->commTally.Hw_RxPhyXRError += rsp[5]; |
| wd->commTally.Hw_RxPhyOFDMError += rsp[6]; |
| wd->commTally.Hw_RxPhyCCKError += rsp[7]; |
| wd->commTally.Hw_RxPhyHTError += rsp[8]; |
| wd->commTally.Hw_RxPhyTotalCount += rsp[9]; |
| } |
| |
| zmw_leave_critical_section(dev); |
| |
| if (id == 0) |
| { |
| zm_msg1_mm(ZM_LV_1, "rsplen =", rsp[0]); |
| zm_msg1_mm(ZM_LV_1, "Hw_UnderrunCnt = ", (0xFFFF & rsp[1])); |
| zm_msg1_mm(ZM_LV_1, "Hw_TotalRxFrm = ", rsp[2]); |
| zm_msg1_mm(ZM_LV_1, "Hw_CRC32Cnt = ", rsp[3]); |
| zm_msg1_mm(ZM_LV_1, "Hw_CRC16Cnt = ", rsp[4]); |
| zm_msg1_mm(ZM_LV_1, "Hw_DecrypErr_UNI = ", rsp[5]); |
| zm_msg1_mm(ZM_LV_1, "Hw_RxFIFOOverrun = ", rsp[6]); |
| zm_msg1_mm(ZM_LV_1, "Hw_DecrypErr_Mul = ", rsp[7]); |
| zm_msg1_mm(ZM_LV_1, "Hw_RetryCnt = ", rsp[8]); |
| zm_msg1_mm(ZM_LV_1, "Hw_TotalTxFrm = ", rsp[9]); |
| zm_msg1_mm(ZM_LV_1, "Hw_RxTimeOut = ", rsp[10]); |
| zm_msg1_mm(ZM_LV_1, "Tx_MPDU = ", rsp[11]); |
| zm_msg1_mm(ZM_LV_1, "BA_Fail = ", rsp[12]); |
| zm_msg1_mm(ZM_LV_1, "Hw_Tx_AMPDU = ", rsp[13]); |
| zm_msg1_mm(ZM_LV_1, "Hw_Tx_MPDU = ", rsp[14]); |
| } |
| else |
| { |
| zm_msg1_mm(ZM_LV_1, "rsplen = ", rsp[0]); |
| zm_msg1_mm(ZM_LV_1, "Hw_RxMPDU = ", (0xFFFF & rsp[1])); |
| zm_msg1_mm(ZM_LV_1, "Hw_RxDropMPDU = ", rsp[2]); |
| zm_msg1_mm(ZM_LV_1, "Hw_RxDelMPDU = ", rsp[3]); |
| zm_msg1_mm(ZM_LV_1, "Hw_RxPhyMiscError = ", rsp[4]); |
| zm_msg1_mm(ZM_LV_1, "Hw_RxPhyXRError = ", rsp[5]); |
| zm_msg1_mm(ZM_LV_1, "Hw_RxPhyOFDMError = ", rsp[6]); |
| zm_msg1_mm(ZM_LV_1, "Hw_RxPhyCCKError = ", rsp[7]); |
| zm_msg1_mm(ZM_LV_1, "Hw_RxPhyHTError = ", rsp[8]); |
| zm_msg1_mm(ZM_LV_1, "Hw_RxPhyTotalCount = ", rsp[9]); |
| } |
| |
| } |
| |
| /* Timer related functions */ |
| void zfTimerInit(zdev_t* dev) |
| { |
| u8_t i; |
| |
| zmw_get_wlan_dev(dev); |
| |
| zm_debug_msg0(""); |
| |
| wd->timerList.freeCount = ZM_MAX_TIMER_COUNT; |
| wd->timerList.head = &(wd->timerList.list[0]); |
| wd->timerList.tail = &(wd->timerList.list[ZM_MAX_TIMER_COUNT-1]); |
| wd->timerList.head->pre = NULL; |
| wd->timerList.head->next = &(wd->timerList.list[1]); |
| wd->timerList.tail->pre = &(wd->timerList.list[ZM_MAX_TIMER_COUNT-2]); |
| wd->timerList.tail->next = NULL; |
| |
| for( i=1; i<(ZM_MAX_TIMER_COUNT-1); i++ ) |
| { |
| wd->timerList.list[i].pre = &(wd->timerList.list[i-1]); |
| wd->timerList.list[i].next = &(wd->timerList.list[i+1]); |
| } |
| |
| wd->bTimerReady = TRUE; |
| } |
| |
| |
| u16_t zfTimerSchedule(zdev_t* dev, u16_t event, u32_t tick) |
| { |
| struct zsTimerEntry *pFreeEntry; |
| struct zsTimerEntry *pEntry; |
| u8_t i, count; |
| |
| zmw_get_wlan_dev(dev); |
| |
| if ( wd->timerList.freeCount == 0 ) |
| { |
| zm_debug_msg0("no more timer"); |
| return 1; |
| } |
| |
| //zm_debug_msg2("event = ", event); |
| //zm_debug_msg1("target tick = ", wd->tick + tick); |
| |
| count = ZM_MAX_TIMER_COUNT - wd->timerList.freeCount; |
| |
| if ( count == 0 ) |
| { |
| wd->timerList.freeCount--; |
| wd->timerList.head->event = event; |
| wd->timerList.head->timer = wd->tick + tick; |
| //zm_debug_msg1("free timer count = ", wd->timerList.freeCount); |
| |
| return 0; |
| } |
| |
| pFreeEntry = wd->timerList.tail; |
| pFreeEntry->timer = wd->tick + tick; |
| pFreeEntry->event = event; |
| wd->timerList.tail = pFreeEntry->pre; |
| pEntry = wd->timerList.head; |
| |
| for( i=0; i<count; i++ ) |
| { |
| // prevent from the case of tick overflow |
| if ( ( pEntry->timer > pFreeEntry->timer )&& |
| ((pEntry->timer - pFreeEntry->timer) < 1000000000) ) |
| { |
| if ( i != 0 ) |
| { |
| pFreeEntry->pre = pEntry->pre; |
| pFreeEntry->pre->next = pFreeEntry; |
| } |
| else |
| { |
| pFreeEntry->pre = NULL; |
| } |
| |
| pEntry->pre = pFreeEntry; |
| pFreeEntry->next = pEntry; |
| break; |
| } |
| |
| pEntry = pEntry->next; |
| } |
| |
| if ( i == 0 ) |
| { |
| wd->timerList.head = pFreeEntry; |
| } |
| |
| if ( i == count ) |
| { |
| pFreeEntry->pre = pEntry->pre; |
| pFreeEntry->pre->next = pFreeEntry; |
| pEntry->pre = pFreeEntry; |
| pFreeEntry->next = pEntry; |
| } |
| |
| wd->timerList.freeCount--; |
| //zm_debug_msg1("free timer count = ", wd->timerList.freeCount); |
| |
| return 0; |
| } |
| |
| u16_t zfTimerCancel(zdev_t* dev, u16_t event) |
| { |
| struct zsTimerEntry *pEntry; |
| u8_t i, count; |
| |
| zmw_get_wlan_dev(dev); |
| |
| //zm_debug_msg2("event = ", event); |
| //zm_debug_msg1("free timer count(b) = ", wd->timerList.freeCount); |
| |
| pEntry = wd->timerList.head; |
| count = ZM_MAX_TIMER_COUNT - wd->timerList.freeCount; |
| |
| for( i=0; i<count; i++ ) |
| { |
| if ( pEntry->event == event ) |
| { |
| if ( pEntry == wd->timerList.head ) |
| { /* remove head entry */ |
| wd->timerList.head = pEntry->next; |
| wd->timerList.tail->next = pEntry; |
| pEntry->pre = wd->timerList.tail; |
| wd->timerList.tail = pEntry; |
| pEntry = wd->timerList.head; |
| } |
| else |
| { /* remove non-head entry */ |
| pEntry->pre->next = pEntry->next; |
| pEntry->next->pre = pEntry->pre; |
| wd->timerList.tail->next = pEntry; |
| pEntry->pre = wd->timerList.tail; |
| wd->timerList.tail = pEntry; |
| pEntry = pEntry->next; |
| } |
| |
| wd->timerList.freeCount++; |
| } |
| else |
| { |
| pEntry = pEntry->next; |
| } |
| } |
| |
| //zm_debug_msg1("free timer count(a) = ", wd->timerList.freeCount); |
| |
| return 0; |
| } |
| |
| void zfTimerClear(zdev_t* dev) |
| { |
| zmw_get_wlan_dev(dev); |
| |
| wd->timerList.freeCount = ZM_MAX_TIMER_COUNT; |
| } |
| |
| u16_t zfTimerCheckAndHandle(zdev_t* dev) |
| { |
| struct zsTimerEntry *pEntry; |
| struct zsTimerEntry *pTheLastEntry = NULL; |
| u16_t event[ZM_MAX_TIMER_COUNT]; |
| u8_t i, j=0, count; |
| |
| zmw_get_wlan_dev(dev); |
| |
| zmw_declare_for_critical_section(); |
| |
| if ( !wd->bTimerReady ) |
| { |
| return 0; |
| } |
| |
| zmw_enter_critical_section(dev); |
| |
| pEntry = wd->timerList.head; |
| count = ZM_MAX_TIMER_COUNT - wd->timerList.freeCount; |
| |
| for( i=0; i<count; i++ ) |
| { |
| // prevent from the case of tick overflow |
| if ( ( pEntry->timer > wd->tick )&& |
| ((pEntry->timer - wd->tick) < 1000000000) ) |
| { |
| break; |
| } |
| |
| event[j++] = pEntry->event; |
| pTheLastEntry = pEntry; |
| pEntry = pEntry->next; |
| } |
| |
| if ( j > 0 ) |
| { |
| wd->timerList.tail->next = wd->timerList.head; |
| wd->timerList.head->pre = wd->timerList.tail; |
| wd->timerList.head = pEntry; |
| wd->timerList.tail = pTheLastEntry; |
| wd->timerList.freeCount += j; |
| //zm_debug_msg1("free timer count = ", wd->timerList.freeCount); |
| } |
| |
| zmw_leave_critical_section(dev); |
| |
| zfProcessEvent(dev, event, j); |
| |
| return 0; |
| } |
| |
| u32_t zfCoreSetKey(zdev_t* dev, u8_t user, u8_t keyId, u8_t type, |
| u16_t* mac, u32_t* key) |
| { |
| u32_t ret; |
| |
| zmw_get_wlan_dev(dev); |
| zmw_declare_for_critical_section(); |
| |
| zmw_enter_critical_section(dev); |
| wd->sta.flagKeyChanging++; |
| zm_debug_msg1(" zfCoreSetKey++++ ", wd->sta.flagKeyChanging); |
| zmw_leave_critical_section(dev); |
| |
| ret = zfHpSetKey(dev, user, keyId, type, mac, key); |
| return ret; |
| } |
| |
| void zfCoreSetKeyComplete(zdev_t* dev) |
| { |
| zmw_get_wlan_dev(dev); |
| zmw_declare_for_critical_section(); |
| |
| #if 0 |
| wd->sta.flagKeyChanging = 0; |
| #else |
| if(wd->sta.flagKeyChanging) |
| { |
| zmw_enter_critical_section(dev); |
| wd->sta.flagKeyChanging--; |
| zmw_leave_critical_section(dev); |
| } |
| #endif |
| zm_debug_msg1(" zfCoreSetKeyComplete--- ", wd->sta.flagKeyChanging); |
| |
| zfPushVtxq(dev); |
| } |
| |
| void zfCoreHalInitComplete(zdev_t* dev) |
| { |
| zmw_get_wlan_dev(dev); |
| zmw_declare_for_critical_section(); |
| |
| zmw_enter_critical_section(dev); |
| wd->halState = ZM_HAL_STATE_RUNNING; |
| zmw_leave_critical_section(dev); |
| |
| zfPushVtxq(dev); |
| } |
| |
| void zfCoreMacAddressNotify(zdev_t* dev, u8_t* addr) |
| { |
| zmw_get_wlan_dev(dev); |
| |
| wd->macAddr[0] = addr[0] | ((u16_t)addr[1]<<8); |
| wd->macAddr[1] = addr[2] | ((u16_t)addr[3]<<8); |
| wd->macAddr[2] = addr[4] | ((u16_t)addr[5]<<8); |
| |
| |
| //zfHpSetMacAddress(dev, wd->macAddr, 0); |
| if (wd->zfcbMacAddressNotify != NULL) |
| { |
| wd->zfcbMacAddressNotify(dev, addr); |
| } |
| } |
| |
| void zfCoreSetIsoName(zdev_t* dev, u8_t* isoName) |
| { |
| zmw_get_wlan_dev(dev); |
| |
| wd->ws.countryIsoName[0] = isoName[0]; |
| wd->ws.countryIsoName[1] = isoName[1]; |
| wd->ws.countryIsoName[2] = '\0'; |
| } |
| |
| |
| extern void zfScanMgrScanEventStart(zdev_t* dev); |
| extern u8_t zfScanMgrScanEventTimeout(zdev_t* dev); |
| extern void zfScanMgrScanEventRetry(zdev_t* dev); |
| |
| void zfProcessEvent(zdev_t* dev, u16_t* eventArray, u8_t eventCount) |
| { |
| u8_t i, j, bypass = FALSE; |
| u16_t eventBypass[32]; |
| u8_t eventBypassCount = 0; |
| |
| zmw_get_wlan_dev(dev); |
| |
| zmw_declare_for_critical_section(); |
| |
| zfZeroMemory((u8_t*) eventBypass, 64); |
| |
| for( i=0; i<eventCount; i++ ) |
| { |
| for( j=0; j<eventBypassCount; j++ ) |
| { |
| if ( eventBypass[j] == eventArray[i] ) |
| { |
| bypass = TRUE; |
| break; |
| } |
| } |
| |
| if ( bypass ) |
| { |
| continue; |
| } |
| |
| switch( eventArray[i] ) |
| { |
| case ZM_EVENT_SCAN: |
| { |
| zfScanMgrScanEventStart(dev); |
| eventBypass[eventBypassCount++] = ZM_EVENT_IN_SCAN; |
| eventBypass[eventBypassCount++] = ZM_EVENT_TIMEOUT_SCAN; |
| } |
| break; |
| |
| case ZM_EVENT_TIMEOUT_SCAN: |
| { |
| u8_t res; |
| |
| res = zfScanMgrScanEventTimeout(dev); |
| if ( res == 0 ) |
| { |
| eventBypass[eventBypassCount++] = ZM_EVENT_TIMEOUT_SCAN; |
| } |
| else if ( res == 1 ) |
| { |
| eventBypass[eventBypassCount++] = ZM_EVENT_IN_SCAN; |
| } |
| } |
| break; |
| |
| case ZM_EVENT_IBSS_MONITOR: |
| { |
| zfStaIbssMonitoring(dev, 0); |
| } |
| break; |
| |
| case ZM_EVENT_IN_SCAN: |
| { |
| zfScanMgrScanEventRetry(dev); |
| } |
| break; |
| |
| case ZM_EVENT_CM_TIMER: |
| { |
| zm_msg0_mm(ZM_LV_0, "ZM_EVENT_CM_TIMER"); |
| |
| wd->sta.cmMicFailureCount = 0; |
| } |
| break; |
| |
| case ZM_EVENT_CM_DISCONNECT: |
| { |
| zm_msg0_mm(ZM_LV_0, "ZM_EVENT_CM_DISCONNECT"); |
| |
| zfChangeAdapterState(dev, ZM_STA_STATE_DISCONNECT); |
| |
| zmw_enter_critical_section(dev); |
| //zfTimerSchedule(dev, ZM_EVENT_CM_BLOCK_TIMER, |
| // ZM_TICK_CM_BLOCK_TIMEOUT); |
| |
| /* Timer Resolution on WinXP is 15/16 ms */ |
| /* Decrease Time offset for <XP> Counter Measure */ |
| zfTimerSchedule(dev, ZM_EVENT_CM_BLOCK_TIMER, |
| ZM_TICK_CM_BLOCK_TIMEOUT - ZM_TICK_CM_BLOCK_TIMEOUT_OFFSET); |
| |
| zmw_leave_critical_section(dev); |
| wd->sta.cmMicFailureCount = 0; |
| //zfiWlanDisable(dev); |
| zfHpResetKeyCache(dev); |
| if (wd->zfcbConnectNotify != NULL) |
| { |
| wd->zfcbConnectNotify(dev, ZM_STATUS_MEDIA_DISCONNECT_MIC_FAIL, |
| wd->sta.bssid); |
| } |
| } |
| break; |
| |
| case ZM_EVENT_CM_BLOCK_TIMER: |
| { |
| zm_msg0_mm(ZM_LV_0, "ZM_EVENT_CM_BLOCK_TIMER"); |
| |
| //zmw_enter_critical_section(dev); |
| wd->sta.cmDisallowSsidLength = 0; |
| if ( wd->sta.bAutoReconnect ) |
| { |
| zm_msg0_mm(ZM_LV_0, "ZM_EVENT_CM_BLOCK_TIMER:bAutoReconnect!=0"); |
| zfScanMgrScanStop(dev, ZM_SCAN_MGR_SCAN_INTERNAL); |
| zfScanMgrScanStart(dev, ZM_SCAN_MGR_SCAN_INTERNAL); |
| } |
| //zmw_leave_critical_section(dev); |
| } |
| break; |
| |
| case ZM_EVENT_TIMEOUT_ADDBA: |
| { |
| if (!wd->addbaComplete && (wd->addbaCount < 5)) |
| { |
| zfAggSendAddbaRequest(dev, wd->sta.bssid, 0, 0); |
| wd->addbaCount++; |
| zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_ADDBA, 100); |
| } |
| else |
| { |
| zfTimerCancel(dev, ZM_EVENT_TIMEOUT_ADDBA); |
| } |
| } |
| break; |
| |
| #ifdef ZM_ENABLE_PERFORMANCE_EVALUATION |
| case ZM_EVENT_TIMEOUT_PERFORMANCE: |
| { |
| zfiPerformanceRefresh(dev); |
| } |
| break; |
| #endif |
| case ZM_EVENT_SKIP_COUNTERMEASURE: |
| //enable the Countermeasure |
| { |
| zm_debug_msg0("Countermeasure : Enable MIC Check "); |
| wd->TKIP_Group_KeyChanging = 0x0; |
| } |
| break; |
| |
| default: |
| break; |
| } |
| } |
| } |
| |
| void zfBssInfoCreate(zdev_t* dev) |
| { |
| u8_t i; |
| |
| zmw_get_wlan_dev(dev); |
| |
| zmw_declare_for_critical_section(); |
| |
| zmw_enter_critical_section(dev); |
| |
| wd->sta.bssList.bssCount = 0; |
| wd->sta.bssList.head = NULL; |
| wd->sta.bssList.tail = NULL; |
| wd->sta.bssInfoArrayHead = 0; |
| wd->sta.bssInfoArrayTail = 0; |
| wd->sta.bssInfoFreeCount = ZM_MAX_BSS; |
| |
| for( i=0; i< ZM_MAX_BSS; i++ ) |
| { |
| //wd->sta.bssInfoArray[i] = &(wd->sta.bssInfoPool[i]); |
| wd->sta.bssInfoArray[i] = zfwMemAllocate(dev, sizeof(struct zsBssInfo)); |
| |
| } |
| |
| zmw_leave_critical_section(dev); |
| } |
| |
| void zfBssInfoDestroy(zdev_t* dev) |
| { |
| u8_t i; |
| zmw_get_wlan_dev(dev); |
| |
| zfBssInfoRefresh(dev, 1); |
| |
| for( i=0; i< ZM_MAX_BSS; i++ ) |
| { |
| if (wd->sta.bssInfoArray[i] != NULL) |
| { |
| zfwMemFree(dev, wd->sta.bssInfoArray[i], sizeof(struct zsBssInfo)); |
| } |
| else |
| { |
| zm_assert(0); |
| } |
| } |
| return; |
| } |
| |
| struct zsBssInfo* zfBssInfoAllocate(zdev_t* dev) |
| { |
| struct zsBssInfo* pBssInfo; |
| |
| zmw_get_wlan_dev(dev); |
| |
| if (wd->sta.bssInfoFreeCount == 0) |
| return NULL; |
| |
| pBssInfo = wd->sta.bssInfoArray[wd->sta.bssInfoArrayHead]; |
| wd->sta.bssInfoArray[wd->sta.bssInfoArrayHead] = NULL; |
| wd->sta.bssInfoArrayHead = (wd->sta.bssInfoArrayHead + 1) & (ZM_MAX_BSS - 1); |
| wd->sta.bssInfoFreeCount--; |
| |
| zfZeroMemory((u8_t*)pBssInfo, sizeof(struct zsBssInfo)); |
| |
| return pBssInfo; |
| } |
| |
| void zfBssInfoFree(zdev_t* dev, struct zsBssInfo* pBssInfo) |
| { |
| zmw_get_wlan_dev(dev); |
| |
| zm_assert(wd->sta.bssInfoArray[wd->sta.bssInfoArrayTail] == NULL); |
| |
| pBssInfo->signalStrength = pBssInfo->signalQuality = 0; |
| pBssInfo->sortValue = 0; |
| |
| wd->sta.bssInfoArray[wd->sta.bssInfoArrayTail] = pBssInfo; |
| wd->sta.bssInfoArrayTail = (wd->sta.bssInfoArrayTail + 1) & (ZM_MAX_BSS - 1); |
| wd->sta.bssInfoFreeCount++; |
| } |
| |
| void zfBssInfoReorderList(zdev_t* dev) |
| { |
| struct zsBssInfo* pBssInfo = NULL; |
| struct zsBssInfo* pInsBssInfo = NULL; |
| struct zsBssInfo* pNextBssInfo = NULL; |
| struct zsBssInfo* pPreBssInfo = NULL; |
| u8_t i = 0; |
| |
| zmw_get_wlan_dev(dev); |
| |
| zmw_declare_for_critical_section(); |
| |
| zmw_enter_critical_section(dev); |
| |
| if (wd->sta.bssList.bssCount > 1) |
| { |
| pInsBssInfo = wd->sta.bssList.head; |
| wd->sta.bssList.tail = pInsBssInfo; |
| pBssInfo = pInsBssInfo->next; |
| pInsBssInfo->next = NULL; |
| while (pBssInfo != NULL) |
| { |
| i = 0; |
| while (1) |
| { |
| // if (pBssInfo->signalStrength >= pInsBssInfo->signalStrength) |
| if( pBssInfo->sortValue >= pInsBssInfo->sortValue) |
| { |
| if (i==0) |
| { |
| //Insert BssInfo to head |
| wd->sta.bssList.head = pBssInfo; |
| pNextBssInfo = pBssInfo->next; |
| pBssInfo->next = pInsBssInfo; |
| break; |
| } |
| else |
| { |
| //Insert BssInfo to neither head nor tail |
| pPreBssInfo->next = pBssInfo; |
| pNextBssInfo = pBssInfo->next; |
| pBssInfo->next = pInsBssInfo; |
| break; |
| } |
| } |
| else |
| { |
| if (pInsBssInfo->next != NULL) |
| { |
| //Signal strength smaller than current BssInfo, check next |
| pPreBssInfo = pInsBssInfo; |
| pInsBssInfo = pInsBssInfo->next; |
| } |
| else |
| { |
| //Insert BssInfo to tail |
| pInsBssInfo->next = pBssInfo; |
| pNextBssInfo = pBssInfo->next; |
| wd->sta.bssList.tail = pBssInfo; |
| pBssInfo->next = NULL; |
| break; |
| } |
| } |
| i++; |
| } |
| pBssInfo = pNextBssInfo; |
| pInsBssInfo = wd->sta.bssList.head; |
| } |
| } //if (wd->sta.bssList.bssCount > 1) |
| |
| zmw_leave_critical_section(dev); |
| } |
| |
| void zfBssInfoInsertToList(zdev_t* dev, struct zsBssInfo* pBssInfo) |
| { |
| zmw_get_wlan_dev(dev); |
| |
| zm_assert(pBssInfo); |
| |
| //zm_debug_msg2("pBssInfo = ", pBssInfo); |
| |
| if ( wd->sta.bssList.bssCount == 0 ) |
| { |
| wd->sta.bssList.head = pBssInfo; |
| wd->sta.bssList.tail = pBssInfo; |
| } |
| else |
| { |
| wd->sta.bssList.tail->next = pBssInfo; |
| wd->sta.bssList.tail = pBssInfo; |
| } |
| |
| pBssInfo->next = NULL; |
| wd->sta.bssList.bssCount++; |
| |
| //zm_debug_msg2("bss count = ", wd->sta.bssList.bssCount); |
| } |
| |
| void zfBssInfoRemoveFromList(zdev_t* dev, struct zsBssInfo* pBssInfo) |
| { |
| struct zsBssInfo* pNowBssInfo; |
| struct zsBssInfo* pPreBssInfo = NULL; |
| u8_t i; |
| |
| zmw_get_wlan_dev(dev); |
| |
| zm_assert(pBssInfo); |
| zm_assert(wd->sta.bssList.bssCount); |
| |
| //zm_debug_msg2("pBssInfo = ", pBssInfo); |
| |
| pNowBssInfo = wd->sta.bssList.head; |
| |
| for( i=0; i<wd->sta.bssList.bssCount; i++ ) |
| { |
| if ( pNowBssInfo == pBssInfo ) |
| { |
| if ( i == 0 ) |
| { /* remove head */ |
| wd->sta.bssList.head = pBssInfo->next; |
| } |
| else |
| { |
| pPreBssInfo->next = pBssInfo->next; |
| } |
| |
| if ( i == (wd->sta.bssList.bssCount - 1) ) |
| { /* remove tail */ |
| wd->sta.bssList.tail = pPreBssInfo; |
| } |
| |
| break; |
| } |
| |
| pPreBssInfo = pNowBssInfo; |
| pNowBssInfo = pNowBssInfo->next; |
| } |
| |
| zm_assert(i != wd->sta.bssList.bssCount); |
| wd->sta.bssList.bssCount--; |
| |
| //zm_debug_msg2("bss count = ", wd->sta.bssList.bssCount); |
| } |
| |
| void zfBssInfoRefresh(zdev_t* dev, u16_t mode) |
| { |
| struct zsBssInfo* pBssInfo; |
| struct zsBssInfo* pNextBssInfo; |
| u8_t i, bssCount; |
| |
| zmw_get_wlan_dev(dev); |
| |
| pBssInfo = wd->sta.bssList.head; |
| bssCount = wd->sta.bssList.bssCount; |
| |
| for( i=0; i<bssCount; i++ ) |
| { |
| if (mode == 1) |
| { |
| pNextBssInfo = pBssInfo->next; |
| zfBssInfoRemoveFromList(dev, pBssInfo); |
| zfBssInfoFree(dev, pBssInfo); |
| pBssInfo = pNextBssInfo; |
| } |
| else |
| { |
| if ( pBssInfo->flag & ZM_BSS_INFO_VALID_BIT ) |
| { /* this one must be kept */ |
| pBssInfo->flag &= ~ZM_BSS_INFO_VALID_BIT; |
| pBssInfo = pBssInfo->next; |
| } |
| else |
| { |
| #define ZM_BSS_CACHE_TIME_IN_MS 20000 |
| if ((wd->tick - pBssInfo->tick) > (ZM_BSS_CACHE_TIME_IN_MS/ZM_MS_PER_TICK)) |
| { |
| pNextBssInfo = pBssInfo->next; |
| zfBssInfoRemoveFromList(dev, pBssInfo); |
| zfBssInfoFree(dev, pBssInfo); |
| pBssInfo = pNextBssInfo; |
| } |
| else |
| { |
| pBssInfo = pBssInfo->next; |
| } |
| } |
| } |
| } //for( i=0; i<bssCount; i++ ) |
| return; |
| } |
| |
| void zfDumpSSID(u8_t length, u8_t *value) |
| { |
| u8_t buf[50]; |
| u8_t tmpLength = length; |
| |
| if ( tmpLength > 49 ) |
| { |
| tmpLength = 49; |
| } |
| |
| zfMemoryCopy(buf, value, tmpLength); |
| buf[tmpLength] = '\0'; |
| //printk("SSID: %s\n", buf); |
| //zm_debug_msg_s("ssid = ", value); |
| } |
| |
| void zfCoreReinit(zdev_t* dev) |
| { |
| zmw_get_wlan_dev(dev); |
| |
| wd->sta.flagKeyChanging = 0; |
| wd->sta.flagFreqChanging = 0; |
| } |
| |
| void zfGenerateRandomBSSID(zdev_t* dev, u8_t *MACAddr, u8_t *BSSID) |
| { |
| //ULONGLONG time; |
| u32_t time; |
| |
| zmw_get_wlan_dev(dev); |
| |
| time = wd->tick; |
| |
| // |
| // Initialize the random BSSID to be the same as MAC address. |
| // |
| |
| // RtlCopyMemory(BSSID, MACAddr, sizeof(DOT11_MAC_ADDRESS)); |
| zfMemoryCopy(BSSID, MACAddr, 6); |
| |
| // |
| // Get the system time in 10 millisecond. |
| // |
| |
| // NdisGetCurrentSystemTime((PLARGE_INTEGER)&time); |
| // time /= 100000; |
| |
| // |
| // Randomize the first 4 bytes of BSSID. |
| // |
| |
| BSSID[0] ^= (u8_t)(time & 0xff); |
| BSSID[0] &= ~0x01; // Turn off multicast bit |
| BSSID[0] |= 0x02; // Turn on local bit |
| |
| time >>= 8; |
| BSSID[1] ^= (u8_t)(time & 0xff); |
| |
| time >>= 8; |
| BSSID[2] ^= (u8_t)(time & 0xff); |
| |
| time >>= 8; |
| BSSID[3] ^= (u8_t)(time & 0xff); |
| } |
| |
| u8_t zfiWlanGetDestAddrFromBuf(zdev_t *dev, zbuf_t *buf, u16_t *macAddr) |
| { |
| #ifdef ZM_ENABLE_NATIVE_WIFI |
| zmw_get_wlan_dev(dev); |
| |
| if ( wd->wlanMode == ZM_MODE_INFRASTRUCTURE ) |
| { |
| /* DA */ |
| macAddr[0] = zmw_tx_buf_readh(dev, buf, 16); |
| macAddr[1] = zmw_tx_buf_readh(dev, buf, 18); |
| macAddr[2] = zmw_tx_buf_readh(dev, buf, 20); |
| } |
| else if ( wd->wlanMode == ZM_MODE_IBSS ) |
| { |
| /* DA */ |
| macAddr[0] = zmw_tx_buf_readh(dev, buf, 4); |
| macAddr[1] = zmw_tx_buf_readh(dev, buf, 6); |
| macAddr[2] = zmw_tx_buf_readh(dev, buf, 8); |
| } |
| else if ( wd->wlanMode == ZM_MODE_AP ) |
| { |
| /* DA */ |
| macAddr[0] = zmw_tx_buf_readh(dev, buf, 4); |
| macAddr[1] = zmw_tx_buf_readh(dev, buf, 6); |
| macAddr[2] = zmw_tx_buf_readh(dev, buf, 8); |
| } |
| else |
| { |
| return 1; |
| } |
| #else |
| /* DA */ |
| macAddr[0] = zmw_tx_buf_readh(dev, buf, 0); |
| macAddr[1] = zmw_tx_buf_readh(dev, buf, 2); |
| macAddr[2] = zmw_tx_buf_readh(dev, buf, 4); |
| #endif |
| |
| return 0; |
| } |
| |
| /* Leave an empty line below to remove warning message on some compiler */ |
| |
| u16_t zfFindCleanFrequency(zdev_t* dev, u32_t adhocMode) |
| { |
| u8_t i, j; |
| u16_t returnChannel; |
| u16_t count_24G = 0, min24GIndex = 0; |
| u16_t count_5G = 0, min5GIndex = 0; |
| u16_t CombinationBssNumberIn24G[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
| u16_t BssNumberIn24G[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
| u16_t Array_24G[15] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
| u16_t BssNumberIn5G[31] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
| u16_t Array_5G[31] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; |
| struct zsBssInfo* pBssInfo; |
| |
| zmw_get_wlan_dev(dev); |
| |
| if ((pBssInfo = wd->sta.bssList.head) == NULL) |
| { |
| if( adhocMode == ZM_ADHOCBAND_B || adhocMode == ZM_ADHOCBAND_G || |
| adhocMode == ZM_ADHOCBAND_BG || adhocMode == ZM_ADHOCBAND_ABG ) |
| { |
| returnChannel = zfChGetFirst2GhzChannel(dev); |
| } |
| else |
| { |
| returnChannel = zfChGetFirst5GhzChannel(dev); |
| } |
| |
| return returnChannel; |
| } |
| |
| /* #1 Get Allowed Channel following Country Code ! */ |
| 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.4GHz |
| Array_24G[count_24G] = wd->regulationTable.allowChannel[i].channel; |
| count_24G++; |
| } |
| else |
| { // 5GHz |
| count_5G++; |
| Array_5G[i] = wd->regulationTable.allowChannel[i].channel; |
| } |
| } |
| zmw_leave_critical_section(dev); |
| |
| while( pBssInfo != NULL ) |
| { |
| /* #2_1 Count BSS number in some specificed frequency in 2.4GHz band ! */ |
| if( adhocMode == ZM_ADHOCBAND_B || adhocMode == ZM_ADHOCBAND_G || |
| adhocMode == ZM_ADHOCBAND_BG || adhocMode == ZM_ADHOCBAND_ABG ) |
| { |
| for( i=0; i<=(count_24G+3); i++ ) |
| { |
| if( pBssInfo->frequency == Array_24G[i] ) |
| { // Array_24G[0] correspond to BssNumberIn24G[2] |
| BssNumberIn24G[pBssInfo->channel+1]++; |
| } |
| } |
| } |
| |
| /* #2_2 Count BSS number in some specificed frequency in 5GHz band ! */ |
| if( adhocMode == ZM_ADHOCBAND_A || adhocMode == ZM_ADHOCBAND_ABG ) |
| { |
| for( i=0; i<count_5G; i++ ) |
| { // 5GHz channel is not equal to array index |
| if( pBssInfo->frequency == Array_5G[i] ) |
| { // Array_5G[0] correspond to BssNumberIn5G[0] |
| BssNumberIn5G[i]++; |
| } |
| } |
| } |
| |
| pBssInfo = pBssInfo->next; |
| } |
| |
| #if 0 |
| for(i=0; i<=(count_24G+3); i++) |
| { |
| printk("2.4GHz Before combin, %d BSS network : %d", i, BssNumberIn24G[i]); |
| } |
| |
| for(i=0; i<count_5G; i++) |
| { |
| printk("5GHz Before combin, %d BSS network : %d", i, BssNumberIn5G[i]); |
| } |
| #endif |
| |
| if( adhocMode == ZM_ADHOCBAND_B || adhocMode == ZM_ADHOCBAND_G || |
| adhocMode == ZM_ADHOCBAND_BG || adhocMode == ZM_ADHOCBAND_ABG ) |
| { |
| /* #3_1 Count BSS number that influence the specificed frequency in 2.4GHz ! */ |
| for( j=0; j<count_24G; j++ ) |
| { |
| CombinationBssNumberIn24G[j] = BssNumberIn24G[j] + BssNumberIn24G[j+1] + |
| BssNumberIn24G[j+2] + BssNumberIn24G[j+3] + |
| BssNumberIn24G[j+4]; |
| //printk("After combine, the number of BSS network channel %d is %d", |
| // j , CombinationBssNumberIn24G[j]); |
| } |
| |
| /* #4_1 Find the less utilized frequency in 2.4GHz band ! */ |
| min24GIndex = zfFindMinimumUtilizationChannelIndex(dev, CombinationBssNumberIn24G, count_24G); |
| } |
| |
| /* #4_2 Find the less utilized frequency in 5GHz band ! */ |
| if( adhocMode == ZM_ADHOCBAND_A || adhocMode == ZM_ADHOCBAND_ABG ) |
| { |
| min5GIndex = zfFindMinimumUtilizationChannelIndex(dev, BssNumberIn5G, count_5G); |
| } |
| |
| if( adhocMode == ZM_ADHOCBAND_B || adhocMode == ZM_ADHOCBAND_G || adhocMode == ZM_ADHOCBAND_BG ) |
| { |
| return Array_24G[min24GIndex]; |
| } |
| else if( adhocMode == ZM_ADHOCBAND_A ) |
| { |
| return Array_5G[min5GIndex]; |
| } |
| else if( adhocMode == ZM_ADHOCBAND_ABG ) |
| { |
| if ( CombinationBssNumberIn24G[min24GIndex] <= BssNumberIn5G[min5GIndex] ) |
| return Array_24G[min24GIndex]; |
| else |
| return Array_5G[min5GIndex]; |
| } |
| else |
| return 2412; |
| } |
| |
| u16_t zfFindMinimumUtilizationChannelIndex(zdev_t* dev, u16_t* array, u16_t count) |
| { |
| u8_t i; |
| u16_t tempMinIndex, tempMinValue; |
| |
| zmw_get_wlan_dev(dev); |
| |
| i = 1; |
| tempMinIndex = 0; |
| tempMinValue = array[tempMinIndex]; |
| while( i< count ) |
| { |
| if( array[i] < tempMinValue ) |
| { |
| tempMinValue = array[i]; |
| tempMinIndex = i; |
| } |
| i++; |
| } |
| |
| return tempMinIndex; |
| } |
| |
| u8_t zfCompareWithBssid(zdev_t* dev, u16_t* bssid) |
| { |
| zmw_get_wlan_dev(dev); |
| |
| if ( zfMemoryIsEqual((u8_t*)bssid, (u8_t*)wd->sta.bssid, 6) ) |
| { |
| return 1; |
| } |
| else |
| { |
| return 0; |
| } |
| } |