mtwifi: add mt7612 support (#4968)

* mtwifi: add mt7612 support (Thx TangHaili)

* mtwifi: mt7603/7612: disable autoload (Thx TangHaili)

* ramips: newifi3: use mtwifi

* luci-app-mtwifi: sync TangHaili's Source
This commit is contained in:
AmadeusGhost 2020-07-05 11:57:49 +08:00 committed by GitHub
parent d4539c3188
commit 24cb7521b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1150 changed files with 393029 additions and 3638 deletions

View File

@ -24,8 +24,8 @@ PKG_KCONFIG:= \
AIRPLAY_SUPPORT MAC_REPEATER_SUPPORT DFS_SUPPORT NINTENDO_AP DOT11K_RRM_SUPPORT RT2860V2_SNMP\
LLTD_SUPPORT NINTENDO_AP COC_SUPPORT MULTI_CORE_SUPPORT MCAST_RATE_SPECIFIC PREVENT_ARP_SPOOFING_SUPPORT \
EXT_BUILD_CHANNEL_LIST AUTO_CH_SELECT_ENHANCE MEMORY_OPTIMIZATION RTMP_TEMPERATURE_CALIBRATION\
SNIFFER_SUPPORT CFG80211_SUPPORT SNIFFER_MIB_CMD ALL_NET_EVENT
SNIFFER_SUPPORT CFG80211_SUPPORT SNIFFER_MIB_CMD ALL_NET_EVENT
PKG_CONFIG_DEPENDS:=$(foreach c, $(PKG_KCONFIG),$(if $(CONFIG_$c),CONFIG_$(c)))
@ -38,7 +38,6 @@ define KernelPackage/mt7603e
TITLE:=MTK wifi AP driver
FILES:=$(PKG_BUILD_DIR)/mt7603_wifi_ap/mt7603e.ko
SUBMENU:=Wireless Drivers
AUTOLOAD:=$(call AutoProbe,mt7603e)
MENU:=1
endef

View File

@ -2,129 +2,126 @@ if PACKAGE_kmod-mt7603e
#if FIRST_IF_MT7603E || SECOND_IF_MT7603E
config MT7603E_FIRST_IF_MT7603E
bool
default y
depends on PACKAGE_kmod-mt7603e
bool
default y
depends on PACKAGE_kmod-mt7603e
config MT7603E_RLT_WIFI
tristate "MT WIFI Driver"
default y
tristate "MT WIFI Driver"
default y
config MT7603E_MT_WIFI_PATH
string
depends on MT7603E_RLT_WIFI
default "rlt_wifi"
string
depends on MT7603E_RLT_WIFI
default "rlt_wifi"
if MT7603E_RLT_WIFI
menu "WiFi Generic Feature Options"
if MT7603E_FIRST_IF_MT7603E
choice
prompt "EEPROM Type of 1st Card"
default MT7603E_FIRST_IF_EEPROM_FLASH
#depends on ! FIRST_IF_NONE
config MT7603E_FIRST_IF_EEPROM_FLASH
bool "FLASH"
prompt "EEPROM Type of 1st Card"
default MT7603E_FIRST_IF_EEPROM_FLASH
#depends on ! FIRST_IF_NONE
config MT7603E_FIRST_IF_EEPROM_PROM
bool "EEPROM"
config MT7603E_FIRST_IF_EEPROM_FLASH
bool "FLASH"
config MT7603E_FIRST_IF_EEPROM_EFUSE
bool "EFUSE"
config MT7603E_FIRST_IF_EEPROM_PROM
bool "EEPROM"
config MT7603E_FIRST_IF_EEPROM_EFUSE
bool "EFUSE"
endchoice
config MT7603E_RT_FIRST_CARD_EEPROM
string
#depends on ! FIRST_IF_NONE
default "prom" if MT7603E_FIRST_IF_EEPROM_PROM
default "efuse" if MT7603E_FIRST_IF_EEPROM_EFUSE
default "flash" if MT7603E_FIRST_IF_EEPROM_FLASH
string
#depends on ! FIRST_IF_NONE
default "prom" if MT7603E_FIRST_IF_EEPROM_PROM
default "efuse" if MT7603E_FIRST_IF_EEPROM_EFUSE
default "flash" if MT7603E_FIRST_IF_EEPROM_FLASH
endif
config MT7603E_MULTI_INF_SUPPORT
bool
#default y if !FIRST_IF_NONE && !SECOND_IF_NONE
default y
bool
#default y if !FIRST_IF_NONE && !SECOND_IF_NONE
default y
#config MT7603E_WIFI_BASIC_FUNC
# bool "Basic Functions"
# select WIRELESS_EXT
# select WEXT_SPY
# select WEXT_PRIV
config MT7603E_WSC_INCLUDED
bool "WSC (WiFi Simple Config)"
bool "WSC (WiFi Simple Config)"
# depends on WIFI_DRIVER
default y
default y
config MT7603E_WSC_V2_SUPPORT
bool "WSC V2(WiFi Simple Config Version 2.0)"
depends on MT7603E_MMT_WSC_INCLUDED
default y
bool "WSC V2(WiFi Simple Config Version 2.0)"
depends on MT7603E_MMT_WSC_INCLUDED
default y
config MT7603E_WSC_NFC_SUPPORT
bool "WSC out-of-band(NFC)"
# depends on WIFI_DRIVER
default n
# depends on WIFI_DRIVER
default n
config MT7603E_DOT11N_DRAFT3
bool "802.11n Draft3"
bool "802.11n Draft3"
# depends on WIFI_DRIVER
default y
default y
#config MT7603E_DOT11_VHT_AC
# bool "802.11 ac"
# depends on WIFI_DRIVER
# default n
config MT7603E_DOT11W_PMF_SUPPORT
bool "PMF Support"
bool "PMF Support"
# depends on WIFI_DRIVER
default y
default y
config MT7603E_TXBF_SUPPORT
bool "Tx Bean Forming Support"
bool "Tx Bean Forming Support"
# depends on WIFI_DRIVER
default n
default n
#config MT7603E_WMM_ACM_SUPPORT
# bool "WMM ACM"
# depends on WIFI_DRIVER
# default n
config MT7603E_LLTD_SUPPORT
bool "LLTD (Link Layer Topology Discovery Protocol)"
bool "LLTD (Link Layer Topology Discovery Protocol)"
# depends on WIFI_DRIVER
default y
default y
config MT7603E_QOS_DLS_SUPPORT
bool "802.11e DLS ((Direct-Link Setup) Support"
bool "802.11e DLS ((Direct-Link Setup) Support"
# depends on WIFI_DRIVER
default n
default n
config MT7603E_WAPI_SUPPORT
bool "WAPI Support"
bool "WAPI Support"
# depends on WIFI_DRIVER
default n
default n
config MT7603E_CARRIER_DETECTION_SUPPORT
bool "Carrier Detect"
bool "Carrier Detect"
# depends on WIFI_DRIVER
default n
default n
config MT7603E_IGMP_SNOOP_SUPPORT
bool "IGMP Snooping"
bool "IGMP Snooping"
# depends on WIFI_DRIVER
default n
default n
config MT7603E_BLOCK_NET_IF
bool "NETIF Block"
bool "NETIF Block"
# depends on WIFI_DRIVER
default n
help
Support Net interface block while Tx-Sw queue full
default n
help
Support Net interface block while Tx-Sw queue full
#config MT7603E_MT_TXBF_SUPPORT
# bool "Tx Bean Forming Support (Only 3883)"
@ -143,88 +140,88 @@ config MT7603E_BLOCK_NET_IF
# default n
config MT7603E_NEW_RATE_ADAPT_SUPPORT
bool "New Rate Adaptation support"
bool "New Rate Adaptation support"
# depends on WIFI_DRIVER
default y
default y
config MT7603E_MT_NEW_RATE_ADAPT_SUPPORT
bool "Intelligent Rate Adaption"
bool "Intelligent Rate Adaption"
# depends on WIFI_DRIVER && MT_RATE_ADAPTION
default y
default y
config MT7603E_AGS_SUPPORT
bool "Adaptive Group Switching"
depends on MT7603E_MT_RATE_ADAPTION
default n
bool "Adaptive Group Switching"
depends on MT7603E_MT_RATE_ADAPTION
default n
config MT7603E_IDS_SUPPORT
bool "IDS (Intrusion Detection System) Support"
bool "IDS (Intrusion Detection System) Support"
# depends on WIFI_DRIVER
default n
default n
config MT7603E_WIFI_WORK_QUEUE
bool "Work Queue"
bool "Work Queue"
# depends on WIFI_DRIVER
default n
default n
config MT7603E_WIFI_SKB_RECYCLE
bool "SKB Recycle(Linux)"
bool "SKB Recycle(Linux)"
# depends on WIFI_DRIVER
default n
default n
config MT7603E_RTMP_FLASH_SUPPORT
bool "Flash Support"
bool "Flash Support"
# depends on WIFI_DRIVER
default y
default y
config MT7603E_LED_CONTROL_SUPPORT
bool "LED Support"
bool "LED Support"
# depends on WIFI_DRIVER
default n
default n
config MT7603E_SINGLE_SKU
bool "Single SKU"
bool "Single SKU"
# depends on WIFI_DRIVER
default n
default n
config MT7603E_SINGLE_SKU_V2
bool "Single SKU V2"
depends on MT7603E_SINGLE_SKU && RALINK_RT6352
default n
bool "Single SKU V2"
depends on MT7603E_SINGLE_SKU && RALINK_RT6352
default n
config MT7603E_HW_ANTENNA_DIVERSITY
bool "Antenna Diversity Support"
depends on MT7603E_RLT_AP_SUPPORT || MT7603E_RLT_STA_SUPPORT
depends on RALINK_RT5350
default n
bool "Antenna Diversity Support"
depends on MT7603E_RLT_AP_SUPPORT || MT7603E_RLT_STA_SUPPORT
depends on RALINK_RT5350
default n
config MT7603E_ATE_SUPPORT
bool "ATE/QA Support"
bool "ATE/QA Support"
# depends on WIFI_DRIVER
default y
default y
config MT7603E_RT2860V2_AP_V24_DATA_STRUCTURE
bool
bool
# depends on WIFI_DRIVER
default y
default y
config MT7603E_RT2860V2_AP_32B_DESC
bool "32 Byte Descriptor Support"
bool "32 Byte Descriptor Support"
# depends on WIFI_DRIVER
depends on RALINK_RT6352 || RALINK_MT7620
default n
depends on RALINK_RT6352 || RALINK_MT7620
default n
config MT7603E_MEMORY_OPTIMIZATION
bool "Memory Optimization"
bool "Memory Optimization"
# depends on WIFI_DRIVER
default n
default n
#config MT7603E_RTMP_INTERNAL_TX_ALC
# bool "TSSI Compensation"
# depends on WIFI_DRIVER
# depends on RALINK_RT3350 || RALINK_RT3352 || RALINK_RT5350 || RALINK_RT6352
# default n
#config MT7603E_RTMP_TEMPERATURE_CALIBRATION
# bool "Temperature Calibration"
# depends on WIFI_DRIVER
@ -232,27 +229,27 @@ config MT7603E_MEMORY_OPTIMIZATION
# default n
config MT7603E_HOTSPOT
bool "Passpoint-R1"
bool "Passpoint-R1"
# depends on WIFI_DRIVER
default n
default n
config MT7603E_MT_HOTSPOT_R2
bool "Passpoint Release-2 Support"
depends on HOTSPOT
select MT7603E_MT_DOT11W_PMF_SUPPORT
default n
bool "Passpoint Release-2 Support"
depends on HOTSPOT
select MT7603E_MT_DOT11W_PMF_SUPPORT
default n
config MT7603E_MT_RTMP_TEMPERATURE_TX_ALC
bool "Temperature Tx Power Compensation"
bool "Temperature Tx Power Compensation"
# depends on WIFI_DRIVER
default n
default n
config MT7603E_UAPSD
bool "UAPSD support"
bool "UAPSD support"
# depends on WIFI_DRIVER
default y
default y
#
# Section for chip architectures
#
@ -261,7 +258,7 @@ config MT7603E_RLT_MAC
bool
# depends on WIFI_DRIVER
default n
config MT7603E_RLT_BBP
bool
@ -275,11 +272,11 @@ config MT7603E_RTMP_MAC
default n
config MT7603E_RTMP_BBP
bool
bool
config MT7603E_RTMP_RF
bool
bool
#config MT7603E_MT_EPA_ELNA
# bool "ePAeLNA"
# depends on WIFI_DRIVER
@ -296,7 +293,7 @@ config MT7603E_RTMP_RF
#
# config MT7603E_MT_EPA_ILNA
# bool "ePAiLNA"
#
#
# config MT7603E_MT_EPA_ELNA
# bool "ePAeLNA"
#endchoice
@ -340,61 +337,61 @@ config MT7603E_RTMP_RF
# Section for interfaces
#
config MT7603E_RTMP_PCI_SUPPORT
bool
bool
config MT7603E_RTMP_USB_SUPPORT
bool
bool
config MT7603E_RTMP_RBUS_SUPPORT
bool
bool
endmenu
menu "WiFi Operation Modes"
choice
prompt "Main Mode"
default MT7603E_MT_WIFI_MODE_AP
choice
prompt "Main Mode"
default MT7603E_MT_WIFI_MODE_AP
config MT7603E_MT_WIFI_MODE_AP
bool "AP"
config MT7603E_MT_WIFI_MODE_AP
bool "AP"
config MT7603E_MT_WIFI_MODE_STA
bool "STA"
config MT7603E_MT_WIFI_MODE_STA
bool "STA"
config MT7603E_MT_WIFI_MODE_BOTH
bool "APSTA"
endchoice
config MT7603E_MT_WIFI_MODE_BOTH
bool "APSTA"
endchoice
if MT7603E_MT_WIFI_MODE_AP || MT7603E_MT_WIFI_MODE_BOTH
if MT7603E_MT_WIFI_MODE_AP || MT7603E_MT_WIFI_MODE_BOTH
config MT7603E_RLT_AP_SUPPORT
tristate "UnifyMAC 802.11n AP support"
default y
# depends on NET_RADIO
select WIRELESS_EXT
select WEXT_SPY
select WEXT_PRIV
tristate "UnifyMAC 802.11n AP support"
default y
# depends on NET_RADIO
select WIRELESS_EXT
select WEXT_SPY
select WEXT_PRIV
config MT7603E_WDS_SUPPORT
bool "WDS"
depends on MT7603E_RLT_AP_SUPPORT
default n
bool "WDS"
depends on MT7603E_RLT_AP_SUPPORT
default n
config MT7603E_MBSS_SUPPORT
bool "MBSSID"
depends on MT7603E_RLT_AP_SUPPORT
default y
bool "MBSSID"
depends on MT7603E_RLT_AP_SUPPORT
default y
config MT7603E_NEW_MBSSID_MODE
bool "New MBSSID MODE"
depends on MT7603E_RLT_AP_SUPPORT && MT7603E_MBSS_SUPPORT
# depends on RALINK_RT3883 || RALINK_RT3352 || RALINK_RT5350 || RALINK_RT6352 || RALINK_MT7620 || RALINK_MT7621
default n
bool "New MBSSID MODE"
depends on MT7603E_RLT_AP_SUPPORT && MT7603E_MBSS_SUPPORT
# depends on RALINK_RT3883 || RALINK_RT3352 || RALINK_RT5350 || RALINK_RT6352 || RALINK_MT7620 || RALINK_MT7621
default n
config MT7603E_ENHANCE_NEW_MBSSID_MODE
bool "Enhanced MBSSID mode"
depends on MT7603E_NEW_MBSSID_MODE
default n
bool "Enhanced MBSSID mode"
depends on MT7603E_NEW_MBSSID_MODE
default n
config MT7603E_CFG80211_SUPPORT
bool "CFG80211"
depends on MT7603E_RLT_AP_SUPPORT
@ -413,34 +410,34 @@ config MT7603E_ALL_NET_EVENT
config MT7603E_ACL_V2_SUPPORT
bool "ACL_V2"
depends on MT7603E_RLT_AP_SUPPORT
config MT7603E_APCLI_SUPPORT
bool "AP-Client Support"
depends on MT7603E_RLT_AP_SUPPORT
default y
bool "AP-Client Support"
depends on MT7603E_RLT_AP_SUPPORT
default y
config MT7603E_MULTI_APCLI_SUPPORT
bool "MULTI AP-Client Support"
depends on MT7603E_APCLI_SUPPORT
default y
default y
config MT7603E_MAC_REPEATER_SUPPORT
bool "MAC Repeater Support"
depends on MT7603E_RLT_AP_SUPPORT
depends on MT7603E_APCLI_SUPPORT
depends on RALINK_RT6352 || RALINK_MT7620 || MT7603E_RALINK_MT7603E
default y
bool "MAC Repeater Support"
depends on MT7603E_RLT_AP_SUPPORT
depends on MT7603E_APCLI_SUPPORT
depends on RALINK_RT6352 || RALINK_MT7620 || MT7603E_RALINK_MT7603E
default y
config MT7603E_AIRPLAY_SUPPORT
bool "AirPlay Support"
depends on MT7603E_APCLI_SUPPORT
#config MT7603E_MT_MESH_SUPPORT
# bool "MESH Support"
# depends on MT7603E_RLT_AP_SUPPORT
config MT7603E_DFS_SUPPORT
bool "DFS"
depends on MT7603E_RLT_AP_SUPPORT
select RALINK_TIMER_DFS
bool "DFS"
depends on MT7603E_RLT_AP_SUPPORT
select RALINK_TIMER_DFS
#config MT7603E_DOT11R_FT_SUPPORT
# bool "802.11r Fast BSS Transition"
@ -451,30 +448,30 @@ config MT7603E_DFS_SUPPORT
# depends on MT7603E_RLT_AP_SUPPORT
config MT7603E_LLTD_SUPPORT
bool "LLTD (Link Layer Topology Discovery Protocol)"
depends on MT7603E_RLT_AP_SUPPORT
default y
bool "LLTD (Link Layer Topology Discovery Protocol)"
depends on MT7603E_RLT_AP_SUPPORT
default y
config MT7603E_NINTENDO_AP
bool "Nintendo AP"
depends on MT7603E_RLT_AP_SUPPORT
bool "Nintendo AP"
depends on MT7603E_RLT_AP_SUPPORT
config MT7603E_COC_SUPPORT
bool "CoC Support"
depends on MT7603E_RLT_AP_SUPPORT
default n
bool "CoC Support"
depends on MT7603E_RLT_AP_SUPPORT
default n
#config MT7603E_ RT2860V2_SNMP
# bool "Net-SNMP Support"
# depends on MT7603E_RLT_AP_SUPPORT
config MT7603E_MCAST_RATE_SPECIFIC
bool "User specific tx rate of mcast pkt"
depends on MT7603E_RLT_AP_SUPPORT
bool "User specific tx rate of mcast pkt"
depends on MT7603E_RLT_AP_SUPPORT
config MT7603E_PREVENT_ARP_SPOOFING_SUPPORT
bool "Detect ARP spoof pkts attack"
depends on MT7603E_RLT_AP_SUPPORT
#config MT7603E_EXT_BUILD_CHANNEL_LIST
# bool "Extension Channel List"
# depends on MT7603E_RLT_AP_SUPPORT
@ -483,22 +480,22 @@ config MT7603E_PREVENT_ARP_SPOOFING_SUPPORT
# bool "Auto Channel Selection Enhancement"
# depends on MT7603E_RLT_AP_SUPPORT
config MT7603E_MULTI_CORE_SUPPORT
bool "multi core support"
depends on TARGET_ramips_mt7621
default n
config MT7603E_MULTI_CORE_SUPPORT
bool "multi core support"
depends on TARGET_ramips_mt7621
default n
endif
endif
source "./src/mt7603_wifi_ap/Kconfig"
endmenu
source "./src/mt7603_wifi_ap/Kconfig"
endmenu
#"MT7603E"
config MT7603E_RALINK_MT7603E
bool
default y
select MT7603E_RTMP_PCI_SUPPORT
bool
default y
select MT7603E_RTMP_PCI_SUPPORT
endif
@ -516,9 +513,9 @@ endif
#if MT7603E_MT_MAC
if MT7603E_RALINK_MT7603E
config MT7603E_MT_MAC
bool
default y
config MT7603E_MT_MAC
bool
default y
endif
#endif MT7603E_MT_WIFI
#endif

View File

@ -0,0 +1,49 @@
# All rights reserved.
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=mt76x2e
P4REV:=8
PKG_VERSION:=3.0.5.0
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/mt76x2
PKG_KCONFIG:= \
RT_FIRST_CARD RT_SECOND_IF_MT7612E RT_SECOND_CARD AP_LLTD AP_LED AP_WDS AP_MBSS AP_MBSS_NEW_MBSSID_MODE \
AP_APCLI AP_80211AC_VHT AP_TXBF_SUPPORT \
PKG_CONFIG_DEPENDS:=$(foreach c, $(PKG_KCONFIG),$(if $(CONFIG_$c),CONFIG_$(c)))
include $(INCLUDE_DIR)/package.mk
TAR_CMD=$(HOST_TAR) -C $(1)/ $(TAR_OPTIONS)
define KernelPackage/mt76x2e
CATEGORY:=Kernel modules
TITLE:=MTK MT76x2e wifi AP driver
FILES:=$(PKG_BUILD_DIR)/mt76x2_ap/mt76x2_ap.ko
SUBMENU:=Wireless Drivers
MENU:=1
endef
define KernelPackage/mt76x2e/config
source "$(SOURCE)/config.in"
endef
define Build/Compile
$(MAKE) -C "$(LINUX_DIR)" V=1 \
CROSS_COMPILE="$(TARGET_CROSS)" \
ARCH="$(LINUX_KARCH)" \
M="$(PKG_BUILD_DIR)/mt76x2_ap" \
$(foreach c, $(PKG_KCONFIG),$(if $(CONFIG_MT76X2E_$c),CONFIG_$(c)=$(CONFIG_MT76X2E_$(c)))) \
modules
endef
define KernelPackage/mt76x2e/install
$(INSTALL_DIR) $(1)/etc/wireless/mt7612/
endef
$(eval $(call KernelPackage,mt76x2e))

View File

@ -0,0 +1,49 @@
if PACKAGE_kmod-mt76x2e
config MT76X2E_RT_SECOND_IF_MT7612E
bool
default y
config MT76X2E_RT_FIRST_CARD
int
default 7603
config MT76X2E_RT_SECOND_CARD
int
default 7612
config MT76X2E_AP_LED
bool
default y
config MT76X2E_AP_LLTD
bool
default y
config MT76X2E_AP_WDS
bool
default y
config MT76X2E_AP_MBSS
bool
default y
config MT76X2E_AP_MBSS_NEW_MBSSID_MODE
bool
default y
config MT76X2E_AP_APCLI
bool
default y
config MT76X2E_AP_80211AC_VHT
bool
default y
config MT76X2E_AP_TXBF_SUPPORT
bool
default n
endif

View File

@ -0,0 +1,276 @@
[V2.x.x.x]
P4V. Test
[V2.5.0.0]
1. Add mac80211 iw utility other commands support.
Rename crda.c to cfg80211.c, CRDA_SUPPORT to RT_CFG80211_SUPPORT.
2. Fix issue: No McuCmdLock initialization for RT3592/RT3390.
3. Fix issue: The start address of HeaderBuf must be aligned by 4 when
VENDOR_FEATURE1_SUPPORT is enabled.
4. WMM ACM: see history of acm_comm.c.
5. Fix issue: sometimes rt2860_interrupt() will be called before rt28xx_init()
in fedora core 7.
6. Add RT3592 PCIe chip ID.
7. Fix issue in 64bit CPU:
(1) WMM ACM: see history of acm_comm.c.
(2) Fix function RTMP_MapChannelID2KHZ().
8. CFG80211: Patch for Linux 2.6.32.
9. Add an ATE command for AUTOALC.
10. Add an ATE command for interpacket GAP.
11. Add an ATE command for ATE payload pattern.
12. Fix issue: UAPSD SP can not be closed correctly for mix-mode power save.
UAPSD + legacy PS.
13. [Bug fixed] The extended rate of probe-req is disappeared in AP-Client mode
14. Add RT3593 PCI/PCIe AP/STA.
15. Fix issue: kernel panic when we forward VLAN bc/mc packet to wireless LAN.
16. Fix issue: some reports from Prevent software analysis tool.
17. Fix issue: get wrong VLAN priority from VLAN tag in RTMPCheckEtherType().
18. Fix issue: no 11b basic rate in beacon when we change WirelessMode to 2.4G,
then 5G, then 2.4G
19. Fix issue: no 11b-only mode can be set in AP mode.
20. MBSS: add function to set different phy mode for different BSS.
21. Phy Mode: add check if the chip supports 5G band when WirelessMode is 5G band
for command WirelessMode and MBSSWirelessMode.
22. QLOAD: Fix issue for big endian.
Or value of QLOAD element in beacon will be wrong.
23. USB: Fix timer trigger fail after APStop and then APStartup.
Side effect1: Power save can not work in AP mode when you do channel
switch because channel switch will do APStop() and APStart().
Side effect2: After radion on/off, TIM will not be updated due to beacon
timer is not started.
24. Station: Add new rate switch algorithm (AGS) for 1*1, 2*2, 3*3.
25. AP: Fix power save problem when station is in power-save mode and send
(re)associate frame again we will think the station is still in PS mode,
but the station is in ACTIVE mode.
26. TX Block: Fix no packet can be sent when TX Fail count > a threshold for
non-WDS interface in RTMPDeQueuePacket().
27. Fix WPS issue: WPS process failed with some WPS Client that sends dis-assoc close to WSC_DONE.
28. Refine the stack size of all functions to be smaller than 300B.
29. Fix bugs when protocol field of packet & 0x8080 does not equal to 0.
Such as PPPOE.
30. Fix issue: Wrong MACRO use for RTMP_SET_PACKET_DHCP ~ RTMP_SET_PACKET_IPV4.
31. Fix ACM issue: Need also to unlock after calling ACMP_MsduClassify() in USB.
32. Fix IGMP bc/mc User Priority issue: Need also to get UP for bc/mc packets.
[V2.4.0.0]
1. AMSDU supports NO-ACK.
2. Added new channel list of A-Band Region 16
3. Basic Ethtool support. (i.e. GSO)
4. Fix issue: PCI command thread initialization in pci_main_dev.c
init_waitqueue_head(&pAd->cmdQTask.kthread_q); for KTHREAD_SUPPORT
5. WMM ACM: see history of acm_comm.c.
6. Fix issue: When PS-Poll is received in AP and STA is not WMM device and
no any queued packet, we will reply DATA NULL frame. We will double-lock.
7. AP QLOAD: Add compile option.
8. Add CRDA function in Linux 2.6.28 above.
9. Increase channel property. Property is only set in CRDA function currently.
10. RSSI feedback supported(only with Ralink client).
11. Fix issue: Wmm capable will be enabled from ABG mode to N mode but Wmm capable is
not recovered when from N mode to ABG mode.
12. Two iwpriv commands "ACLDelEntry" and "ACLShowAll" are added.
13. Support 802.11v draft 5.0 WNM - BSS transition Management and DMS.
14. Add OS abstract layer partition, util.ko, driver.ko, and netif.ko
15. Support ApClient WPS PBC.
[V2.3.0.0]
1. WMM ACM AP/STA support. (Pass WiFi Test Plan v0.30)
2. Add HAS_STATS_COUNT compile option.
3. Provide some 802.1x parameter support(Quiet-period, idle-timeout, NAD-ID).
4. Fix issue : The Tx date rate can't be fixed in B/G PHY mode.
5. QLOAD: Add status information display function. "qload show" & QloadClr.
6. QLOAD: Add channel busy alarm and a command thread in PCI/USB driver.
7. It supports the MAC assignment from configuration file(.dat).
8. Fix issue : No packet is delivered from AP when PsMode from PS to ACTIVE.
9. Fast Power Save : Use Null frame with PM=0 to get buffered packet, not PS-Poll in station mode.
10. miniupnpd supported.
11. AP-Client and WDS support fixed rate.
12. Support GreenAP.
13. Support Single SKU.
14. Fix issue : RT3062/RT3562 can't enable/disable Radio.
15. Discard IgmpSn enable setting per BSSID and change it to as global setting.
[V2.2.0.0]
1. New generation schema for multiple OS porting
2. New chip support for RT3572
3. New chip support for RT3062/RT3562
4. Restrict the encryption type in HT mode.
5. Support 802.1x reauthentication mechanism.
6. Limit the STA connection count per BSS.
7. Some variables support MBSS setting.
8. Support WDS entry life check function.
9. Support Mesh Air link time.
10. Support Mesh Link Metric report action.
11. Support Dot11K RRM for all testing cases of voice-enterprise testing event.
12. Performance Tune.
[V2.1.1.0]
1. fix eFuse bug on big-endian platform
2. fix WMM problem for RT3071/72
3. fix one bug for ATE TX power handling and ATE frequency offset bug.
4. fix mesh crash issue
5. fix RT307x AMPDU throughput bug after interface down/up
6. update RT307x new firmware.
[V2.1.0.0]
1. Support new chips RT3070/71/72, RT3090/91/92.
2. Fix bugs: fix WMM, Mesh, WDS, AP Client and DLS problems for Amazon SE platform
3. Fix bug: memory leakage problem when interface up/down.
4. Support eFuse.
[V2.0.0.0]
1. Added Global Country Domain supported.
2. Fix bug: suspend/resume error when ra0 down, rax up
3. Add new UAPSD SP counting mechanism.
4. Fix bug: Ikanos WDS, AP Client, Mesh interface get problem.
5. Add new WSC hardware push button function for PCI & USB.
6. Added a function allow user to specific Tx rate for Mcast packets.
7. Migrate Mesh supporting to Draft-2.0.
8. Support WAPI functionality
9. Modify the priority of BAR transmission to solve the connection issue with Intel 4965 11n STA.
10. Fix RT2870 USB suspend/resume.
[V1.9.0.0]
1. Replace iwpriv cmd "AccessControlList" by "ACLAddEntry" and "ACLClearAll"
2. Fixed the wrong usage of AtoH().
3. Support new Windows ATE GUI.
4. Add a command "iwpriv ra0 set ATERE2P=1" to display all EEPROM content.
5. Correct the limitation of the length of fragment.
6. Fix bug: Fail to transmit packets through AMPDU way except the case that AP to STA.
7. Wrong Hareware packet length calculation of Mesh packet if it been Fragmented.
8. Support SIGMA 8622/8624 platform.
9. Add WPS PBC Session Overlap Detecting.
10. Add WPS 4-PinCode Support.
11. Fixed WPS enable PSP can not associate AP when AP security set to WPA-PSK.
12. Fix "Suspend to Disk" problem for USB
[V1.8.0.0]
1. Show Tx/Rx statistics per MBSS.
2. 802.1x supports failover mechanism.
3. Add watchdog to prevent MAC/BBP into the deadlock condition.
4. Support pure 11n with 5G band.
5. Update Timer Functions
6. In multiple cards application, the interface name is changed to raxx_k, where xx means card ID (0 ~ 31) and
k means the BSS number (0 ~ 7)
7. Support individual MCS per BSS.
8. Add IKANOS Vx160 and Vx180.
9. Add station keep alive detection function in AP mode.
10. The SIFS of CCK is changed to 16 micro seconds to fix the connection problem with INTEL 2200bg cards.
11. QBSS Load Element is added to provide channel utilization information to all STAs.
12. Fix bug : After AP re-key, the ping connection from client to AP would be time-out within several seconds.
13. Support Mesh function.
14. Big-endian ATE supported.
[V1.7.0.0]
1. Support IDS notification mechanism
2. Change IRQ LOCK to SEM LOCK
3. Fix bug : When QoS(non-BE) and fragment packets are received, AP would calculate wrong MIC in TKIP mode.
4. Support Non-GPL MD5
5. Update Group rekey mechanism
6. Fix BA time-out issue for Intel wireless card 4965AGN with version 11.5.0.32.
7. Add command "iwpriv ra0 set ATELDE2P=1" to overwrite all EEPROM contents from "/etc/Wireless/RT2860(/70)AP(/STA)/e2p.bin".
8. Fix RTS threshold issue in 5G-band
9. Add DLS Function.
10. IPV6 MLDv2 support
11. Fix VLAN ID >= 256 can not be used.
12 Added PCIE MSI supporting for RT2890.
13 Added new channel list builder that create channel list according to country-code and channel Geography(in/out door).
[V1.6.0.0]
1. Fix bug : Before AP shutdown, AP doesn't noify those associated STA through dis-association.
2. Fix bug : The Atheros wireless STA card built in MacBook can't work normally when HT mode and the encryption is WEP or TKIP.
3. The support region in A band synchronizes with EEPROM.
4. It supports to initialize current wireless MAC address from E2PROM or module parameter.
5. Support maximum 8 MBSS and each beacon maximum length is 512 bytes.
6. Support 5-GHz band ATE.
7. Send DisAssoc frame to timeout STA.
8. Workaround for Atheros STA on AES mode.
9. Tx RTS/CTS when AP setup BA.
10. Driver sends IAPP L2 frame instread of Daemon.
11. Correct some timeout values of WPS.
12. Fix bug : The 802.1x daemon(rt2860apd) has some problem for parsing multiple parameters in MBSS.
13. Fix bug : The AP site survey signal isn't correct.
14. Provide some 11n statistics variables.
15. Fix bug : RT2561 module can not be removed after RT2860 module is inserted.
16. Added DEO (100 ~ 140) channel list for Ganmany.
17. Support wds phy mode and security setting for each wds link.
18. Fix bug : The Atheros legacy USB STA card can't connect to our AP in WPA-TKIP.
19. Modify rate adaptation for fast ramp-up tuning.
20. Fix WPS IOT issue with Atheros externnal registrar. Need Sync the user space daemon "wscd" to version 0.1.0
21. Fix bug : The BlackBerry/HTC can't connect to our AP.
22. Correct the default values of those WMM EDCA parameters.
23. Fix low throughput issue in Intel certification test.
[V1.5.0.0]
1. Added McastPhyMode and McastMcs iwpriv commands let user to specifice the rate for Multicast packets transmition.
2. Added two configrations of McastPhyMode and McastMcs.
3. Re-organize the WPA state machine in order to the consistency between AP and AP-Client.
4. Added DFS support.
5. Added Carrier-Sense suppport.
6. Fixed a bug about dissection issue in profile.
7. Fixed CountryRegion and channel map, when profile's channel have not on channel list.
8. Fixed 802.1x Authentication problem with 1x-WEP/WPA(2)-Enterprise when WPS is enabled.
9. Fix bug : Once the radio is off and on, the beacon frames disappear.
[V1.4.0.0]
1. Wireless IGMP snooping support for multimedia steaming.
2. Access control list support
3. Re-organize the Rx data path.
4. AP client WPS support.
5. Fix the Auto-selecting channel issue.
6. Add CountryString ioctl command function.
7. Buf fix for Atheros WPS STA can not config WPS AP when Athros JumpStart STA is external Registrar.
8. Merge for WCN test modify to WPS functions.
9. Patch for 11n requirement, if HT mode is set and BW is 40MHz in A-band, the supported Channel number must be the multiple of 2.
10. Fix bug: If STA card operated with zero-config, the group rekey negotiation of WPA2(PSK)-AES always fails.
11. Add Tx & Rx Stream functionality.
12. Support QA user interface for ATE function.
[V1.3.0.0]
1. add vlan tag support for each BSS
2. add support for 32bit/64bit Linux
3. merge in plugfest code
4. Support Ap-Client function
5. Add new parameter "bWiFiTest" for WPA & WMM WiFi-Test.
6. Add the setting of Japan filter coefficients for ATE.
7. Fix bug for channel have not update when auto channel select was true.
[V1.2.1.0]
1. add protect for RTMP_IRQ_LOCK to avoid in spin_lock_irqsave call spin_lock_bh cause kernel waring messages.
2. tag one branch named V_1_2_1_0 (v1.2.1.0) in the CVS
[V1.2.0.0]
1. set BBP R66 to 0x38 in 20 MHz band
2. Disable one mechanism - change 40 to 20 MHz automatically when detecting other legacy APs with beacon.
3. Fix bug for counterMeasures in WiFi test
4. Write TXWI in ATE's way and disable any protection mechanism when ATE is running.
5. Asic only takes care of the sequence number of beacon frame.
6. disable ATE RSSI statistics when ATE is not running.
7. Set CW_MAX from 10 to 6 in AP mode.
8. Select DAC according to HT or Legacy mode.
9. Support WPA2 Pre-authemtication.
10. Fix WDS panic bug
11. Shift skb control block used by driver to offset 10 to avoid dirty cb[] from protocol stack
12. modify mac register "PBF_MAX_PCNT" from 0x1F3f7f9f to 0x1f3fbf9f
13. Fix issue - 802.1X daemon may cause throughput reduction.
14. Support Wireless event log mechanism.
15. Add a 200ms-timer to enqueue EAPoL-Start for WPAPSK, not RtmpusecDelay.
16. modify mac register "EXP_ACK_TIME" from 0x002400ca to 0x005400ca.
17. Auto-selecting channel check.
[V1.1.0.0]
1. Add fast rate switch from Windows code
2. tune BBP R66, R62, R63, R64, R86 by bandwidth and G/A band different value
3. Modify release to DPA and DPB
4. Modify fast rate switch timer form periodic to trigger by condition, same with Windows
5. Fix UAPSD bugs for null frame was drop
6. Fix management queue pass qos null frame ...
7. Code freeze for Wifi
8. fix 5vt packet set to 0 to clear cb[22]
9. merge code from Plugfest #6
10. add "iwpriv ra0 show driverinfo" to show the driver version
11. fix rt_config.h tag of Support station with tab
12. merge ATE code request by Gemtek
13. remove 5VT enhancement in RX path
[V1.0.0.0]
1.RT2860c emulation ping ok

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,188 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2006, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
ap_apcli.c
Abstract:
Support AP-Client function.
Note:
1. Call RT28xx_ApCli_Init() in init function and
call RT28xx_ApCli_Remove() in close function
2. MAC of ApCli-interface is initialized in RT28xx_ApCli_Init()
3. ApCli index (0) of different rx packet is got in
APHandleRxDoneInterrupt() by using FromWhichBSSID = pEntry->apidx;
Or FromWhichBSSID = BSS0;
4. ApCli index (0) of different tx packet is assigned in
rt28xx_send_packets() by using RTMP_SET_PACKET_NET_DEVICE_APCLI()
5. ApCli index (0) of different interface is got in APHardTransmit() by using
RTMP_GET_PACKET_IF()
6. ApCli index (0) of IOCTL command is put in pAd->OS_Cookie->ioctl_if
8. The number of ApCli only can be 1
9. apcli convert engine subroutines, we should just take care data packet.
Revision History:
Who When What
-------------- ---------- ----------------------------------------------
Shiang, Fonchi 02-13-2007 created
*/
#define RTMP_MODULE_OS
#ifdef APCLI_SUPPORT
/*#include "rt_config.h" */
#include "rtmp_comm.h"
#include "rt_os_util.h"
#include "rt_os_net.h"
struct rtnl_link_stats64 *
RT28xx_get_apcli_ether_stats64(PNET_DEV net_dev, struct rtnl_link_stats64 *stats);
/*
========================================================================
Routine Description:
Init AP-Client function.
Arguments:
pAd points to our adapter
main_dev_p points to the main BSS network interface
Return Value:
None
Note:
1. Only create and initialize virtual network interfaces.
2. No main network interface here.
========================================================================
*/
VOID RT28xx_ApCli_Init(VOID *pAd, PNET_DEV main_dev_p)
{
RTMP_OS_NETDEV_OP_HOOK netDevOpHook;
/* init operation functions */
NdisZeroMemory(&netDevOpHook, sizeof(RTMP_OS_NETDEV_OP_HOOK));
netDevOpHook.open = ApCli_VirtualIF_Open;
netDevOpHook.stop = ApCli_VirtualIF_Close;
netDevOpHook.xmit = rt28xx_send_packets;
netDevOpHook.ioctl = rt28xx_ioctl;
netDevOpHook.get_stats = RT28xx_get_apcli_ether_stats64;
RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_APC_INIT,
0, &netDevOpHook, 0);
}
/*
========================================================================
Routine Description:
Open a virtual network interface.
Arguments:
dev_p which WLAN network interface
Return Value:
0: open successfully
otherwise: open fail
Note:
========================================================================
*/
INT ApCli_VirtualIF_Open(PNET_DEV dev_p)
{
VOID *pAd;
pAd = RTMP_OS_NETDEV_GET_PRIV(dev_p);
ASSERT(pAd);
DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> %s\n", __FUNCTION__, RTMP_OS_NETDEV_GET_DEVNAME(dev_p)));
if (VIRTUAL_IF_UP(pAd) != 0)
return -1;
/* increase MODULE use count */
RT_MOD_INC_USE_COUNT();
RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_APC_OPEN, 0, dev_p, 0);
return 0;
}
/*
========================================================================
Routine Description:
Close a virtual network interface.
Arguments:
dev_p which WLAN network interface
Return Value:
0: close successfully
otherwise: close fail
Note:
========================================================================
*/
INT ApCli_VirtualIF_Close(PNET_DEV dev_p)
{
VOID *pAd;
pAd = RTMP_OS_NETDEV_GET_PRIV(dev_p);
ASSERT(pAd);
DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> %s\n", __FUNCTION__, RTMP_OS_NETDEV_GET_DEVNAME(dev_p)));
RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_APC_CLOSE, 0, dev_p, 0);
VIRTUAL_IF_DOWN(pAd);
RT_MOD_DEC_USE_COUNT();
return 0;
}
/*
========================================================================
Routine Description:
Remove ApCli-BSS network interface.
Arguments:
pAd points to our adapter
Return Value:
None
Note:
========================================================================
*/
VOID RT28xx_ApCli_Remove(VOID *pAd)
{
RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_APC_REMOVE, 0, NULL, 0);
}
#endif /* APCLI_SUPPORT */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,928 @@
/****************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
****************************************************************************
Module Name:
auth.c
Abstract:
Handle de-auth request from local MLME
Revision History:
Who When What
-------- ---------- ----------------------------------------------
John Chang 08-04-2003 created for 11g soft-AP
*/
#include "rt_config.h"
#ifdef DOT11R_FT_SUPPORT
#include "ft.h"
#endif /* DOT11R_FT_SUPPORT */
static VOID APMlmeDeauthReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem);
static VOID APPeerDeauthReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem);
static VOID APPeerAuthReqAtIdleAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem);
static VOID APPeerAuthConfirmAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem);
static VOID APPeerAuthSimpleRspGenAndSend(
IN PRTMP_ADAPTER pAd,
IN PHEADER_802_11 pHdr80211,
IN USHORT Alg,
IN USHORT Seq,
IN USHORT StatusCode,
IN UINT32 apidx);
/*
==========================================================================
Description:
authenticate state machine init, including state transition and timer init
Parameters:
Sm - pointer to the auth state machine
Note:
The state machine looks like this
AP_AUTH_REQ_IDLE
APMT2_MLME_DEAUTH_REQ mlme_deauth_req_action
==========================================================================
*/
void APAuthStateMachineInit(
IN PRTMP_ADAPTER pAd,
IN STATE_MACHINE *Sm,
OUT STATE_MACHINE_FUNC Trans[])
{
StateMachineInit(Sm, (STATE_MACHINE_FUNC *)Trans, AP_MAX_AUTH_STATE,
AP_MAX_AUTH_MSG, (STATE_MACHINE_FUNC)Drop,
AP_AUTH_REQ_IDLE, AP_AUTH_MACHINE_BASE);
/* the first column */
StateMachineSetAction(Sm, AP_AUTH_REQ_IDLE, APMT2_MLME_DEAUTH_REQ,
(STATE_MACHINE_FUNC)APMlmeDeauthReqAction);
StateMachineSetAction(Sm, AP_AUTH_REQ_IDLE, APMT2_PEER_DEAUTH,
(STATE_MACHINE_FUNC)APPeerDeauthReqAction);
StateMachineSetAction(Sm, AP_AUTH_REQ_IDLE, APMT2_PEER_AUTH_REQ,
(STATE_MACHINE_FUNC)APPeerAuthReqAtIdleAction);
StateMachineSetAction(Sm, AP_AUTH_REQ_IDLE, APMT2_PEER_AUTH_CONFIRM,
(STATE_MACHINE_FUNC)APPeerAuthConfirmAction);
}
/*
==========================================================================
Description:
Upper Layer request to kick out a STA
==========================================================================
*/
static VOID APMlmeDeauthReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
MLME_DEAUTH_REQ_STRUCT *pInfo;
HEADER_802_11 Hdr;
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
ULONG FrameLen = 0;
MAC_TABLE_ENTRY *pEntry;
UCHAR apidx;
pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg;
if (Elem->Wcid < MAX_LEN_OF_MAC_TABLE)
{
pEntry = &pAd->MacTab.Content[Elem->Wcid];
if (!pEntry)
return;
#ifdef WAPI_SUPPORT
WAPI_InternalCmdAction(pAd,
pEntry->AuthMode,
pEntry->apidx,
pEntry->Addr,
WAI_MLME_DISCONNECT);
#endif /* WAPI_SUPPORT */
/* send wireless event - for deauthentication */
RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pInfo->Addr, 0, 0);
ApLogEvent(pAd, pInfo->Addr, EVENT_DISASSOCIATED);
apidx = pEntry->apidx;
/* 1. remove this STA from MAC table */
MacTableDeleteEntry(pAd, Elem->Wcid, pInfo->Addr);
/* 2. send out DE-AUTH request frame */
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if (NStatus != NDIS_STATUS_SUCCESS)
return;
DBGPRINT(RT_DEBUG_TRACE,
("AUTH - Send DE-AUTH req to %02x:%02x:%02x:%02x:%02x:%02x\n",
PRINT_MAC(pInfo->Addr)));
MgtMacHeaderInit(pAd, &Hdr, SUBTYPE_DEAUTH, 0, pInfo->Addr,
pAd->ApCfg.MBSSID[apidx].wdev.if_addr,
pAd->ApCfg.MBSSID[apidx].wdev.bssid);
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &Hdr,
2, &pInfo->Reason,
END_OF_ARGS);
MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
#ifdef SMART_MESH_MONITOR
{
struct nsmpif_drvevnt_buf drvevnt;
drvevnt.data.leave.type = NSMPIF_DRVEVNT_STA_LEAVE;
drvevnt.data.leave.channel = pAd->CommonCfg.Channel;
NdisCopyMemory(drvevnt.data.leave.sta_mac, pInfo->Addr, MAC_ADDR_LEN);
RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_STA_LEAVE,
NULL, (PUCHAR)&drvevnt.data.leave, sizeof(drvevnt.data.leave));
}
#endif /* SMART_MESH_MONITOR */
}
}
static VOID APPeerDeauthReqAction(
IN PRTMP_ADAPTER pAd,
IN PMLME_QUEUE_ELEM Elem)
{
UCHAR Addr2[MAC_ADDR_LEN];
USHORT Reason;
UINT16 SeqNum;
MAC_TABLE_ENTRY *pEntry;
if (! PeerDeauthReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &SeqNum, &Reason))
return;
pEntry = NULL;
/*pEntry = MacTableLookup(pAd, Addr2); */
if (Elem->Wcid < MAX_LEN_OF_MAC_TABLE)
{
pEntry = &pAd->MacTab.Content[Elem->Wcid];
//JERRY
{
MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[pEntry->apidx];
PFRAME_802_11 Fr = (PFRAME_802_11)Elem->Msg;
unsigned char *tmp = (unsigned char *)pMbss->wdev.bssid;
unsigned char *tmp2 = (unsigned char *)&Fr->Hdr.Addr1;
if (memcmp(&Fr->Hdr.Addr1, pMbss->wdev.bssid, 6) != 0)
{
DBGPRINT(RT_DEBUG_TRACE, ("da not match bssid,bssid:0x%02x%02x%02x%02x%02x%02x, addr1:0x%02x%02x%02x%02x%02x%02x\n",
*tmp, *(tmp+1), *(tmp+2), *(tmp+3), *(tmp+4), *(tmp+5),
*tmp2, *(tmp2+1), *(tmp2+2), *(tmp2+3), *(tmp2+4), *(tmp2+5)));
return;
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("da match,0x%02x%02x%02x%02x%02x%02x\n",
*tmp, *(tmp+1), *(tmp+2), *(tmp+3), *(tmp+4), *(tmp+5)));
}
}
#ifdef DOT1X_SUPPORT
/* Notify 802.1x daemon to clear this sta info */
if (pEntry->AuthMode == Ndis802_11AuthModeWPA ||
pEntry->AuthMode == Ndis802_11AuthModeWPA2 ||
pAd->ApCfg.MBSSID[pEntry->apidx].wdev.IEEE8021X)
DOT1X_InternalCmdAction(pAd, pEntry, DOT1X_DISCONNECT_ENTRY);
#endif /* DOT1X_SUPPORT */
#ifdef WAPI_SUPPORT
WAPI_InternalCmdAction(pAd,
pEntry->AuthMode,
pEntry->apidx,
pEntry->Addr,
WAI_MLME_DISCONNECT);
#endif /* WAPI_SUPPORT */
/* send wireless event - for deauthentication */
RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, Addr2, 0, 0);
ApLogEvent(pAd, Addr2, EVENT_DISASSOCIATED);
if (pEntry->CMTimerRunning == TRUE)
{
/*
If one who initilized Counter Measure deauth itself,
AP doesn't log the MICFailTime
*/
pAd->ApCfg.aMICFailTime = pAd->ApCfg.PrevaMICFailTime;
}
#ifdef APCLI_SUPPORT
if (pEntry && !(IS_ENTRY_APCLI(pEntry)))
#endif /* APCLI_SUPPORT */
{
MacTableDeleteEntry(pAd, Elem->Wcid, Addr2);
}
#ifdef APCLI_SUPPORT
else
{
DBGPRINT(RT_DEBUG_OFF, ("%s: receive not client de-auth ###\n", __FUNCTION__));
}
#endif /* APCLI_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE,
("AUTH - receive DE-AUTH(seq-%d) from "
"%02x:%02x:%02x:%02x:%02x:%02x, reason=%d\n",
SeqNum, PRINT_MAC(Addr2), Reason));
#ifdef MAC_REPEATER_SUPPORT
if (pAd->ApCfg.bMACRepeaterEn == TRUE)
{
UCHAR apCliIdx, CliIdx, isLinkValid;
REPEATER_CLIENT_ENTRY *pReptEntry = NULL;
pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, Addr2, TRUE, &isLinkValid);
if (pReptEntry && (pReptEntry->CliConnectState != 0))
{
apCliIdx = pReptEntry->MatchApCliIdx;
CliIdx = pReptEntry->MatchLinkIdx;
#ifdef DOT11_N_SUPPORT
/* free resources of BA*/
BASessionTearDownALL(pAd, pReptEntry->MacTabWCID);
#endif /* DOT11_N_SUPPORT */
RTMPRemoveRepeaterDisconnectEntry(pAd, apCliIdx, CliIdx);
RTMPRemoveRepeaterEntry(pAd, apCliIdx, CliIdx);
}
}
#endif /* MAC_REPEATER_SUPPORT */
#ifdef SMART_MESH_MONITOR
{
struct nsmpif_drvevnt_buf drvevnt;
drvevnt.data.leave.type = NSMPIF_DRVEVNT_STA_LEAVE;
drvevnt.data.leave.channel = pAd->CommonCfg.Channel;
NdisCopyMemory(drvevnt.data.leave.sta_mac, Addr2, MAC_ADDR_LEN);
RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_STA_LEAVE,
NULL, (PUCHAR)&drvevnt.data.leave, sizeof(drvevnt.data.leave));
}
#endif /* SMART_MESH_MONITOR */
}
}
static VOID APPeerAuthReqAtIdleAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
INT i;
USHORT Seq, Alg, RspReason, Status;
UCHAR Addr1[MAC_ADDR_LEN];
UCHAR Addr2[MAC_ADDR_LEN];
CHAR Chtxt[CIPHER_TEXT_LEN];
UINT32 apidx;
PHEADER_802_11 pRcvHdr;
HEADER_802_11 AuthHdr;
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
ULONG FrameLen = 0;
MAC_TABLE_ENTRY *pEntry;
UCHAR ChTxtIe = 16, ChTxtLen = CIPHER_TEXT_LEN;
#ifdef DOT11R_FT_SUPPORT
PFT_CFG pFtCfg;
FT_INFO FtInfo;
PFT_INFO pFtInfoBuf;
#endif /* DOT11R_FT_SUPPORT */
MULTISSID_STRUCT *pMbss;
struct wifi_dev *wdev;
CHAR rssi;
#ifdef BAND_STEERING
BOOLEAN bBndStrgCheck = TRUE;
#endif /* BAND_STEERING */
if (! APPeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr1,
Addr2, &Alg, &Seq, &Status, Chtxt
#ifdef DOT11R_FT_SUPPORT
,&FtInfo
#endif /* DOT11R_FT_SUPPORT */
))
return;
/* Find which MBSSID to be authenticate */
apidx = get_apidx_by_addr(pAd, Addr1);
if (apidx >= pAd->ApCfg.BssidNum)
{
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid not found\n"));
return;
}
pMbss = &pAd->ApCfg.MBSSID[apidx];
wdev = &pMbss->wdev;
if ((wdev->if_dev == NULL) || ((wdev->if_dev != NULL) &&
!(RTMP_OS_NETDEV_STATE_RUNNING(wdev->if_dev))))
{
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid IF didn't up yet.\n"));
return;
}
pEntry = MacTableLookup(pAd, Addr2);
if (pEntry && IS_ENTRY_CLIENT(pEntry))
{
#ifdef DOT11W_PMF_SUPPORT
if ((CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))
&& (pEntry->PortSecured == WPA_802_1X_PORT_SECURED))
goto SendAuth;
#endif /* DOT11W_PMF_SUPPORT */
if (!RTMPEqualMemory(Addr1, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, MAC_ADDR_LEN))
{
MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr);
pEntry = NULL;
DBGPRINT(RT_DEBUG_WARN, ("AUTH - Bssid does not match\n"));
}
else
{
if (pEntry->bIAmBadAtheros == TRUE)
{
AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, FALSE, FALSE);
DBGPRINT(RT_DEBUG_TRACE, ("Atheros Problem. Turn on RTS/CTS!!!\n"));
pEntry->bIAmBadAtheros = FALSE;
}
#ifdef DOT11_N_SUPPORT
BASessionTearDownALL(pAd, pEntry->wcid);
#endif /* DOT11_N_SUPPORT */
ASSERT(pEntry->Aid == Elem->Wcid);
}
}
#ifdef DOT11W_PMF_SUPPORT
SendAuth:
#endif /* DOT11W_PMF_SUPPORT */
pRcvHdr = (PHEADER_802_11)(Elem->Msg);
DBGPRINT(RT_DEBUG_TRACE,
("AUTH - MBSS(%d), Rcv AUTH seq#%d, Alg=%d, Status=%d from "
"[wcid=%d]%02x:%02x:%02x:%02x:%02x:%02x\n",
apidx, Seq, Alg, Status, Elem->Wcid, PRINT_MAC(Addr2)));
/* YF@20130102: Refuse the weak signal of AuthReq */
rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, (CHAR)Elem->Rssi0, RSSI_0),
ConvertToRssi(pAd, (CHAR)Elem->Rssi1, RSSI_1),
ConvertToRssi(pAd, (CHAR)Elem->Rssi2, RSSI_2));
DBGPRINT(RT_DEBUG_TRACE, ("%s: AUTH_FAIL_REQ Threshold = %d, AUTH_NO_RSP_REQ Threshold = %d, AUTH RSSI = %d\n",
wdev->if_dev->name, pMbss->AuthFailRssiThreshold, pMbss->AuthNoRspRssiThreshold, rssi));
if (((pMbss->AuthFailRssiThreshold != 0) && (rssi < pMbss->AuthFailRssiThreshold)) ||
((pMbss->AuthNoRspRssiThreshold != 0) && (rssi < pMbss->AuthNoRspRssiThreshold)))
{
DBGPRINT(RT_DEBUG_TRACE, ("Reject this AUTH_REQ due to Weak Signal.\n"));
if ((pMbss->AuthFailRssiThreshold != 0) && (rssi < pMbss->AuthFailRssiThreshold))
APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_UNSPECIFY_FAIL, apidx);
/* If this STA exists, delete it. */
if (pEntry)
MacTableDeleteEntry(pAd, pEntry->Aid, pEntry->Addr);
RTMPSendWirelessEvent(pAd, IW_MAC_FILTER_LIST_EVENT_FLAG, Addr2, apidx, 0);
return;
}
#ifdef WSC_V2_SUPPORT
/* Do not check ACL when WPS V2 is enabled and ACL policy is positive. */
if (
/* We don't be restricted by this check for SMART_MESH. */
#ifdef SMART_MESH
FALSE &&
#endif /* SMART_MESH */
(pMbss->WscControl.WscConfMode != WSC_DISABLE) &&
(pMbss->WscControl.WscV2Info.bEnableWpsV2) &&
(pMbss->WscControl.WscV2Info.bWpsEnable) &&
(pMbss->AccessControlList.Policy == 1))
;
else
#endif /* WSC_V2_SUPPORT */
/* fail in ACL checking => send an AUTH-Fail seq#2. */
if (! ApCheckAccessControlList(pAd, Addr2, apidx))
{
ASSERT(Seq == 1);
ASSERT(pEntry == NULL);
#ifdef SMART_MESH
/* If a MAC address is not within the list,
driver MUST not respond to any 802.11 frames including AuthResp, ProbeResp, nor ACK.
*/
if(FALSE)
#endif /* SMART_MESH */
APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_UNSPECIFY_FAIL, apidx);
/* If this STA exists, delete it. */
if (pEntry)
MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr);
RTMPSendWirelessEvent(pAd, IW_MAC_FILTER_LIST_EVENT_FLAG, Addr2, apidx, 0);
#ifdef SMART_MESH_MONITOR
struct nsmpif_drvevnt_buf drvevnt;
drvevnt.data.authreject.type = NSMPIF_DRVEVNT_STA_AUTH_REJECT;
drvevnt.data.authreject.channel = pAd->CommonCfg.Channel;
NdisCopyMemory(drvevnt.data.authreject.sta_mac, Addr2, MAC_ADDR_LEN);
drvevnt.data.authreject.is_ucast = 0;
drvevnt.data.authreject.cap = 0;
drvevnt.data.authreject.rate = pAd->LastMgmtRxRate;
drvevnt.data.authreject.rssi = rssi;
drvevnt.data.authreject.snr = ConvertToSnr(pAd, Elem->Signal);
#ifdef RTMP_MAC
if (pAd->chipCap.hif_type == HIF_RTMP)
{
if (IS_RT6352(pAd))
{
if ((42 - drvevnt.data.authreject.snr) >= 0)
drvevnt.data.authreject.snr = (42 - drvevnt.data.authreject.snr);
else
drvevnt.data.authreject.snr = 0;
}
}
#endif /* RTMP_MAC */
drvevnt.data.authreject.ntgr_vie_len = 0;
NdisZeroMemory(drvevnt.data.authreject.ntgr_vie,sizeof(drvevnt.data.authreject.ntgr_vie));
if (Seq == 1)
{
PFRAME_802_11 Fr = (PFRAME_802_11)Elem->Msg;
ULONG MsgLen = Elem->MsgLen;
PEID_STRUCT eid_ptr = NULL;
BOOLEAN bNTGRIeFound = FALSE;
eid_ptr = (PEID_STRUCT) &Fr->Octet[6];
while (((UCHAR *)eid_ptr + eid_ptr->Len + 1) < ((UCHAR *)Fr + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_VENDOR_SPECIFIC:
if((eid_ptr->Len >= NTGR_OUI_LEN) && NdisEqualMemory(eid_ptr->Octet, NETGEAR_OUI, NTGR_OUI_LEN))
{
bNTGRIeFound = TRUE;
drvevnt.data.authreject.ntgr_vie_len = (eid_ptr->Len - NTGR_OUI_LEN);
if(drvevnt.data.authreject.ntgr_vie_len > 0)
NdisCopyMemory(drvevnt.data.authreject.ntgr_vie, &eid_ptr->Octet[NTGR_OUI_LEN], drvevnt.data.authreject.ntgr_vie_len );
}
break;
default:
break;
}
if(bNTGRIeFound)
break;
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
}
RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM,NSMPIF_DRVEVNT_STA_AUTH_REJECT,
NULL, (PUCHAR)&drvevnt.data.authreject, sizeof(drvevnt.data.authreject));
#endif /* SMART_MESH_MONITOR */
DBGPRINT(RT_DEBUG_TRACE,
("Failed in ACL checking => send an AUTH seq#2 with "
"Status code = %d\n", MLME_UNSPECIFY_FAIL));
return;
}
#ifdef DOT11R_FT_SUPPORT
pFtCfg = &pMbss->FtCfg;
if ((pFtCfg->FtCapFlag.Dot11rFtEnable)
&& (Alg == AUTH_MODE_FT))
{
USHORT result;
if (!pEntry)
pEntry = MacTableInsertEntry(pAd, Addr2, wdev, apidx, OPMODE_AP, TRUE);
if (pEntry != NULL)
{
os_alloc_mem(pAd, (UCHAR **)&pFtInfoBuf, sizeof(FT_INFO));
if (pFtInfoBuf)
{
result = FT_AuthReqHandler(pAd, pEntry, &FtInfo, pFtInfoBuf);
if (result == MLME_SUCCESS)
{
NdisMoveMemory(&pEntry->MdIeInfo, &FtInfo.MdIeInfo, sizeof(FT_MDIE_INFO));
pEntry->AuthState = AS_AUTH_OPEN;
pEntry->Sst = SST_AUTH;
}
FT_EnqueueAuthReply(pAd, pRcvHdr, Alg, 2, result,
&pFtInfoBuf->MdIeInfo, &pFtInfoBuf->FtIeInfo, NULL,
pFtInfoBuf->RSN_IE, pFtInfoBuf->RSNIE_Len);
NdisZeroMemory(pEntry->LastTK, LEN_TK);
os_free_mem(NULL, pFtInfoBuf);
if (result == MLME_SUCCESS) {
/* Install pairwise key */
WPAInstallPairwiseKey(pAd, pEntry->apidx, pEntry, TRUE);
/* Update status */
pEntry->WpaState = AS_PTKINITDONE;
pEntry->GTKState = REKEY_ESTABLISHED;
}
}
}
return;
}
else
#endif /* DOT11R_FT_SUPPORT */
#ifdef BAND_STEERING
BND_STRG_CHECK_CONNECTION_REQ( pAd,
NULL,
Addr2,
Elem->MsgType,
Elem->Rssi0,
Elem->Rssi1,
Elem->Rssi2,
&bBndStrgCheck);
if (bBndStrgCheck == FALSE)
return;
#endif /* BAND_STEERING */
if ((Alg == AUTH_MODE_OPEN) &&
(pMbss->wdev.AuthMode != Ndis802_11AuthModeShared))
{
if (!pEntry)
pEntry = MacTableInsertEntry(pAd, Addr2, wdev, apidx, OPMODE_AP, TRUE);
if (pEntry)
{
#ifdef DOT11W_PMF_SUPPORT
if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))
|| (pEntry->PortSecured != WPA_802_1X_PORT_SECURED))
#endif /* DOT11W_PMF_SUPPORT */
{
pEntry->AuthState = AS_AUTH_OPEN;
pEntry->Sst = SST_AUTH; /* what if it already in SST_ASSOC ??????? */
}
APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_SUCCESS, apidx);
}
else
; /* MAC table full, what should we respond ????? */
}
else if ((Alg == AUTH_MODE_KEY) &&
((wdev->AuthMode == Ndis802_11AuthModeShared)
|| (wdev->AuthMode == Ndis802_11AuthModeAutoSwitch)))
{
if (!pEntry)
pEntry = MacTableInsertEntry(pAd, Addr2, wdev, apidx, OPMODE_AP, TRUE);
if (pEntry)
{
pEntry->AuthState = AS_AUTHENTICATING;
pEntry->Sst = SST_NOT_AUTH; /* what if it already in SST_ASSOC ??????? */
/* log this STA in AuthRspAux machine, only one STA is stored. If two STAs using */
/* SHARED_KEY authentication mingled together, then the late comer will win. */
COPY_MAC_ADDR(&pAd->ApMlmeAux.Addr, Addr2);
for(i=0; i<CIPHER_TEXT_LEN; i++)
pAd->ApMlmeAux.Challenge[i] = RandomByte(pAd);
RspReason = 0;
Seq++;
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if(NStatus != NDIS_STATUS_SUCCESS)
return; /* if no memory, can't do anything */
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH seq#2 (Challenge)\n"));
MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2,
wdev->if_addr,
wdev->bssid);
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &AuthHdr,
2, &Alg,
2, &Seq,
2, &RspReason,
1, &ChTxtIe,
1, &ChTxtLen,
CIPHER_TEXT_LEN, pAd->ApMlmeAux.Challenge,
END_OF_ARGS);
#ifdef SMART_MESH
SMART_MESH_INSERT_IE(pMbss->SmartMeshCfg,
pOutBuffer,
FrameLen,
SM_IE_AUTH_RSP);
#endif /* SMART_MESH */
MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
}
else
; /* MAC table full, what should we respond ???? */
}
else
{
/* wrong algorithm */
APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_ALG_NOT_SUPPORT, apidx);
/* If this STA exists, delete it. */
if (pEntry)
MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr);
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Alg=%d, Seq=%d, AuthMode=%d\n",
Alg, Seq, pAd->ApCfg.MBSSID[apidx].wdev.AuthMode));
}
#ifdef SMART_MESH_MONITOR
if (pAd->MntEnable &&
(Elem->Wcid >= WCID_OF_MONITOR_STA_BASE && Elem->Wcid <= MAX_WCID_OF_MONITOR_STA))
UpdateMonitorEntry(pAd,Elem->Wcid,pEntry->Addr,FALSE);
#endif /* SMART_MESH_MONITOR */
}
static VOID APPeerAuthConfirmAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
USHORT Seq, Alg, Status;
UCHAR Addr2[MAC_ADDR_LEN];
PHEADER_802_11 pRcvHdr;
CHAR Chtxt[CIPHER_TEXT_LEN];
MAC_TABLE_ENTRY *pEntry;
UCHAR Addr1[MAC_ADDR_LEN];
UINT32 apidx;
#ifdef DOT11R_FT_SUPPORT
PFT_CFG pFtCfg;
FT_INFO FtInfo;
PFT_INFO pFtInfoBuf;
#endif /* DOT11R_FT_SUPPORT */
if (! APPeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr1,
Addr2, &Alg, &Seq, &Status, Chtxt
#ifdef DOT11R_FT_SUPPORT
,&FtInfo
#endif /* DOT11R_FT_SUPPORT */
))
return;
apidx = get_apidx_by_addr(pAd, Addr1);
if (apidx >= pAd->ApCfg.BssidNum)
{
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid not found\n"));
return;
}
if ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev != NULL) &&
!(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].wdev.if_dev)))
{
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid IF didn't up yet.\n"));
return;
} /* End of if */
if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)
{
DBGPRINT(RT_DEBUG_ERROR, ("AUTH - Invalid wcid (%d).\n", Elem->Wcid));
return;
}
pEntry = &pAd->MacTab.Content[Elem->Wcid];
if (pEntry && IS_ENTRY_CLIENT(pEntry))
{
if (!RTMPEqualMemory(Addr1, pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid, MAC_ADDR_LEN))
{
MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr);
pEntry = NULL;
DBGPRINT(RT_DEBUG_WARN, ("AUTH - Bssid does not match\n"));
}
else
{
if (pEntry->bIAmBadAtheros == TRUE)
{
AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, FALSE, FALSE);
DBGPRINT(RT_DEBUG_TRACE, ("Atheros Problem. Turn on RTS/CTS!!!\n"));
pEntry->bIAmBadAtheros = FALSE;
}
ASSERT(pEntry->Aid == Elem->Wcid);
#ifdef DOT11_N_SUPPORT
BASessionTearDownALL(pAd, pEntry->wcid);
#endif /* DOT11_N_SUPPORT */
}
}
pRcvHdr = (PHEADER_802_11)(Elem->Msg);
DBGPRINT(RT_DEBUG_TRACE,
("AUTH - MBSS(%d), Rcv AUTH seq#%d, Alg=%d, Status=%d from "
"[wcid=%d]%02x:%02x:%02x:%02x:%02x:%02x\n",
apidx, Seq, Alg, Status, Elem->Wcid, PRINT_MAC(Addr2)));
if (pEntry && MAC_ADDR_EQUAL(Addr2, pAd->ApMlmeAux.Addr))
{
#ifdef DOT11R_FT_SUPPORT
pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg;
if ((pFtCfg->FtCapFlag.Dot11rFtEnable) && (Alg == AUTH_MODE_FT))
{
USHORT result;
os_alloc_mem(pAd, (UCHAR **)&pFtInfoBuf, sizeof(FT_INFO));
if (pFtInfoBuf)
{
NdisZeroMemory(pFtInfoBuf, sizeof(FT_INFO));
os_alloc_mem(pAd, (UCHAR **)&(pFtInfoBuf->RicInfo.pRicInfo), 512);
if (pFtInfoBuf->RicInfo.pRicInfo != NULL)
{
result = FT_AuthConfirmHandler(pAd, pEntry, &FtInfo, pFtInfoBuf);
FT_EnqueueAuthReply(pAd, pRcvHdr, Alg, 4, result,
&pFtInfoBuf->MdIeInfo, &pFtInfoBuf->FtIeInfo,
&pFtInfoBuf->RicInfo, pFtInfoBuf->RSN_IE, pFtInfoBuf->RSNIE_Len);
os_free_mem(NULL, pFtInfoBuf->RicInfo.pRicInfo);
}
os_free_mem(NULL, pFtInfoBuf);
}
else
{
return;
}
}
else
#endif /* DOT11R_FT_SUPPORT */
if ((pRcvHdr->FC.Wep == 1) &&
NdisEqualMemory(Chtxt, pAd->ApMlmeAux.Challenge, CIPHER_TEXT_LEN))
{
/* Successful */
APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_SUCCESS, apidx);
pEntry->AuthState = AS_AUTH_KEY;
pEntry->Sst = SST_AUTH;
}
else
{
/* send wireless event - Authentication rejected because of challenge failure */
RTMPSendWirelessEvent(pAd, IW_AUTH_REJECT_CHALLENGE_FAILURE, pEntry->Addr, 0, 0);
/* fail - wep bit is not set or challenge text is not equal */
APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_REJ_CHALLENGE_FAILURE, apidx);
MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr);
/*Chtxt[127]='\0'; */
/*pAd->ApMlmeAux.Challenge[127]='\0'; */
DBGPRINT(RT_DEBUG_TRACE, ("%s\n",
((pRcvHdr->FC.Wep == 1) ? "challenge text is not equal" : "wep bit is not set")));
/*DBGPRINT(RT_DEBUG_TRACE, ("Sent Challenge = %s\n",&pAd->ApMlmeAux.Challenge[100])); */
/*DBGPRINT(RT_DEBUG_TRACE, ("Rcv Challenge = %s\n",&Chtxt[100])); */
}
}
else
{
/* fail for unknown reason. most likely is AuthRspAux machine be overwritten by another */
/* STA also using SHARED_KEY authentication */
APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, Alg, Seq + 1, MLME_UNSPECIFY_FAIL, apidx);
/* If this STA exists, delete it. */
if (pEntry)
MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr);
}
}
/*
==========================================================================
Description:
Some STA/AP
Note:
This action should never trigger AUTH state transition, therefore we
separate it from AUTH state machine, and make it as a standalone service
==========================================================================
*/
VOID APCls2errAction(
IN RTMP_ADAPTER *pAd,
IN ULONG Wcid,
IN HEADER_802_11 *pHeader)
{
HEADER_802_11 Hdr;
UCHAR *pOutBuffer = NULL;
NDIS_STATUS NStatus;
ULONG FrameLen = 0;
USHORT Reason = REASON_CLS2ERR;
MAC_TABLE_ENTRY *pEntry = NULL;
UCHAR apidx;
if (Wcid < MAX_LEN_OF_MAC_TABLE)
pEntry = &(pAd->MacTab.Content[Wcid]);
if (pEntry && IS_ENTRY_CLIENT(pEntry))
{
/*ApLogEvent(pAd, pAddr, EVENT_DISASSOCIATED); */
MacTableDeleteEntry(pAd, pEntry->wcid, pHeader->Addr2);
}
else
{
apidx = get_apidx_by_addr(pAd, pHeader->Addr1);
if (apidx >= pAd->ApCfg.BssidNum)
{
DBGPRINT(RT_DEBUG_TRACE,("AUTH - Class 2 error but not my bssid %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pHeader->Addr1)));
return;
}
}
/* send out DEAUTH frame */
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if (NStatus != NDIS_STATUS_SUCCESS)
return;
DBGPRINT(RT_DEBUG_TRACE,
("AUTH - Class 2 error, Send DEAUTH frame to "
"%02x:%02x:%02x:%02x:%02x:%02x\n",
PRINT_MAC(pHeader->Addr2)));
MgtMacHeaderInit(pAd, &Hdr, SUBTYPE_DEAUTH, 0, pHeader->Addr2,
pHeader->Addr1,
pHeader->Addr1);
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &Hdr,
2, &Reason,
END_OF_ARGS);
MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
}
/*
==========================================================================
Description:
Send out a Authentication (response) frame
==========================================================================
*/
VOID APPeerAuthSimpleRspGenAndSend(
IN PRTMP_ADAPTER pAd,
IN PHEADER_802_11 pHdr,
IN USHORT Alg,
IN USHORT Seq,
IN USHORT StatusCode,
IN UINT32 apidx)
{
HEADER_802_11 AuthHdr;
ULONG FrameLen = 0;
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if (NStatus != NDIS_STATUS_SUCCESS)
return;
if (StatusCode == MLME_SUCCESS)
{
DBGPRINT(RT_DEBUG_TRACE, ("AUTH_RSP - Send AUTH response (SUCCESS)...\n"));
}
else
{
/* For MAC wireless client(Macintosh), need to send AUTH_RSP with Status Code (fail reason code) to reject it. */
DBGPRINT(RT_DEBUG_TRACE, ("AUTH_RSP - Peer AUTH fail (Status = %d)...\n", StatusCode));
}
MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, pHdr->Addr2,
pHdr->Addr1,
pHdr->Addr1);
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &AuthHdr,
2, &Alg,
2, &Seq,
2, &StatusCode,
END_OF_ARGS);
#ifdef SMART_MESH
SMART_MESH_INSERT_IE(pAd->ApCfg.MBSSID[apidx].SmartMeshCfg,
pOutBuffer,
FrameLen,
SM_IE_AUTH_RSP);
#endif /*SMART_MESH*/
MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,351 @@
/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Abstract:
Handle WMM-DLS state machine.
***************************************************************************/
#include "rt_config.h"
#ifdef QOS_DLS_SUPPORT
/*
========================================================================
Routine Description:
DLS state machine init, including state transition and timer init.
Arguments:
pAd points to our adapter
S pointer to the DLS state machine
Trans[]
Return Value:
None
Note:
The state machine looks like the following
DLS_IDLE
MT2_PEER_DLS_REQ PeerDlsReqAction
MT2_PEER_DLS_RSP PeerDlsRspAction
MT2_PEER_DLS_TEAR_DOWN PeerDlsTearDownAction
========================================================================
*/
VOID APDLSStateMachineInit(
IN PRTMP_ADAPTER pAd,
IN STATE_MACHINE *S,
OUT STATE_MACHINE_FUNC Trans[])
{
StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_DLS_STATE, MAX_DLS_MSG,
(STATE_MACHINE_FUNC)Drop, DLS_IDLE, DLS_MACHINE_BASE);
StateMachineSetAction(S, DLS_IDLE, MT2_PEER_DLS_REQ,
(STATE_MACHINE_FUNC)APPeerDlsReqAction);
StateMachineSetAction(S, DLS_IDLE, MT2_PEER_DLS_RSP,
(STATE_MACHINE_FUNC)APPeerDlsRspAction);
StateMachineSetAction(S, DLS_IDLE, MT2_PEER_DLS_TEAR_DOWN,
(STATE_MACHINE_FUNC)APPeerDlsTearDownAction);
}
/*
========================================================================
Routine Description:
Handle peer DLS Request action frame.
Arguments:
pAd points to our adapter
*pElem action frame
Return Value:
None
Note:
========================================================================
*/
VOID APPeerDlsReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *pElem)
{
PMAC_TABLE_ENTRY pDAEntry, pSAEntry;
UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
UINT16 CapabilityInfo;
UINT16 DLSTimeout;
PUCHAR pOutBuffer = NULL;
PFRAME_802_11 Fr;
UINT16 Status;
UINT32 FrameLen = 0;
HEADER_802_11 DlsRspHdr;
UCHAR Category = CATEGORY_DLS;
UCHAR Action = ACTION_DLS_RESPONSE;
UCHAR SupportedRatesLen = 0;
UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
HT_CAPABILITY_IE HtCapability;
UCHAR HtCapabilityLen;
/* frame sanity check */
if (!PeerDlsReqSanity(pAd, pElem->Msg, pElem->MsgLen, DA, SA,
&CapabilityInfo, &DLSTimeout,
&SupportedRatesLen, &SupportedRates[0],
&HtCapabilityLen, &HtCapability))
{
return;
}
/* check whether the source station is legal */
pSAEntry = MacTableLookup(pAd, SA);
if (!pSAEntry)
return;
pSAEntry->bDlsInit = FALSE;
/* check whether the destination station exists in our associated table */
pDAEntry = MacTableLookup(pAd, DA);
if (!pDAEntry)
Status = MLME_DEST_STA_NOT_IN_QBSS;
else if (pDAEntry && (pDAEntry->apidx != pSAEntry->apidx))
Status = MLME_DEST_STA_NOT_IN_QBSS;
else if (pDAEntry && !CLIENT_STATUS_TEST_FLAG(pDAEntry, fCLIENT_STATUS_WMM_CAPABLE))
Status = MLME_DEST_STA_IS_NOT_A_QSTA;
else if (pDAEntry->WepStatus != pSAEntry->WepStatus)
Status = MLME_QOS_UNSPECIFY; /* different security algorithm */
else if (!pAd->ApCfg.MBSSID[pSAEntry->apidx].bDLSCapable)
Status = MLME_DLS_NOT_ALLOW_IN_QBSS;
else
Status = MLME_SUCCESS;
if (pDAEntry)
pDAEntry->bDlsInit = FALSE;
/* forward DLS-Request to real destination */
Fr = (PFRAME_802_11)pElem->Msg;
/* pOutBuffer = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG); */
os_alloc_mem(pAd, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER);
if(pOutBuffer == NULL)
return;
#ifdef CONFIG_HOTSPOT
if (pAd->ApCfg.MBSSID[pSAEntry->apidx].HotSpotCtrl.L2Filter)
Status = MLME_DLS_NOT_ALLOW_IN_QBSS;
#endif
/*
If status is successful, forward DLS-Request frame to destination
otherwise send DLS-Response with reason code to originator.
*/
if (Status == MLME_SUCCESS)
{
NdisMoveMemory(Fr->Hdr.Addr1, DA, MAC_ADDR_LEN);
NdisMoveMemory(Fr->Hdr.Addr2, pAd->ApCfg.MBSSID[pSAEntry->apidx].wdev.bssid, MAC_ADDR_LEN);
NdisMoveMemory(Fr->Hdr.Addr3, SA, MAC_ADDR_LEN);
NdisMoveMemory(pOutBuffer, pElem->Msg, pElem->MsgLen);
FrameLen = pElem->MsgLen;
}
else
{
/* response error to source station */
MgtMacHeaderInit(pAd, &DlsRspHdr, SUBTYPE_ACTION, 0, SA,
pAd->ApCfg.MBSSID[pSAEntry->apidx].wdev.if_addr,
pAd->ApCfg.MBSSID[pSAEntry->apidx].wdev.bssid);
/*
Capability information and supported rate field are present
only when status code is zero.
*/
MakeOutgoingFrame(pOutBuffer, (ULONG *) &FrameLen,
sizeof(HEADER_802_11), &DlsRspHdr,
1, &Category,
1, &Action,
2, &Status,
6, SA,
6, DA,
END_OF_ARGS);
}
/* transmit the frame */
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
/* kfree(pOutBuffer); */
os_free_mem(NULL, pOutBuffer);
DBGPRINT(RT_DEBUG_TRACE,
("DLS - APPeerDlsReqAction() from %02x:%02x:%02x:%02x:%02x:%02x "
"with Status=%d\n",
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], Status));
}
/*
========================================================================
Routine Description:
Handle peer DLS Response action frame.
Arguments:
pAd points to our adapter
*pElem action frame
Return Value:
None
Note:
========================================================================
*/
VOID APPeerDlsRspAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *pElem)
{
PMAC_TABLE_ENTRY pDAEntry, pSAEntry;
UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
UINT16 CapabilityInfo;
UINT16 StatusCode;
PUCHAR pOutBuffer = NULL;
PFRAME_802_11 Fr;
UINT32 FrameLen = 0;
UCHAR SupportedRatesLen = 0;
UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES];
UCHAR HtCapabilityLen;
HT_CAPABILITY_IE HtCapability;
/* frame sanity check */
if (! PeerDlsRspSanity(pAd, pElem->Msg, pElem->MsgLen, DA, SA,
&CapabilityInfo, &StatusCode,
&SupportedRatesLen, &SupportedRates[0],
&HtCapabilityLen, &HtCapability))
{
return;
}
DBGPRINT(RT_DEBUG_TRACE,
("DLS - PeerDlsRspAction() from %02x:%02x:%02x:%02x:%02x:%02x "
"with StatusCode=%d\n",
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5], StatusCode));
/* check whether the source station is legal */
pSAEntry = MacTableLookup(pAd, SA);
if (!pSAEntry)
return;
pDAEntry = MacTableLookup(pAd, DA);
if (!pDAEntry)
{
DBGPRINT(RT_DEBUG_TRACE, ("Destination station does not exist!\n"));
return;
}
pSAEntry->bDlsInit = FALSE;
/* forward DLS-Request to real destination */
Fr = (PFRAME_802_11)pElem->Msg;
/* pOutBuffer = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG); */
os_alloc_mem(pAd, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER);
if (pOutBuffer == NULL)
return; /* fatal error, no available memory */
NdisMoveMemory(Fr->Hdr.Addr1, DA, MAC_ADDR_LEN);
NdisMoveMemory(Fr->Hdr.Addr2, pAd->ApCfg.MBSSID[pSAEntry->apidx].wdev.bssid, MAC_ADDR_LEN);
NdisMoveMemory(Fr->Hdr.Addr3, SA, MAC_ADDR_LEN);
NdisMoveMemory(pOutBuffer, pElem->Msg, pElem->MsgLen);
FrameLen = pElem->MsgLen;
/* transmit the response frame */
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
/* kfree(pOutBuffer); */
os_free_mem(NULL, pOutBuffer);
}
/*
========================================================================
Routine Description:
Handle peer DLS Tear down action frame.
Arguments:
pAd points to our adapter
*pElem action frame
Return Value:
None
Note:
========================================================================
*/
VOID APPeerDlsTearDownAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *pElem)
{
PMAC_TABLE_ENTRY pDAEntry, pSAEntry;
UCHAR DA[MAC_ADDR_LEN], SA[MAC_ADDR_LEN];
UINT16 ReasonCode;
PUCHAR pOutBuffer = NULL;
PFRAME_802_11 Fr;
UINT32 FrameLen = 0;
/* frame sanity check */
if (! PeerDlsTearDownSanity(pAd, pElem->Msg, pElem->MsgLen,
DA, SA, &ReasonCode))
{
return;
}
DBGPRINT(RT_DEBUG_TRACE,
("DLS - PeerDlsTearDownAction() from %02x:%02x:%02x:%02x:%02x:%02x\n",
SA[0], SA[1], SA[2], SA[3], SA[4], SA[5]));
pSAEntry = MacTableLookup(pAd, SA);
if (!pSAEntry)
return;
pDAEntry = MacTableLookup(pAd, DA);
if (!pDAEntry)
{
DBGPRINT(RT_DEBUG_TRACE, ("Destination station does not exist!\n"));
return;
}
pSAEntry->bDlsInit = FALSE;
/* forward Tear-down to real destination */
Fr = (PFRAME_802_11)pElem->Msg;
/* pOutBuffer = kmalloc(MAX_LEN_OF_MLME_BUFFER, MEM_ALLOC_FLAG); */
os_alloc_mem(pAd, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER);
if (pOutBuffer == NULL)
return; /* fatal error, no available memory */
NdisMoveMemory(Fr->Hdr.Addr1, DA, MAC_ADDR_LEN);
NdisMoveMemory(Fr->Hdr.Addr2, pAd->ApCfg.MBSSID[pSAEntry->apidx].wdev.bssid, MAC_ADDR_LEN);
NdisMoveMemory(Fr->Hdr.Addr3, SA, MAC_ADDR_LEN);
NdisMoveMemory(pOutBuffer, pElem->Msg, pElem->MsgLen);
FrameLen = pElem->MsgLen;
/* transmit the tear down frame */
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
/* kfree(pOutBuffer); */
os_free_mem(NULL, pOutBuffer);
}
#endif /* QOS_DLS_SUPPORT */
/* End of ap_dls.c */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,463 @@
/****************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
****************************************************************************
Module Name:
ap_ids.c
Abstract:
monitor intrusion detection condition
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#ifdef IDS_SUPPORT
#include "rt_config.h"
#define IDS_EXEC_INTV 1000 /* 1 sec */
VOID RTMPIdsStart(
IN PRTMP_ADAPTER pAd)
{
if (pAd->ApCfg.IDSTimerRunning == FALSE)
{
RTMPSetTimer(&pAd->ApCfg.IDSTimer, IDS_EXEC_INTV);
pAd->ApCfg.IDSTimerRunning = TRUE;
}
}
VOID RTMPIdsStop(
IN PRTMP_ADAPTER pAd)
{
BOOLEAN Cancelled;
if (pAd->ApCfg.IDSTimerRunning == TRUE)
{
RTMPCancelTimer(&pAd->ApCfg.IDSTimer, &Cancelled);
pAd->ApCfg.IDSTimerRunning = FALSE;
}
}
#ifdef SYSTEM_LOG_SUPPORT
VOID RTMPHandleIdsEvent(
IN PRTMP_ADAPTER pAd)
{
INT i, j;
UINT32 FloodFrameCount[IW_FLOOD_EVENT_TYPE_NUM];
UINT32 FloodFrameThreshold[IW_FLOOD_EVENT_TYPE_NUM];
FloodFrameCount[0] = pAd->ApCfg.RcvdAuthCount;
FloodFrameCount[1] = pAd->ApCfg.RcvdAssocReqCount;
FloodFrameCount[2] = pAd->ApCfg.RcvdReassocReqCount;
FloodFrameCount[3] = pAd->ApCfg.RcvdProbeReqCount;
FloodFrameCount[4] = pAd->ApCfg.RcvdDisassocCount;
FloodFrameCount[5] = pAd->ApCfg.RcvdDeauthCount;
FloodFrameCount[6] = pAd->ApCfg.RcvdEapReqCount;
FloodFrameThreshold[0] = pAd->ApCfg.AuthFloodThreshold;
FloodFrameThreshold[1] = pAd->ApCfg.AssocReqFloodThreshold;
FloodFrameThreshold[2] = pAd->ApCfg.ReassocReqFloodThreshold;
FloodFrameThreshold[3] = pAd->ApCfg.ProbeReqFloodThreshold;
FloodFrameThreshold[4] = pAd->ApCfg.DisassocFloodThreshold;
FloodFrameThreshold[5] = pAd->ApCfg.DeauthFloodThreshold;
FloodFrameThreshold[6] = pAd->ApCfg.EapReqFloodThreshold;
/* trigger flooding traffic event */
for (j = 0; j < IW_FLOOD_EVENT_TYPE_NUM; j++)
{
if ((FloodFrameThreshold[j] > 0) && (FloodFrameCount[j] > FloodFrameThreshold[j]))
{
RTMPSendWirelessEvent(pAd, IW_FLOOD_AUTH_EVENT_FLAG + j, NULL, MAX_MBSSID_NUM(pAd), 0);
/*DBGPRINT(RT_DEBUG_TRACE, ("flooding traffic event(%d) - %d\n", IW_FLOOD_AUTH_EVENT_FLAG + j, FloodFrameCount[j])); */
}
}
for (i = 0; i < pAd->ApCfg.BssidNum; i++)
{
UINT32 SpoofedFrameCount[IW_SPOOF_EVENT_TYPE_NUM];
CHAR RssiOfSpoofedFrame[IW_SPOOF_EVENT_TYPE_NUM];
INT k;
SpoofedFrameCount[0] = pAd->ApCfg.MBSSID[i].RcvdConflictSsidCount;
SpoofedFrameCount[1] = pAd->ApCfg.MBSSID[i].RcvdSpoofedAssocRespCount;
SpoofedFrameCount[2] = pAd->ApCfg.MBSSID[i].RcvdSpoofedReassocRespCount;
SpoofedFrameCount[3] = pAd->ApCfg.MBSSID[i].RcvdSpoofedProbeRespCount;
SpoofedFrameCount[4] = pAd->ApCfg.MBSSID[i].RcvdSpoofedBeaconCount;
SpoofedFrameCount[5] = pAd->ApCfg.MBSSID[i].RcvdSpoofedDisassocCount;
SpoofedFrameCount[6] = pAd->ApCfg.MBSSID[i].RcvdSpoofedAuthCount;
SpoofedFrameCount[7] = pAd->ApCfg.MBSSID[i].RcvdSpoofedDeauthCount;
SpoofedFrameCount[8] = pAd->ApCfg.MBSSID[i].RcvdSpoofedUnknownMgmtCount;
SpoofedFrameCount[9] = pAd->ApCfg.MBSSID[i].RcvdReplayAttackCount;
RssiOfSpoofedFrame[0] = pAd->ApCfg.MBSSID[i].RssiOfRcvdConflictSsid;
RssiOfSpoofedFrame[1] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedAssocResp;
RssiOfSpoofedFrame[2] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedReassocResp;
RssiOfSpoofedFrame[3] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedProbeResp;
RssiOfSpoofedFrame[4] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedBeacon;
RssiOfSpoofedFrame[5] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedDisassoc;
RssiOfSpoofedFrame[6] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedAuth;
RssiOfSpoofedFrame[7] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedDeauth;
RssiOfSpoofedFrame[8] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedUnknownMgmt;
RssiOfSpoofedFrame[9] = pAd->ApCfg.MBSSID[i].RssiOfRcvdReplayAttack;
/* trigger spoofed attack event */
for (k = 0; k < IW_SPOOF_EVENT_TYPE_NUM; k++)
{
if (SpoofedFrameCount[k] > 0)
{
RTMPSendWirelessEvent(pAd, IW_CONFLICT_SSID_EVENT_FLAG + k, NULL, i, RssiOfSpoofedFrame[k]);
/*DBGPRINT(RT_DEBUG_TRACE, ("spoofed attack event(%d) - %d\n", IW_CONFLICT_SSID_EVENT_FLAG + k, SpoofedFrameCount[k])); */
}
}
}
}
#endif /* SYSTEM_LOG_SUPPORT */
VOID RTMPClearAllIdsCounter(
IN PRTMP_ADAPTER pAd)
{
INT i;
pAd->ApCfg.RcvdAuthCount = 0;
pAd->ApCfg.RcvdAssocReqCount = 0;
pAd->ApCfg.RcvdReassocReqCount = 0;
pAd->ApCfg.RcvdProbeReqCount = 0;
pAd->ApCfg.RcvdDisassocCount = 0;
pAd->ApCfg.RcvdDeauthCount = 0;
pAd->ApCfg.RcvdEapReqCount = 0;
pAd->ApCfg.RcvdMaliciousDataCount = 0;
for (i = 0; i < pAd->ApCfg.BssidNum; i++)
{
pAd->ApCfg.MBSSID[i].RcvdConflictSsidCount = 0;
pAd->ApCfg.MBSSID[i].RcvdSpoofedAssocRespCount = 0;
pAd->ApCfg.MBSSID[i].RcvdSpoofedReassocRespCount = 0;
pAd->ApCfg.MBSSID[i].RcvdSpoofedProbeRespCount = 0;
pAd->ApCfg.MBSSID[i].RcvdSpoofedBeaconCount = 0;
pAd->ApCfg.MBSSID[i].RcvdSpoofedDisassocCount = 0;
pAd->ApCfg.MBSSID[i].RcvdSpoofedAuthCount = 0;
pAd->ApCfg.MBSSID[i].RcvdSpoofedDeauthCount = 0;
pAd->ApCfg.MBSSID[i].RcvdSpoofedUnknownMgmtCount = 0;
pAd->ApCfg.MBSSID[i].RcvdReplayAttackCount = 0;
pAd->ApCfg.MBSSID[i].RssiOfRcvdConflictSsid = 0;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedAssocResp = 0;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedReassocResp = 0;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedProbeResp = 0;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedBeacon = 0;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedDisassoc = 0;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedAuth = 0;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedDeauth = 0;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedUnknownMgmt = 0;
pAd->ApCfg.MBSSID[i].RssiOfRcvdReplayAttack = 0;
}
}
VOID RTMPIdsPeriodicExec(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
pAd->ApCfg.IDSTimerRunning = FALSE;
#ifdef SYSTEM_LOG_SUPPORT
/* when IDS occured, send out wireless event */
if (pAd->CommonCfg.bWirelessEvent)
RTMPHandleIdsEvent(pAd);
#endif /* SYSTEM_LOG_SUPPORT */
/* clear all IDS counter */
RTMPClearAllIdsCounter(pAd);
/* set timer */
if (pAd->ApCfg.IdsEnable)
{
RTMPSetTimer(&pAd->ApCfg.IDSTimer, IDS_EXEC_INTV);
pAd->ApCfg.IDSTimerRunning = TRUE;
}
}
/*
========================================================================
Routine Description:
This routine is used to check if a rogue AP sent an 802.11 management
frame to a client using our BSSID.
Arguments:
pAd - Pointer to our adapter
pHeader - Pointer to 802.11 header
Return Value:
TRUE - This is a spoofed frame
FALSE - This isn't a spoofed frame
========================================================================
*/
BOOLEAN RTMPSpoofedMgmtDetection(
IN RTMP_ADAPTER *pAd,
IN HEADER_802_11 *pHeader,
IN RX_BLK *rxblk)
{
INT i;
for (i = 0; i < pAd->ApCfg.BssidNum; i++)
{
/* Spoofed BSSID detection */
if (NdisEqualMemory(pHeader->Addr2, pAd->ApCfg.MBSSID[i].wdev.bssid, MAC_ADDR_LEN))
{
CHAR RcvdRssi;
RcvdRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, rxblk->rssi[0], RSSI_0), ConvertToRssi(pAd, rxblk->rssi[1], RSSI_1), ConvertToRssi(pAd, rxblk->rssi[2], RSSI_2));
switch (pHeader->FC.SubType)
{
case SUBTYPE_ASSOC_RSP:
pAd->ApCfg.MBSSID[i].RcvdSpoofedAssocRespCount ++;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedAssocResp = RcvdRssi;
break;
case SUBTYPE_REASSOC_RSP:
pAd->ApCfg.MBSSID[i].RcvdSpoofedReassocRespCount ++;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedReassocResp = RcvdRssi;
break;
case SUBTYPE_PROBE_RSP:
pAd->ApCfg.MBSSID[i].RcvdSpoofedProbeRespCount ++;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedProbeResp = RcvdRssi;
break;
case SUBTYPE_BEACON:
pAd->ApCfg.MBSSID[i].RcvdSpoofedBeaconCount ++;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedBeacon = RcvdRssi;
break;
case SUBTYPE_DISASSOC:
pAd->ApCfg.MBSSID[i].RcvdSpoofedDisassocCount ++;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedDisassoc = RcvdRssi;
break;
case SUBTYPE_AUTH:
pAd->ApCfg.MBSSID[i].RcvdSpoofedAuthCount ++;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedAuth = RcvdRssi;
break;
case SUBTYPE_DEAUTH:
pAd->ApCfg.MBSSID[i].RcvdSpoofedDeauthCount ++;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedDeauth = RcvdRssi;
break;
default:
pAd->ApCfg.MBSSID[i].RcvdSpoofedUnknownMgmtCount ++;
pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedUnknownMgmt = RcvdRssi;
break;
}
return TRUE;
}
}
return FALSE;
}
VOID RTMPConflictSsidDetection(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pSsid,
IN UCHAR SsidLen,
IN CHAR Rssi0,
IN CHAR Rssi1,
IN CHAR Rssi2)
{
INT i;
for (i = 0; i < pAd->ApCfg.BssidNum; i++)
{
/* Conflict SSID detection */
if (SSID_EQUAL(pSsid, SsidLen, pAd->ApCfg.MBSSID[i].Ssid, pAd->ApCfg.MBSSID[i].SsidLen))
{
CHAR RcvdRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, Rssi0, RSSI_0),
ConvertToRssi(pAd, Rssi1, RSSI_1),
ConvertToRssi(pAd, Rssi2, RSSI_2));
pAd->ApCfg.MBSSID[i].RcvdConflictSsidCount ++;
pAd->ApCfg.MBSSID[i].RssiOfRcvdConflictSsid = RcvdRssi;
return;
}
}
}
BOOLEAN RTMPReplayAttackDetection(
IN RTMP_ADAPTER *pAd,
IN UCHAR *pAddr2,
IN RX_BLK *rxblk)
{
INT i;
for (i = 0; i < pAd->ApCfg.BssidNum; i++)
{
/* Conflict SSID detection */
if (NdisEqualMemory(pAddr2, pAd->ApCfg.MBSSID[i].wdev.bssid, MAC_ADDR_LEN))
{
CHAR RcvdRssi;
RcvdRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, rxblk->rssi[0], RSSI_0),
ConvertToRssi(pAd, rxblk->rssi[1], RSSI_1),
ConvertToRssi(pAd, rxblk->rssi[2], RSSI_2));
pAd->ApCfg.MBSSID[i].RcvdReplayAttackCount ++;
pAd->ApCfg.MBSSID[i].RssiOfRcvdReplayAttack = RcvdRssi;
return TRUE;
}
}
return FALSE;
}
VOID RTMPUpdateStaMgmtCounter(
IN PRTMP_ADAPTER pAd,
IN USHORT type)
{
switch (type)
{
case SUBTYPE_ASSOC_REQ:
pAd->ApCfg.RcvdAssocReqCount ++;
/*DBGPRINT(RT_DEBUG_TRACE, ("RcvdAssocReqCount=%d\n", pAd->ApCfg.RcvdAssocReqCount)); */
break;
case SUBTYPE_REASSOC_REQ:
pAd->ApCfg.RcvdReassocReqCount ++;
/*DBGPRINT(RT_DEBUG_TRACE, ("RcvdReassocReqCount=%d\n", pAd->ApCfg.RcvdReassocReqCount)); */
break;
case SUBTYPE_PROBE_REQ:
pAd->ApCfg.RcvdProbeReqCount ++;
/*DBGPRINT(RT_DEBUG_TRACE, ("RcvdProbeReqCount=%d\n", pAd->ApCfg.RcvdProbeReqCount)); */
break;
case SUBTYPE_DISASSOC:
pAd->ApCfg.RcvdDisassocCount ++;
/*DBGPRINT(RT_DEBUG_TRACE, ("RcvdDisassocCount=%d\n", pAd->ApCfg.RcvdDisassocCount)); */
break;
case SUBTYPE_DEAUTH:
pAd->ApCfg.RcvdDeauthCount ++;
/*DBGPRINT(RT_DEBUG_TRACE, ("RcvdDeauthCount=%d\n", pAd->ApCfg.RcvdDeauthCount)); */
break;
case SUBTYPE_AUTH:
pAd->ApCfg.RcvdAuthCount ++;
/*DBGPRINT(RT_DEBUG_TRACE, ("RcvdAuthCount=%d\n", pAd->ApCfg.RcvdAuthCount)); */
break;
}
}
VOID rtmp_read_ids_from_file(
IN PRTMP_ADAPTER pAd,
PSTRING tmpbuf,
PSTRING buffer)
{
/*IdsEnable */
if(RTMPGetKeyParameter("IdsEnable", tmpbuf, 10, buffer, TRUE))
{
if (simple_strtol(tmpbuf, 0, 10) == 1)
pAd->ApCfg.IdsEnable = TRUE;
else
pAd->ApCfg.IdsEnable = FALSE;
DBGPRINT(RT_DEBUG_TRACE, ("IDS is %s\n", pAd->ApCfg.IdsEnable ? "enabled" : "disabled"));
}
/*AuthFloodThreshold */
if(RTMPGetKeyParameter("AuthFloodThreshold", tmpbuf, 10, buffer, TRUE))
{
pAd->ApCfg.AuthFloodThreshold = simple_strtol(tmpbuf, 0, 10);
DBGPRINT(RT_DEBUG_TRACE, ("AuthFloodThreshold = %d\n", pAd->ApCfg.AuthFloodThreshold));
}
/*AssocReqFloodThreshold */
if(RTMPGetKeyParameter("AssocReqFloodThreshold", tmpbuf, 10, buffer, TRUE))
{
pAd->ApCfg.AssocReqFloodThreshold = simple_strtol(tmpbuf, 0, 10);
DBGPRINT(RT_DEBUG_TRACE, ("AssocReqFloodThreshold = %d\n", pAd->ApCfg.AssocReqFloodThreshold));
}
/*ReassocReqFloodThreshold */
if(RTMPGetKeyParameter("ReassocReqFloodThreshold", tmpbuf, 10, buffer, TRUE))
{
pAd->ApCfg.ReassocReqFloodThreshold = simple_strtol(tmpbuf, 0, 10);
DBGPRINT(RT_DEBUG_TRACE, ("ReassocReqFloodThreshold = %d\n", pAd->ApCfg.ReassocReqFloodThreshold));
}
/*ProbeReqFloodThreshold */
if(RTMPGetKeyParameter("ProbeReqFloodThreshold", tmpbuf, 10, buffer, TRUE))
{
pAd->ApCfg.ProbeReqFloodThreshold = simple_strtol(tmpbuf, 0, 10);
DBGPRINT(RT_DEBUG_TRACE, ("ProbeReqFloodThreshold = %d\n", pAd->ApCfg.ProbeReqFloodThreshold));
}
/*DisassocFloodThreshold */
if(RTMPGetKeyParameter("DisassocFloodThreshold", tmpbuf, 10, buffer, TRUE))
{
pAd->ApCfg.DisassocFloodThreshold = simple_strtol(tmpbuf, 0, 10);
DBGPRINT(RT_DEBUG_TRACE, ("DisassocFloodThreshold = %d\n", pAd->ApCfg.DisassocFloodThreshold));
}
/*DeauthFloodThreshold */
if(RTMPGetKeyParameter("DeauthFloodThreshold", tmpbuf, 10, buffer, TRUE))
{
pAd->ApCfg.DeauthFloodThreshold = simple_strtol(tmpbuf, 0, 10);
DBGPRINT(RT_DEBUG_TRACE, ("DeauthFloodThreshold = %d\n", pAd->ApCfg.DeauthFloodThreshold));
}
/*EapReqFloodThreshold */
if(RTMPGetKeyParameter("EapReqFloodThreshold", tmpbuf, 10, buffer, TRUE))
{
pAd->ApCfg.EapReqFloodThreshold = simple_strtol(tmpbuf, 0, 10);
DBGPRINT(RT_DEBUG_TRACE, ("EapReqFloodThreshold = %d\n", pAd->ApCfg.EapReqFloodThreshold));
}
/* DataFloodThreshold */
if(RTMPGetKeyParameter("DataFloodThreshold", tmpbuf, 10, buffer, TRUE))
{
pAd->ApCfg.DataFloodThreshold = simple_strtol(tmpbuf, 0, 10);
DBGPRINT(RT_DEBUG_TRACE, ("DataFloodThreshold = %d\n", pAd->ApCfg.DataFloodThreshold));
}
}
#endif /* IDS_SUPPORT */

View File

@ -0,0 +1,309 @@
/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Abstract:
Support multi-BSS function.
Note:
1. Call RT28xx_MBSS_Init() in init function and
call RT28xx_MBSS_Remove() in close function
2. MAC of different BSS is initialized in APStartUp()
3. BSS Index (0 ~ 15) of different rx packet is got in
APHandleRxDoneInterrupt() by using FromWhichBSSID = pEntry->apidx;
Or FromWhichBSSID = BSS0;
4. BSS Index (0 ~ 15) of different tx packet is assigned in
rt28xx_send_packets() by using RTMP_SET_PACKET_NET_DEVICE_MBSSID()
5. BSS Index (0 ~ 15) of different BSS is got in APHardTransmit() by using
RTMP_GET_PACKET_IF()
6. BSS Index (0 ~ 15) of IOCTL command is put in pAd->OS_Cookie->ioctl_if
7. Beacon of different BSS is enabled in APMakeAllBssBeacon() by writing 1
to the register MAC_BSSID_DW1
8. The number of MBSS can be 1, 2, 4, or 8
***************************************************************************/
#ifdef MBSS_SUPPORT
#include "rt_config.h"
/* --------------------------------- Public -------------------------------- */
/*
========================================================================
Routine Description:
Initialize Multi-BSS function.
Arguments:
pAd points to our adapter
pDevMain points to the main BSS network interface
Return Value:
None
Note:
1. Only create and initialize virtual network interfaces.
2. No main network interface here.
3. If you down ra0 and modify the BssNum of RT2860AP.dat/RT2870AP.dat,
it will not work! You must rmmod rt2860ap.ko and lsmod rt2860ap.ko again.
========================================================================
*/
VOID MBSS_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps)
{
PNET_DEV pDevNew;
INT32 IdBss, MaxNumBss;
INT status;
RTMP_OS_NETDEV_OP_HOOK netDevHook;
MaxNumBss = pAd->ApCfg.BssidNum;
if (MaxNumBss > MAX_MBSSID_NUM(pAd))
MaxNumBss = MAX_MBSSID_NUM(pAd);
/* sanity check to avoid redundant virtual interfaces are created */
if (!pAd->FlgMbssInit)
{
/* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */
for(IdBss=FIRST_MBSSID; IdBss<MAX_MBSSID_NUM(pAd); IdBss++)
pAd->ApCfg.MBSSID[IdBss].wdev.if_dev = NULL;
}
/* create virtual network interface */
for(IdBss=FIRST_MBSSID; IdBss<MaxNumBss; IdBss++)
{
struct wifi_dev *wdev;
UINT32 MC_RowID = 0, IoctlIF = 0;
char *dev_name;
#ifdef MULTIPLE_CARD_SUPPORT
MC_RowID = pAd->MC_RowID;
#endif /* MULTIPLE_CARD_SUPPORT */
#ifdef HOSTAPD_SUPPORT
IoctlIF = pAd->IoctlIF;
#endif /* HOSTAPD_SUPPORT */
if (pAd->ApCfg.MBSSID[IdBss].wdev.if_dev)
continue;
dev_name = get_dev_name_prefix(pAd, INT_MBSSID);
pDevNew = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_MBSSID, IdBss, sizeof(struct mt_dev_priv), dev_name);
#ifdef HOSTAPD_SUPPORT
pAd->IoctlIF = IoctlIF;
#endif /* HOSTAPD_SUPPORT */
if (pDevNew == NULL)
{
pAd->ApCfg.BssidNum = IdBss; /* re-assign new MBSS number */
break;
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("Register MBSSID IF (%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(pDevNew)));
}
wdev = &pAd->ApCfg.MBSSID[IdBss].wdev;
wdev->wdev_type = WDEV_TYPE_AP;
wdev->func_dev = &pAd->ApCfg.MBSSID[IdBss];
wdev->sys_handle = (void *)pAd;
wdev->if_dev = pDevNew;
if (rtmp_wdev_idx_reg(pAd, wdev) < 0) {
DBGPRINT(RT_DEBUG_ERROR, ("Assign wdev idx for %s failed, free net device!\n",
RTMP_OS_NETDEV_GET_DEVNAME(pDevNew)));
RtmpOSNetDevFree(pDevNew);
break;
}
wdev->tx_pkt_allowed = ApAllowToSendPacket;
RTMP_OS_NETDEV_SET_PRIV(pDevNew, pAd);
RTMP_OS_NETDEV_SET_WDEV(pDevNew, wdev);
/* init operation functions and flags */
NdisCopyMemory(&netDevHook, pNetDevOps, sizeof(netDevHook));
netDevHook.priv_flags = INT_MBSSID;
netDevHook.needProtcted = TRUE;
netDevHook.wdev = wdev;
/* Init MAC address of virtual network interface */
NdisMoveMemory(&netDevHook.devAddr[0], &wdev->bssid[0], MAC_ADDR_LEN);
/* register this device to OS */
status = RtmpOSNetDevAttach(pAd->OpMode, pDevNew, &netDevHook);
if (status != NDIS_STATUS_SUCCESS)
DBGPRINT(RT_DEBUG_ERROR, ("Error in RtmpOSNetDevAttach() !!\n"));
}
pAd->FlgMbssInit = TRUE;
}
/*
========================================================================
Routine Description:
Remove Multi-BSS network interface.
Arguments:
pAd points to our adapter
Return Value:
None
Note:
FIRST_MBSSID = 1
Main BSS is not removed here.
========================================================================
*/
VOID MBSS_Remove(RTMP_ADAPTER *pAd)
{
struct wifi_dev *wdev;
UINT IdBss;
for(IdBss=FIRST_MBSSID; IdBss<MAX_MBSSID_NUM(pAd); IdBss++)
{
wdev = &pAd->ApCfg.MBSSID[IdBss].wdev;
if (wdev->if_dev)
{
RtmpOSNetDevProtect(1);
RtmpOSNetDevDetach(wdev->if_dev);
RtmpOSNetDevProtect(0);
rtmp_wdev_idx_unreg(pAd, wdev);
RtmpOSNetDevFree(wdev->if_dev);
wdev->if_dev = NULL;
}
}
}
/*
========================================================================
Routine Description:
Get multiple bss idx.
Arguments:
pAd points to our adapter
pDev which WLAN network interface
Return Value:
0: close successfully
otherwise: close fail
Note:
========================================================================
*/
INT32 RT28xx_MBSS_IdxGet(RTMP_ADAPTER *pAd, PNET_DEV pDev)
{
INT32 BssId = -1;
INT32 IdBss;
for(IdBss=0; IdBss<pAd->ApCfg.BssidNum; IdBss++)
{
if (pAd->ApCfg.MBSSID[IdBss].wdev.if_dev == pDev)
{
BssId = IdBss;
break;
}
}
return BssId;
}
/*
========================================================================
Routine Description:
Open a virtual network interface.
Arguments:
pDev which WLAN network interface
Return Value:
0: open successfully
otherwise: open fail
Note:
========================================================================
*/
INT MBSS_Open(PNET_DEV pDev)
{
PRTMP_ADAPTER pAd;
INT BssId;
pAd = RTMP_OS_NETDEV_GET_PRIV(pDev);
BssId = RT28xx_MBSS_IdxGet(pAd, pDev);
if (BssId < 0)
return -1;
#ifdef AIRPLAY_SUPPORT
if (AIRPLAY_ON(pAd))
pAd->ApCfg.MBSSID[BssId].bBcnSntReq = TRUE;
else
pAd->ApCfg.MBSSID[BssId].bBcnSntReq = FALSE;
#else
pAd->ApCfg.MBSSID[BssId].bBcnSntReq = TRUE;
#endif /* AIRPLAY_SUPPORT */
return 0;
}
/*
========================================================================
Routine Description:
Close a virtual network interface.
Arguments:
pDev which WLAN network interface
Return Value:
0: close successfully
otherwise: close fail
Note:
========================================================================
*/
INT MBSS_Close(PNET_DEV pDev)
{
PRTMP_ADAPTER pAd;
INT BssId;
pAd = RTMP_OS_NETDEV_GET_PRIV(pDev);
BssId = RT28xx_MBSS_IdxGet(pAd, pDev);
if (BssId < 0)
return -1;
RTMP_OS_NETDEV_STOP_QUEUE(pDev);
/* kick out all stas behind the Bss */
MbssKickOutStas(pAd, BssId, REASON_DISASSOC_INACTIVE);
pAd->ApCfg.MBSSID[BssId].bBcnSntReq = FALSE;
APMakeAllBssBeacon(pAd);
APUpdateAllBeaconFrame(pAd);
return 0;
}
#endif /* MBSS_SUPPORT */

View File

@ -0,0 +1,192 @@
/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Abstract:
Support multi-BSS function.
Note:
1. Call RT28xx_MBSS_Init() in init function and
call RT28xx_MBSS_Remove() in close function
2. MAC of different BSS is initialized in APStartUp()
3. BSS Index (0 ~ 15) of different rx packet is got in
APHandleRxDoneInterrupt() by using FromWhichBSSID = pEntry->apidx;
Or FromWhichBSSID = BSS0;
4. BSS Index (0 ~ 15) of different tx packet is assigned in
rt28xx_send_packets() by using RTMP_SET_PACKET_NET_DEVICE_MBSSID()
5. BSS Index (0 ~ 15) of different BSS is got in APHardTransmit() by using
RTMP_GET_PACKET_IF()
6. BSS Index (0 ~ 15) of IOCTL command is put in pAd->OS_Cookie->ioctl_if
7. Beacon of different BSS is enabled in APMakeAllBssBeacon() by writing 1
to the register MAC_BSSID_DW1
8. The number of MBSS can be 1, 2, 4, or 8
***************************************************************************/
#define RTMP_MODULE_OS
#ifdef MBSS_SUPPORT
/*#include "rt_config.h" */
#include "rtmp_comm.h"
#include "rt_os_util.h"
#include "rt_os_net.h"
/* --------------------------------- Public -------------------------------- */
struct rtnl_link_stats64 *
RT28xx_get_ether_stats64(PNET_DEV net_dev, struct rtnl_link_stats64 *stats);
/*
========================================================================
Routine Description:
Initialize Multi-BSS function.
Arguments:
pAd points to our adapter
pDevMain points to the main BSS network interface
Return Value:
None
Note:
1. Only create and initialize virtual network interfaces.
2. No main network interface here.
3. If you down ra0 and modify the BssNum of RT2860AP.dat/RT2870AP.dat,
it will not work! You must rmmod rt2860ap.ko and lsmod rt2860ap.ko again.
========================================================================
*/
VOID RT28xx_MBSS_Init(VOID *pAd, PNET_DEV pDevMain)
{
RTMP_OS_NETDEV_OP_HOOK netDevHook;
NdisZeroMemory(&netDevHook, sizeof(netDevHook));
netDevHook.open = MBSS_VirtualIF_Open; /* device opem hook point */
netDevHook.stop = MBSS_VirtualIF_Close; /* device close hook point */
netDevHook.xmit = rt28xx_send_packets; /* hard transmit hook point */
netDevHook.ioctl = rt28xx_ioctl; /* ioctl hook point */
netDevHook.get_stats = RT28xx_get_ether_stats64;
RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MBSS_INIT,
0, &netDevHook, 0);
}
/*
========================================================================
Routine Description:
Remove Multi-BSS network interface.
Arguments:
pAd points to our adapter
Return Value:
None
Note:
FIRST_MBSSID = 1
Main BSS is not removed here.
========================================================================
*/
VOID RT28xx_MBSS_Remove(VOID *pAd)
{
RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MBSS_REMOVE, 0, NULL, 0);
}
/* --------------------------------- Private -------------------------------- */
/*
========================================================================
Routine Description:
Open a virtual network interface.
Arguments:
pDev which WLAN network interface
Return Value:
0: open successfully
otherwise: open fail
Note:
========================================================================
*/
INT MBSS_VirtualIF_Open(PNET_DEV pDev)
{
VOID *pAd;
DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> MBSSVirtualIF_open\n", RTMP_OS_NETDEV_GET_DEVNAME(pDev)));
pAd = RTMP_OS_NETDEV_GET_PRIV(pDev);
RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MBSS_OPEN, 0, pDev, 0);
if (VIRTUAL_IF_UP(pAd) != 0)
return -1;
/* increase MODULE use count */
RT_MOD_INC_USE_COUNT();
RTMP_OS_NETDEV_START_QUEUE(pDev);
return 0;
}
/*
========================================================================
Routine Description:
Close a virtual network interface.
Arguments:
pDev which WLAN network interface
Return Value:
0: close successfully
otherwise: close fail
Note:
========================================================================
*/
INT MBSS_VirtualIF_Close(PNET_DEV pDev)
{
VOID *pAd;
DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> MBSSVirtualIF_close\n", RTMP_OS_NETDEV_GET_DEVNAME(pDev)));
pAd = RTMP_OS_NETDEV_GET_PRIV(pDev);
RTMP_OS_NETDEV_STOP_QUEUE(pDev);
RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MBSS_CLOSE, 0, pDev, 0);
VIRTUAL_IF_DOWN(pAd);
RT_MOD_DEC_USE_COUNT();
return 0;
}
#endif /* MBSS_SUPPORT */

View File

@ -0,0 +1,773 @@
/****************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
****************************************************************************
Module Name:
mlme.c
Abstract:
Major MLME state machiones here
Revision History:
Who When What
-------- ---------- ----------------------------------------------
John Chang 08-04-2003 created for 11g soft-AP
*/
#include "rt_config.h"
#include <stdarg.h>
extern UCHAR ZeroSsid[32];
#ifdef BTCOEX_CONCURRENT
extern int CoexCenctralChannel;
extern int CoexChannel;
extern int CoexChannelBw;
#endif
#ifdef DOT11_N_SUPPORT
int DetectOverlappingPeriodicRound;
#ifdef DOT11N_DRAFT3
VOID Bss2040CoexistTimeOut(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
int apidx;
PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
DBGPRINT(RT_DEBUG_TRACE, ("Bss2040CoexistTimeOut(): Recovery to original setting!\n"));
/* Recovery to original setting when next DTIM Interval. */
pAd->CommonCfg.Bss2040CoexistFlag &= (~BSS_2040_COEXIST_TIMER_FIRED);
NdisZeroMemory(&pAd->CommonCfg.LastBSSCoexist2040, sizeof(BSS_2040_COEXIST_IE));
pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_SYNC;
if (pAd->CommonCfg.bBssCoexEnable == FALSE)
{
/* TODO: Find a better way to handle this when the timer is fired and we disable the bBssCoexEable support!! */
DBGPRINT(RT_DEBUG_TRACE, ("Bss2040CoexistTimeOut(): bBssCoexEnable is FALSE, return directly!\n"));
return;
}
for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
SendBSS2040CoexistMgmtAction(pAd, MCAST_WCID, apidx, 0);
}
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
VOID APDetectOverlappingExec(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
#ifdef DOT11_N_SUPPORT
PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext;
if (DetectOverlappingPeriodicRound == 0)
{
/* switch back 20/40 */
if ((pAd->CommonCfg.Channel <=14) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40))
{
pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1;
pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA;
}
}
else
{
if ((DetectOverlappingPeriodicRound == 25) || (DetectOverlappingPeriodicRound == 1))
{
if ((pAd->CommonCfg.Channel <=14) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth==BW_40))
{
SendBeaconRequest(pAd, 1);
SendBeaconRequest(pAd, 2);
SendBeaconRequest(pAd, 3);
}
}
DetectOverlappingPeriodicRound--;
}
#endif /* DOT11_N_SUPPORT */
}
/*
==========================================================================
Description:
This routine is executed every second -
1. Decide the overall channel quality
2. Check if need to upgrade the TX rate to any client
3. perform MAC table maintenance, including ageout no-traffic clients,
and release packet buffer in PSQ is fail to TX in time.
==========================================================================
*/
VOID APMlmePeriodicExec(
PRTMP_ADAPTER pAd)
{
/*
Reqeust by David 2005/05/12
It make sense to disable Adjust Tx Power on AP mode, since we can't
take care all of the client's situation
ToDo: need to verify compatibility issue with WiFi product.
*/
#ifdef CUSTOMER_DCC_FEATURE
if(pAd->AllowedStaList.StaCount > 0)
RemoveOldStaList(pAd);
if(pAd->ApEnableBeaconTable == TRUE)
RemoveOldBssEntry(pAd);
APResetStreamingStatus(pAd);
#endif
#ifdef CARRIER_DETECTION_SUPPORT
if (isCarrierDetectExist(pAd) == TRUE)
{
PCARRIER_DETECTION_STRUCT pCarrierDetect = &pAd->CommonCfg.CarrierDetect;
if (pCarrierDetect->OneSecIntCount < pCarrierDetect->CarrierGoneThreshold)
{
pCarrierDetect->CD_State = CD_NORMAL;
pCarrierDetect->recheck = pCarrierDetect->recheck1;
if (pCarrierDetect->Debug != RT_DEBUG_TRACE)
{
DBGPRINT(RT_DEBUG_TRACE, ("Carrier gone\n"));
/* start all TX actions. */
APMakeAllBssBeacon(pAd);
APUpdateAllBeaconFrame(pAd);
AsicEnableBssSync(pAd);
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("Carrier gone\n"));
}
}
pCarrierDetect->OneSecIntCount = 0;
}
#endif /* CARRIER_DETECTION_SUPPORT */
RTMP_CHIP_HIGH_POWER_TUNING(pAd, &pAd->ApCfg.RssiSample);
/* Disable Adjust Tx Power for WPA WiFi-test. */
/* Because high TX power results in the abnormal disconnection of Intel BG-STA. */
/*#ifndef WIFI_TEST */
/* if (pAd->CommonCfg.bWiFiTest == FALSE) */
/* for SmartBit 64-byte stream test */
/* removed based on the decision of Ralink congress at 2011/7/06 */
/* if (pAd->MacTab.Size > 0) */
#ifdef RT6352
if (IS_RT6352(pAd))
RT6352_AsicAdjustTxPower(pAd);
else
#endif /* RT6352 */
AsicAdjustTxPower(pAd);
/*#endif // WIFI_TEST */
#ifdef THERMAL_PROTECT_SUPPORT
thermal_protection(pAd);
#endif /* THERMAL_PROTECT_SUPPORT */
RTMP_CHIP_ASIC_TEMPERATURE_COMPENSATION(pAd);
/* walk through MAC table, see if switching TX rate is required */
/* MAC table maintenance */
if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0)
{
/* one second timer */
MacTableMaintenance(pAd);
#ifdef CONFIG_FPGA_MODE
if (pAd->fpga_ctl.fpga_tr_stop)
{
UINT32 mac_val;
/* enable/disable tx/rx*/
RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &mac_val);
switch (pAd->fpga_ctl.fpga_tr_stop)
{
case 3: //stop tx + rx
mac_val &= (~0xc);
break;
case 2: // stop rx
mac_val &= (~0x8);
break;
case 1: // stop tx
mac_val &= (~0x4);
break;
case 4:
default:
mac_val |= 0x0c;
break;
}
RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, mac_val);
}
#endif /* CONFIG_FPGA_MODE */
RTMPMaintainPMKIDCache(pAd);
#ifdef WDS_SUPPORT
WdsTableMaintenance(pAd);
#endif /* WDS_SUPPORT */
#ifdef CLIENT_WDS
CliWds_ProxyTabMaintain(pAd);
#endif /* CLIENT_WDS */
#ifdef MWDS
MWDSProxyTabMaintain(pAd);
#endif /* MWDS */
}
#ifdef AP_SCAN_SUPPORT
AutoChannelSelCheck(pAd);
#endif /* AP_SCAN_SUPPORT */
APUpdateCapabilityAndErpIe(pAd);
#ifdef APCLI_SUPPORT
if (pAd->Mlme.OneSecPeriodicRound % 2 == 0)
ApCliIfMonitor(pAd);
if (pAd->Mlme.OneSecPeriodicRound % 2 == 1)
#ifdef APCLI_AUTO_CONNECT_SUPPORT
if (pAd->ApCfg.ApCliAutoConnectChannelSwitching == FALSE)
#endif /* APCLI_AUTO_CONNECT_SUPPORT */
ApCliIfUp(pAd);
{
INT loop;
ULONG Now32;
#ifdef APCLI_CERT_SUPPORT
BOOLEAN IsUseBA = TRUE;
#endif /* APCLI_CERT_SUPPORT */
#ifdef MAC_REPEATER_SUPPORT
if (pAd->ApCfg.bMACRepeaterEn == TRUE)
{
#ifdef APCLI_AUTO_CONNECT_SUPPORT
RTMPRepeaterReconnectionCheck(pAd);
#endif /* APCLI_AUTO_CONNECT_SUPPORT */
}
#endif /* MAC_REPEATER_SUPPORT */
NdisGetSystemUpTime(&Now32);
for (loop = 0; loop < MAX_APCLI_NUM; loop++)
{
PAPCLI_STRUCT pApCliEntry = &pAd->ApCfg.ApCliTab[loop];
if (pAd->ApCfg.ApCliTab[loop].bBlockAssoc ==TRUE && pAd->ApCfg.ApCliTab[loop].bBlockAssoc &&
RTMP_TIME_AFTER(Now32, pAd->ApCfg.ApCliTab[loop].LastMicErrorTime + (60*OS_HZ)))
pAd->ApCfg.ApCliTab[loop].bBlockAssoc = FALSE;
if ((pApCliEntry->Valid == TRUE)
&& (pApCliEntry->MacTabWCID < MAX_LEN_OF_MAC_TABLE))
{
/* update channel quality for Roaming and UI LinkQuality display */
MlmeCalculateChannelQuality(pAd,
&pAd->MacTab.Content[pApCliEntry->MacTabWCID], Now32);
/* WPA MIC error should block association attempt for 60 seconds*/
#ifdef APCLI_CERT_SUPPORT
if (pAd->bApCliCertTest == TRUE)
{
PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID];
struct wifi_dev *wdev = NULL;
wdev = &pApCliEntry->wdev;
if (pEntry->RXBAbitmap == 0 && pEntry->TXBAbitmap == 0)
IsUseBA = FALSE;
if( wdev->DesiredHtPhyInfo.bHtEnable &&
IsUseBA == FALSE )
{
EDCA_AC_CFG_STRUC Ac2Cfg, Ac1Cfg;
RTMP_IO_READ32(pAd, EDCA_AC2_CFG, &Ac2Cfg.word);
RTMP_IO_READ32(pAd, EDCA_AC1_CFG, &Ac1Cfg.word);
if ((pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] == 0) &&
(pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] >= 1000) &&
(pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] == 0))
{
/*5.2.27 T7 */
if (Ac1Cfg.field.Aifsn!=0x1)
{
Ac1Cfg.field.Aifsn = 0x1;
RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
DBGPRINT(RT_DEBUG_TRACE, ("Change EDCA_AC1_CFG to %x \n", Ac1Cfg.word));
}
}
else if ((pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] == 0) &&
(pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] == 0) &&
(pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] == 0) &&
(pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] < 10))
{
/* restore default parameter of BK*/
if (Ac1Cfg.field.Aifsn!=0x7)
{
Ac1Cfg.field.Aifsn = 0x7;
RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word);
DBGPRINT(RT_DEBUG_TRACE, ("Restore EDCA_AC1_CFG to %x \n", Ac1Cfg.word));
}
}
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
}
}
#endif /* APCLI_CERT_SUPPORT */
}
}
}
#endif /* APCLI_SUPPORT */
#ifdef DOT11_N_SUPPORT
if (pAd->CommonCfg.bHTProtect)
{
/*APUpdateCapabilityAndErpIe(pAd); */
APUpdateOperationMode(pAd);
if (pAd->CommonCfg.IOTestParm.bRTSLongProtOn == FALSE)
{
AsicUpdateProtect(pAd, (USHORT)pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, pAd->MacTab.fAnyStationNonGF);
}
}
#endif /* DOT11_N_SUPPORT */
#ifdef A_BAND_SUPPORT
if ( (pAd->CommonCfg.Channel > 14)
&& (pAd->CommonCfg.bIEEE80211H == 1)
)
{
#ifdef DFS_SUPPORT
ApRadarDetectPeriodic(pAd);
#else
pAd->Dot11_H.InServiceMonitorCount++;
if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE)
{
if (pAd->Dot11_H.RDCount++ > pAd->Dot11_H.ChMovingTime)
{
AsicEnableBssSync(pAd);
pAd->Dot11_H.RDMode = RD_NORMAL_MODE;
}
}
#endif /* !DFS_SUPPORT */
}
#endif /* A_BAND_SUPPORT */
#ifdef DOT11R_FT_SUPPORT
FT_R1KHInfoMaintenance(pAd);
#endif /* DOT11R_FT_SUPPORT */
#ifdef APCLI_SUPPORT
#ifdef DOT11_N_SUPPORT
#ifdef DOT11N_DRAFT3
#ifdef APCLI_CERT_SUPPORT
/* Perform 20/40 BSS COEX scan every Dot11BssWidthTriggerScanInt */
if (APCLI_IF_UP_CHECK(pAd, 0) && (pAd->bApCliCertTest == TRUE))
{
if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SCAN_2040)) &&
(pAd->CommonCfg.Dot11BssWidthTriggerScanInt != 0) &&
((pAd->Mlme.OneSecPeriodicRound % pAd->CommonCfg.Dot11BssWidthTriggerScanInt) == (pAd->CommonCfg.Dot11BssWidthTriggerScanInt-1)))
{
DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - LastOneSecTotalTxCount/LastOneSecRxOkDataCnt = %d/%d \n",
pAd->RalinkCounters.LastOneSecTotalTxCount,
pAd->RalinkCounters.LastOneSecRxOkDataCnt));
/* Check last scan time at least 30 seconds from now. */
/* Check traffic is less than about 1.5~2Mbps.*/
/* it might cause data lost if we enqueue scanning.*/
/* This criteria needs to be considered*/
if ((pAd->RalinkCounters.LastOneSecTotalTxCount < 70) && (pAd->RalinkCounters.LastOneSecRxOkDataCnt < 70)
/*&& ((pAd->StaCfg.LastScanTime + 10 * OS_HZ) < pAd->Mlme.Now32) */)
{
MLME_SCAN_REQ_STRUCT ScanReq;
/* Fill out stuff for scan request and kick to scan*/
ScanParmFill(pAd, &ScanReq, ZeroSsid, 0, BSS_ANY, SCAN_2040_BSS_COEXIST);
/* Before scan, reset trigger event table. */
TriEventInit(pAd);
MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, 0);
/* Set InfoReq = 1, So after scan , alwats sebd 20/40 Coexistence frame to AP*/
pAd->CommonCfg.BSSCoexist2040.field.InfoReq = 1;
RTMP_MLME_HANDLER(pAd);
}
DBGPRINT(RT_DEBUG_TRACE, (" LastOneSecTotalTxCount/LastOneSecRxOkDataCnt = %d/%d \n",
pAd->RalinkCounters.LastOneSecTotalTxCount,
pAd->RalinkCounters.LastOneSecRxOkDataCnt));
}
}
#endif /* APCLI_CERT_SUPPORT */
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
#endif /* APCLI_SUPPORT */
}
/*! \brief To substitute the message type if the message is coming from external
* \param *Fr The frame received
* \param *Machine The state machine
* \param *MsgType the message type for the state machine
* \return TRUE if the substitution is successful, FALSE otherwise
* \pre
* \post
*/
BOOLEAN APMsgTypeSubst(
IN PRTMP_ADAPTER pAd,
IN PFRAME_802_11 pFrame,
OUT INT *Machine,
OUT INT *MsgType)
{
USHORT Seq;
UCHAR EAPType;
BOOLEAN Return = FALSE;
#ifdef WSC_AP_SUPPORT
UCHAR EAPCode;
PMAC_TABLE_ENTRY pEntry;
#endif /* WSC_AP_SUPPORT */
/*
TODO:
only PROBE_REQ can be broadcast, all others must be unicast-to-me && is_mybssid;
otherwise, ignore this frame
*/
/* wpa EAPOL PACKET */
if (pFrame->Hdr.FC.Type == FC_TYPE_DATA)
{
#ifdef WSC_AP_SUPPORT
WSC_CTRL *wsc_ctrl;
/*WSC EAPOL PACKET */
pEntry = MacTableLookup(pAd, pFrame->Hdr.Addr2);
if (pEntry &&
((pEntry->bWscCapable) ||
(pAd->ApCfg.MBSSID[pEntry->apidx].wdev.AuthMode < Ndis802_11AuthModeWPA)))
{
/*
WSC AP only can service one WSC STA in one WPS session.
Forward this EAP packet to WSC SM if this EAP packets is from
WSC STA that WSC AP services or WSC AP doesn't service any
WSC STA now.
*/
wsc_ctrl = &pAd->ApCfg.MBSSID[pEntry->apidx].WscControl;
if ((MAC_ADDR_EQUAL(wsc_ctrl->EntryAddr, pEntry->Addr) ||
MAC_ADDR_EQUAL(wsc_ctrl->EntryAddr, ZERO_MAC_ADDR)) &&
IS_ENTRY_CLIENT(pEntry) &&
(wsc_ctrl->WscConfMode != WSC_DISABLE))
{
*Machine = WSC_STATE_MACHINE;
EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
EAPCode = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 4);
Return = WscMsgTypeSubst(EAPType, EAPCode, MsgType);
}
}
#endif /* WSC_AP_SUPPORT */
if (!Return)
{
*Machine = WPA_STATE_MACHINE;
EAPType = *((UCHAR*)pFrame + LENGTH_802_11 + LENGTH_802_1_H + 1);
Return = WpaMsgTypeSubst(EAPType, (INT *) MsgType);
}
return Return;
}
if (pFrame->Hdr.FC.Type != FC_TYPE_MGMT)
return FALSE;
switch (pFrame->Hdr.FC.SubType)
{
case SUBTYPE_ASSOC_REQ:
*Machine = AP_ASSOC_STATE_MACHINE;
*MsgType = APMT2_PEER_ASSOC_REQ;
break;
/*
case SUBTYPE_ASSOC_RSP:
*Machine = AP_ASSOC_STATE_MACHINE;
*MsgType = APMT2_PEER_ASSOC_RSP;
break;
*/
case SUBTYPE_REASSOC_REQ:
*Machine = AP_ASSOC_STATE_MACHINE;
*MsgType = APMT2_PEER_REASSOC_REQ;
break;
/*
case SUBTYPE_REASSOC_RSP:
*Machine = AP_ASSOC_STATE_MACHINE;
*MsgType = APMT2_PEER_REASSOC_RSP;
break;
*/
case SUBTYPE_PROBE_REQ:
*Machine = AP_SYNC_STATE_MACHINE;
*MsgType = APMT2_PEER_PROBE_REQ;
break;
/* For Active Scan */
case SUBTYPE_PROBE_RSP:
*Machine = AP_SYNC_STATE_MACHINE;
*MsgType = APMT2_PEER_PROBE_RSP;
break;
case SUBTYPE_BEACON:
*Machine = AP_SYNC_STATE_MACHINE;
*MsgType = APMT2_PEER_BEACON;
break;
/*
case SUBTYPE_ATIM:
*Machine = AP_SYNC_STATE_MACHINE;
*MsgType = APMT2_PEER_ATIM;
break;
*/
case SUBTYPE_DISASSOC:
*Machine = AP_ASSOC_STATE_MACHINE;
*MsgType = APMT2_PEER_DISASSOC_REQ;
break;
case SUBTYPE_AUTH:
/* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */
NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT));
*Machine = AP_AUTH_STATE_MACHINE;
if (Seq == 1)
*MsgType = APMT2_PEER_AUTH_REQ;
else if (Seq == 3)
*MsgType = APMT2_PEER_AUTH_CONFIRM;
else
{
DBGPRINT(RT_DEBUG_TRACE,("wrong AUTH seq=%d Octet=%02x %02x %02x %02x %02x %02x %02x %02x\n", Seq,
pFrame->Octet[0], pFrame->Octet[1], pFrame->Octet[2], pFrame->Octet[3],
pFrame->Octet[4], pFrame->Octet[5], pFrame->Octet[6], pFrame->Octet[7]));
return FALSE;
}
break;
case SUBTYPE_DEAUTH:
*Machine = AP_AUTH_STATE_MACHINE; /*AP_AUTH_RSP_STATE_MACHINE;*/
*MsgType = APMT2_PEER_DEAUTH;
break;
case SUBTYPE_ACTION:
case SUBTYPE_ACTION_NO_ACK:
*Machine = ACTION_STATE_MACHINE;
/* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */
if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG)
{
*MsgType = MT2_ACT_INVALID;
}
else
{
*MsgType = (pFrame->Octet[0]&0x7F);
}
break;
default:
return FALSE;
break;
}
return TRUE;
}
/*
========================================================================
Routine Description:
Periodic evaluate antenna link status
Arguments:
pAd - Adapter pointer
Return Value:
None
========================================================================
*/
VOID APAsicEvaluateRxAnt(
IN PRTMP_ADAPTER pAd)
{
ULONG TxTotalCnt;
#ifdef RALINK_ATE
if (ATE_ON(pAd))
return;
#endif /* RALINK_ATE */
#ifdef CARRIER_DETECTION_SUPPORT
if(pAd->CommonCfg.CarrierDetect.CD_State == CD_SILENCE)
return;
#endif /* CARRIER_DETECTION_SUPPORT */
#ifdef RT8592
// TODO: shiang-6590, for 8592, this EvaaluateRxAnt still need??
if (IS_RT8592(pAd))
return;
#endif /* RT8592 */
#ifdef RT65xx
if (IS_RT65XX(pAd))
return;
#endif /* RT76x0 */
#ifdef TXBF_SUPPORT
/* TODO: we didn't do RxAnt evaluate for 3x3 chips */
if (IS_RT3883(pAd) || IS_RT2883(pAd))
return;
#endif /* TXBF_SUPPORT */
#ifdef DOT11_N_SUPPORT
#ifdef GREENAP_SUPPORT
if (pAd->ApCfg.bGreenAPActive == TRUE)
bbp_set_rxpath(pAd, 1);
else
#endif /* GREENAP_SUPPORT */
#endif /* DOT11_N_SUPPORT */
bbp_set_rxpath(pAd, pAd->Antenna.field.RxPath);
TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount +
pAd->RalinkCounters.OneSecTxRetryOkCount +
pAd->RalinkCounters.OneSecTxFailCount;
if (TxTotalCnt > 50)
{
RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20);
pAd->Mlme.bLowThroughput = FALSE;
}
else
{
RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300);
pAd->Mlme.bLowThroughput = TRUE;
}
}
/*
========================================================================
Routine Description:
After evaluation, check antenna link status
Arguments:
pAd - Adapter pointer
Return Value:
None
========================================================================
*/
VOID APAsicRxAntEvalTimeout(RTMP_ADAPTER *pAd)
{
CHAR rssi0, rssi1, rssi2;
#ifdef RALINK_ATE
if (ATE_ON(pAd))
return;
#endif /* RALINK_ATE */
/* if the traffic is low, use average rssi as the criteria */
if (pAd->Mlme.bLowThroughput == TRUE)
{
rssi0 = pAd->ApCfg.RssiSample.LastRssi0;
rssi1 = pAd->ApCfg.RssiSample.LastRssi1;
rssi2 = pAd->ApCfg.RssiSample.LastRssi2;
}
else
{
rssi0 = pAd->ApCfg.RssiSample.AvgRssi0;
rssi1 = pAd->ApCfg.RssiSample.AvgRssi1;
rssi2 = pAd->ApCfg.RssiSample.AvgRssi2;
}
#ifdef DOT11N_SS3_SUPPORT
if(pAd->Antenna.field.RxPath == 3)
{
CHAR larger = -127;
larger = max(rssi0, rssi1);
if (pAd->CommonCfg.RxStream >= 3)
pAd->Mlme.RealRxPath = 3;
else
{
if (larger > (rssi2 + 20))
pAd->Mlme.RealRxPath = 2;
else
pAd->Mlme.RealRxPath = 3;
}
}
#endif /* DOT11N_SS3_SUPPORT */
/* Disable the below to fix 1T/2R issue. It's suggested by Rory at 2007/7/11. */
#ifdef DOT11_N_SUPPORT
#ifdef GREENAP_SUPPORT
if (pAd->ApCfg.bGreenAPActive == TRUE)
bbp_set_rxpath(pAd, 1);
else
#endif /* GREENAP_SUPPORT */
#endif /* DOT11_N_SUPPORT */
bbp_set_rxpath(pAd, pAd->Mlme.RealRxPath);
}
/*
========================================================================
Routine Description:
After evaluation, check antenna link status
Arguments:
pAd - Adapter pointer
Return Value:
None
========================================================================
*/
VOID APAsicAntennaAvg(
IN PRTMP_ADAPTER pAd,
IN UCHAR AntSelect,
IN SHORT* RssiAvg)
{
SHORT realavgrssi;
LONG realavgrssi1;
ULONG recvPktNum = pAd->RxAnt.RcvPktNum[AntSelect];
realavgrssi1 = pAd->RxAnt.Pair1AvgRssiGroup1[AntSelect];
if(realavgrssi1 == 0)
{
*RssiAvg = 0;
return;
}
realavgrssi = (SHORT) (realavgrssi1 / recvPktNum);
pAd->RxAnt.Pair1AvgRssiGroup1[0] = 0;
pAd->RxAnt.Pair1AvgRssiGroup1[1] = 0;
pAd->RxAnt.Pair1AvgRssiGroup2[0] = 0;
pAd->RxAnt.Pair1AvgRssiGroup2[1] = 0;
pAd->RxAnt.RcvPktNum[0] = 0;
pAd->RxAnt.RcvPktNum[1] = 0;
*RssiAvg = realavgrssi - 256;
}

View File

@ -0,0 +1,965 @@
/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Abstract:
Provide information on the current STA population and traffic levels
in the QBSS.
This attribute is available only at a QAP. This attribute, when TRUE,
indicates that the QAP implementation is capable of generating and
transmitting the QBSS load element in the Beacon and Probe Response frames.
***************************************************************************/
#include "rt_config.h"
#ifdef AP_QLOAD_SUPPORT
typedef struct GNU_PACKED _ELM_QBSS_LOAD{
UINT8 ElementId;
UINT8 Length;
/* the total number of STAs currently associated with this QBSS */
UINT16 StationCount;
/* defined as the percentage of time, nomalized to 255, the QAP sensed the
medium busy, as indicated by either the physical or virtual carrier
sense mechanism.
This percentage is computed using the formula:
((channel busy time / (dot11ChannelUtilizationBeaconIntervals *
dot11BeaconPeriod * 1024)) * 255) */
UINT8 ChanUtil;
/* specifies the remaining amount of medium time available via explicit
admission control, in units of 32 microsecond periods per 1 second.
The field is helpful for roaming non-AP QSTAs to select a QAP that is
likely to accept future admission control requests, but it does not
represent a guarantee that the HC will admit these requests. */
UINT16 AvalAdmCap;
} ELM_QBSS_LOAD;
#define ELM_QBSS_LOAD_ID 11
#define ELM_QBSS_LOAD_LEN 5
/*
We will send a alarm when channel busy time (primary or secondary) >=
Time Threshold and Num Threshold.
QBSS_LOAD_ALRAM_BUSY_TIME_THRESHOLD = 0 means alarm function is disabled.
If you want to enable it, use command
"iwpriv ra0 set qloadalarmtimethres=90"
*/
#define QBSS_LOAD_ALRAM_BUSY_TIME_THRESHOLD 0 /* unit: % */
#define QBSS_LOAD_ALRAM_BUSY_NUM_THRESHOLD 10 /* unit: 1 */
/* a alarm will not re-issued until QBSS_LOAD_ALARM_DURATION * TBTT */
#define QBSS_LOAD_ALARM_DURATION 100 /* unit: TBTT */
static VOID QBSS_LoadAlarmSuspend(
IN RTMP_ADAPTER *pAd);
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
/* handle a alarm */
static VOID QBSS_LoadAlarm(
IN RTMP_ADAPTER *pAd);
static VOID QBSS_LoadAlarmBusyTimeThresholdReset(
IN RTMP_ADAPTER *pAd,
IN UINT32 TimePeriod);
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
/* --------------------------------- Private -------------------------------- */
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
/*
========================================================================
Routine Description:
Handle a alarm.
Arguments:
pAd - WLAN control block pointer
Return Value:
None
Note:
You can use different methods to handle QBSS Load alarm here.
Current methods are:
1. Change 20/40 to 20-only.
2. Change channel to the clear channel.
========================================================================
*/
static VOID QBSS_LoadAlarm(
IN RTMP_ADAPTER *pAd)
{
/* suspend alarm until channel switch */
QBSS_LoadAlarmSuspend(pAd);
pAd->phy_ctrl.QloadAlarmNumber ++;
/* check if we have already been 20M bandwidth */
#ifdef DOT11_N_SUPPORT
#ifdef DOT11N_DRAFT3
if ((pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset != 0) &&
(pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth != 0))
{
MAC_TABLE *pMacTable;
UINT32 StaId;
DBGPRINT(RT_DEBUG_TRACE, ("qbss> Alarm! Change to 20 bw...\n"));
/* disassociate stations without D3 2040Coexistence function */
pMacTable = &pAd->MacTab;
for(StaId=1; StaId<MAX_LEN_OF_MAC_TABLE; StaId++)
{
MAC_TABLE_ENTRY *pEntry = &pMacTable->Content[StaId];
BOOLEAN bDisconnectSta = FALSE;
if (!IS_ENTRY_CLIENT(pEntry))
continue;
if (pEntry->Sst != SST_ASSOC)
continue;
if (pEntry->BSS2040CoexistenceMgmtSupport)
bDisconnectSta = TRUE;
if (bDisconnectSta)
{
/* send wireless event - for ageout */
RTMPSendWirelessEvent(pAd, IW_AGEOUT_EVENT_FLAG, pEntry->Addr, 0, 0);
{
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
ULONG FrameLen = 0;
HEADER_802_11 DeAuthHdr;
USHORT Reason;
/* send out a DISASSOC request frame */
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer);
if (NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_TRACE, (" MlmeAllocateMemory fail ..\n"));
/*NdisReleaseSpinLock(&pAd->MacTabLock); */
continue;
}
Reason = REASON_DEAUTH_STA_LEAVING;
MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0,
pEntry->Addr,
pAd->ApCfg.MBSSID[pEntry->apidx].wdev.if_addr,
pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid);
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &DeAuthHdr,
2, &Reason,
END_OF_ARGS);
MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
}
DBGPRINT(RT_DEBUG_TRACE, ("qbss> Alarm! Deauth the station "
"%02x:%02x:%02x:%02x:%02x:%02x\n",
PRINT_MAC(pEntry->Addr)));
MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr);
continue;
}
}
/* for 11n */
pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0;
pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0;
/* always 20M */
pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20;
/* mark alarm flag */
pAd->phy_ctrl.FlgQloadAlarm = TRUE;
QBSS_LoadAlarmResume(pAd);
}
else
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
{
/* we are in 20MHz bandwidth so try to switch channel */
DBGPRINT(RT_DEBUG_TRACE, ("qbss> Alarm! Switch channel...\n"));
/* send command to switch channel */
RTEnqueueInternalCmd(pAd, CMDTHREAD_CHAN_RESCAN, NULL, 0);
}
}
/*
========================================================================
Routine Description:
Re-calculate busy time threshold.
Arguments:
pAd - WLAN control block pointer
TimePeriod - TBTT
Return Value:
None
Note:
EX: TBTT=100ms, 90%, pAd->QloadBusyTimeThreshold = 90ms
========================================================================
*/
static VOID QBSS_LoadAlarmBusyTimeThresholdReset(
IN RTMP_ADAPTER *pAd,
IN UINT32 TimePeriod)
{
pAd->phy_ctrl.QloadBusyTimeThreshold = TimePeriod;
pAd->phy_ctrl.QloadBusyTimeThreshold *= pAd->phy_ctrl.QloadAlarmBusyTimeThreshold;
pAd->phy_ctrl.QloadBusyTimeThreshold /= 100;
pAd->phy_ctrl.QloadBusyTimeThreshold <<= 10; /* translate mini-sec to micro-sec */
}
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
/* --------------------------------- Public -------------------------------- */
/*
========================================================================
Routine Description:
Initialize ASIC Channel Busy Calculation mechanism.
Arguments:
pAd - WLAN control block pointer
Return Value:
None
Note:
Init Condition: WMM must be enabled.
========================================================================
*/
VOID QBSS_LoadInit(
IN RTMP_ADAPTER *pAd)
{
UINT32 IdBss;
/* check whether any BSS enables WMM feature */
for(IdBss=0; IdBss<pAd->ApCfg.BssidNum; IdBss++)
{
if ((pAd->ApCfg.MBSSID[IdBss].wdev.bWmmCapable)
#ifdef DOT11K_RRM_SUPPORT
|| (IS_RRM_ENABLE(pAd, IdBss))
#endif /* DOT11K_RRM_SUPPORT */
)
{
pAd->phy_ctrl.FlgQloadEnable = TRUE;
break;
}
}
if (pAd->phy_ctrl.FlgQloadEnable == TRUE)
{
/* Count EIFS, NAV, RX busy, TX busy as channel busy and
enable Channel statistic timer (bit 0) */
/* Note: if bit 0 == 0, the function will be disabled */
RTMP_IO_WRITE32(pAd, CH_TIME_CFG, 0x0000001F);
#ifdef MT76x2
if(IS_MT76x2(pAd))
{
RTMP_IO_WRITE32(pAd, CH_TIME_CFG, 0x0000011F);
/*ENABLE bit[9:8] = 1 ,to set CH_BUSY reg ReadClear*/
}
#endif
/* default value is 50, please reference to IEEE802.11e 2005 Annex D */
pAd->phy_ctrl.QloadChanUtilBeaconInt = 50;
}
else
{
/* no any WMM is enabled */
RTMP_IO_WRITE32(pAd, CH_TIME_CFG, 0x00000000);
}
pAd->phy_ctrl.QloadChanUtilTotal = 0;
pAd->phy_ctrl.QloadUpTimeLast = 0;
#ifdef QLOAD_FUNC_BUSY_TIME_STATS
/* clear busy time statistics */
NdisZeroMemory(pAd->phy_ctrl.QloadBusyCountPri, sizeof(pAd->phy_ctrl.QloadBusyCountPri));
NdisZeroMemory(pAd->phy_ctrl.QloadBusyCountSec, sizeof(pAd->phy_ctrl.QloadBusyCountSec));
#endif /* QLOAD_FUNC_BUSY_TIME_STATS */
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
/* init threshold before QBSS_LoadAlarmReset */
pAd->phy_ctrl.QloadAlarmBusyTimeThreshold = QBSS_LOAD_ALRAM_BUSY_TIME_THRESHOLD;
pAd->phy_ctrl.QloadAlarmBusyNumThreshold = QBSS_LOAD_ALRAM_BUSY_NUM_THRESHOLD;
QBSS_LoadAlarmReset(pAd);
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
}
/*
========================================================================
Routine Description:
Reset alarm function.
Arguments:
pAd - WLAN control block pointer
Return Value:
None
Note:
========================================================================
*/
VOID QBSS_LoadAlarmReset(
IN RTMP_ADAPTER *pAd)
{
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
pAd->phy_ctrl.FlgQloadAlarm = FALSE;
pAd->phy_ctrl.QloadAlarmDuration = 0;
pAd->phy_ctrl.QloadAlarmNumber = 0;
pAd->phy_ctrl.FlgQloadAlarmIsSuspended = FALSE;
QBSS_LoadAlarmBusyTimeThresholdReset(pAd, pAd->CommonCfg.BeaconPeriod);
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
}
/*
========================================================================
Routine Description:
Resume alarm function.
Arguments:
pAd - WLAN control block pointer
Return Value:
None
Note:
========================================================================
*/
VOID QBSS_LoadAlarmResume(
IN RTMP_ADAPTER *pAd)
{
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
pAd->phy_ctrl.FlgQloadAlarmIsSuspended = FALSE;
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
}
/*
========================================================================
Routine Description:
Suspend alarm function.
Arguments:
pAd - WLAN control block pointer
Return Value:
None
Note:
========================================================================
*/
static VOID QBSS_LoadAlarmSuspend(
IN RTMP_ADAPTER *pAd)
{
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
pAd->phy_ctrl.FlgQloadAlarmIsSuspended = TRUE;
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
}
/*
========================================================================
Routine Description:
Get average busy time in current channel.
Arguments:
pAd - WLAN control block pointer
Return Value:
average busy time
Note:
========================================================================
*/
UINT32 QBSS_LoadBusyTimeGet(
IN RTMP_ADAPTER *pAd)
{
if (pAd->phy_ctrl.QloadChanUtilBeaconCnt == 0)
return pAd->phy_ctrl.QloadChanUtilTotal;
return (pAd->phy_ctrl.QloadChanUtilTotal / pAd->phy_ctrl.QloadChanUtilBeaconCnt);
}
/*
========================================================================
Routine Description:
Check if a alarm is occurred and clear the alarm.
Arguments:
pAd - WLAN control block pointer
Return Value:
TRUE - alarm occurs
FALSE - no alarm
Note:
We will clear the alarm in the function.
========================================================================
*/
BOOLEAN QBSS_LoadIsAlarmIssued(
IN RTMP_ADAPTER *pAd)
{
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
BOOLEAN FlgQloadAlarm = pAd->phy_ctrl.FlgQloadAlarm;
pAd->phy_ctrl.FlgQloadAlarm = FALSE;
return FlgQloadAlarm;
#else
return FALSE;
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
}
/*
========================================================================
Routine Description:
Check if the busy time is accepted.
Arguments:
pAd - WLAN control block pointer
Return Value:
TURE - ok
FALSE - fail
Note:
========================================================================
*/
BOOLEAN QBSS_LoadIsBusyTimeAccepted(
IN RTMP_ADAPTER *pAd,
IN UINT32 BusyTime)
{
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
if (pAd->phy_ctrl.QloadAlarmBusyTimeThreshold == 0)
return TRUE; /* always ok */
if (BusyTime >= pAd->phy_ctrl.QloadBusyTimeThreshold)
return FALSE;
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
return TRUE;
}
#ifdef CONFIG_HOTSPOT_R2
UINT32 QBSS_LoadElementAppend_HSTEST(
IN RTMP_ADAPTER *pAd,
OUT UINT8 *pBeaconBuf,
IN UCHAR apidx)
{
ELM_QBSS_LOAD load, *pLoad = &load;
ULONG ElmLen;
/* check whether channel busy time calculation is enabled */
if (pAd->phy_ctrl.FlgQloadEnable == 0)
return 0;
/* End of if */
/* init */
pLoad->ElementId = ELM_QBSS_LOAD_ID;
pLoad->Length = ELM_QBSS_LOAD_LEN;
pLoad->StationCount = le2cpu16(pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QLoadStaCnt);
pLoad->ChanUtil = pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QLoadCU;
/* because no ACM is supported, the available bandwidth is 1 sec */
pLoad->AvalAdmCap = le2cpu16(0xffff); /* 0x7a12 * 32us = 1 second */
/* copy the element to the frame */
MakeOutgoingFrame(pBeaconBuf, &ElmLen,
sizeof(ELM_QBSS_LOAD), pLoad,
END_OF_ARGS);
return ElmLen;
} /* End of QBSS_LoadElementAppend */
#endif
/*
========================================================================
Routine Description:
Append the QBSS Load element to the beacon frame.
Arguments:
pAd - WLAN control block pointer
*pBeaconBuf - the beacon or probe response frame
Return Value:
the element total Length
Note:
Append Condition: You must check whether WMM is enabled before the
function is using.
========================================================================
*/
UINT32 QBSS_LoadElementAppend(
IN RTMP_ADAPTER *pAd,
OUT UINT8 *pBeaconBuf)
{
ELM_QBSS_LOAD load, *pLoad = &load;
ULONG ElmLen;
/* check whether channel busy time calculation is enabled */
if (pAd->phy_ctrl.FlgQloadEnable == 0)
return 0;
/* init */
pLoad->ElementId = ELM_QBSS_LOAD_ID;
pLoad->Length = ELM_QBSS_LOAD_LEN;
pLoad->StationCount = le2cpu16(MacTableAssocStaNumGet(pAd));
pLoad->ChanUtil = pAd->phy_ctrl.QloadChanUtil;
/* because no ACM is supported, the available bandwidth is 1 sec */
pLoad->AvalAdmCap = le2cpu16(0x7a12); /* 0x7a12 * 32us = 1 second */
/* copy the element to the frame */
MakeOutgoingFrame(pBeaconBuf, &ElmLen,
sizeof(ELM_QBSS_LOAD), pLoad,
END_OF_ARGS);
return ElmLen;
}
/*
========================================================================
Routine Description:
Update Channel Utilization.
Arguments:
pAd - WLAN control block pointer
UpTime - current up time
Return Value:
None
Note:
UpTime is used in QLOAD_FUNC_BUSY_TIME_STATS & QLOAD_FUNC_BUSY_TIME_ALARM
If UpTime != 0, it means that the time period calling the function
maybe not TBTT so we need to re-calculate the time period.
If you call the function in kernel thread, the time period sometimes
will not accurate due to kernel thread is not real-time, so we need to
recalculate the time period.
========================================================================
*/
VOID QBSS_LoadUpdate(
IN RTMP_ADAPTER *pAd,
IN ULONG UpTime)
{
UINT32 ChanUtilNu, ChanUtilDe;
UINT32 BusyTime = 0;
UINT32 BusyTimeId;
UINT32 TimePeriod = pAd->CommonCfg.BeaconPeriod;
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
BOOLEAN FlgIsBusyOverThreshold = FALSE;
BOOLEAN FlgIsAlarmNeeded = FALSE;
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
/* check whether channel busy time calculation is enabled */
if ((pAd->phy_ctrl.FlgQloadEnable == 0) ||
(pAd->phy_ctrl.FlgQloadAlarmIsSuspended == TRUE))
return;
/* calculate new time period if needed */
if ((UpTime > 0) &&
(pAd->phy_ctrl.QloadUpTimeLast > 0) &&
(UpTime > pAd->phy_ctrl.QloadUpTimeLast))
{
/* re-calculate time period */
TimePeriod = (UINT32)(UpTime - pAd->phy_ctrl.QloadUpTimeLast);
/* translate to mini-second */
TimePeriod = (TimePeriod*1000)/OS_HZ;
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
/* re-calculate phy_ctrl.QloadBusyTimeThreshold */
if (TimePeriod != pAd->phy_ctrl.QloadTimePeriodLast)
QBSS_LoadAlarmBusyTimeThresholdReset(pAd, TimePeriod);
pAd->phy_ctrl.QloadTimePeriodLast = TimePeriod;
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
}
/* update up time */
pAd->phy_ctrl.QloadUpTimeLast = UpTime;
/* do busy time statistics */
#ifdef DOT11_N_SUPPORT
if ((pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset != 0) &&
(pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth != 0))
{
/* in 20MHz, no need to check busy time of secondary channel */
RTMP_IO_READ32(pAd, CH_BUSY_STA_SEC, &BusyTime);
pAd->phy_ctrl.QloadLatestChannelBusyTimeSec = BusyTime;
#ifdef QLOAD_FUNC_BUSY_TIME_STATS
BusyTimeId = BusyTime >> 10; /* translate us to ms */
/* ex:95ms, 95*20/100 = 19 */
BusyTimeId = (BusyTimeId*QLOAD_BUSY_INTERVALS)/TimePeriod;
if (BusyTimeId >= QLOAD_BUSY_INTERVALS)
BusyTimeId = QLOAD_BUSY_INTERVALS - 1;
pAd->phy_ctrl.QloadBusyCountSec[BusyTimeId] ++;
#endif /* QLOAD_FUNC_BUSY_TIME_STATS */
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
if ((pAd->phy_ctrl.FlgQloadAlarmIsSuspended == FALSE) &&
(pAd->phy_ctrl.QloadAlarmBusyTimeThreshold > 0))
{
/* Alarm is not suspended and is enabled */
if ((pAd->phy_ctrl.QloadBusyTimeThreshold != 0) &&
(BusyTime >= pAd->phy_ctrl.QloadBusyTimeThreshold))
{
FlgIsBusyOverThreshold = TRUE;
}
}
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
}
#endif /* DOT11_N_SUPPORT */
/* do busy time statistics for primary channel */
#ifdef CUSTOMER_DCC_FEATURE
if(pAd->EnableChannelStatsCheck)
{
BusyTime = pAd->ChannelStats.ChBusyTime100msecValue;
}
else if(!(ApScanRunning(pAd)))
#endif
RTMP_IO_READ32(pAd, CH_BUSY_STA, &BusyTime);
pAd->phy_ctrl.QloadLatestChannelBusyTimePri = BusyTime;
#ifdef QLOAD_FUNC_BUSY_TIME_STATS
BusyTimeId = BusyTime >> 10; /* translate us to ms */
/* ex:95ms, 95*20/100 = 19 */
BusyTimeId = (BusyTimeId*QLOAD_BUSY_INTERVALS)/TimePeriod;
if (BusyTimeId >= QLOAD_BUSY_INTERVALS)
BusyTimeId = QLOAD_BUSY_INTERVALS - 1;
pAd->phy_ctrl.QloadBusyCountPri[BusyTimeId] ++;
#endif /* QLOAD_FUNC_BUSY_TIME_STATS */
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
if ((pAd->phy_ctrl.FlgQloadAlarmIsSuspended == FALSE) &&
(pAd->phy_ctrl.QloadAlarmBusyTimeThreshold > 0))
{
/* Alarm is not suspended and is enabled */
if ((pAd->phy_ctrl.QloadBusyTimeThreshold != 0) &&
(BusyTime >= pAd->phy_ctrl.QloadBusyTimeThreshold))
{
FlgIsBusyOverThreshold = TRUE;
}
}
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
/* accumulate channel busy time for primary channel */
pAd->phy_ctrl.QloadChanUtilTotal += BusyTime;
/* update new channel utilization for primary channel */
if (++pAd->phy_ctrl.QloadChanUtilBeaconCnt >= pAd->phy_ctrl.QloadChanUtilBeaconInt)
{
ChanUtilNu = pAd->phy_ctrl.QloadChanUtilTotal;
ChanUtilNu *= 255;
ChanUtilDe = pAd->phy_ctrl.QloadChanUtilBeaconInt;
/*
Still use pAd->CommonCfg.BeaconPeriod.
Because we change QloadChanUtil not every TBTT.
*/
ChanUtilDe *= pAd->CommonCfg.BeaconPeriod;
ChanUtilDe <<= 10; /* ms to us */
pAd->phy_ctrl.QloadChanUtil = (UINT8)(ChanUtilNu/ChanUtilDe);
if((ChanUtilNu/ChanUtilDe) >= 255)
pAd->phy_ctrl.QloadChanUtil = 255;
/* re-accumulate channel busy time */
pAd->phy_ctrl.QloadChanUtilBeaconCnt = 0;
pAd->phy_ctrl.QloadChanUtilTotal = 0;
}
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
/* check if alarm function is enabled */
if ((pAd->phy_ctrl.FlgQloadAlarmIsSuspended == FALSE) &&
(pAd->phy_ctrl.QloadAlarmBusyTimeThreshold > 0))
{
/* Alarm is not suspended and is enabled */
/* check if we need to issue a alarm */
if (FlgIsBusyOverThreshold == TRUE)
{
if (pAd->phy_ctrl.QloadAlarmDuration == 0)
{
/* last alarm ended so we can check new alarm */
pAd->phy_ctrl.QloadAlarmBusyNum ++;
if (pAd->phy_ctrl.QloadAlarmBusyNum >= pAd->phy_ctrl.QloadAlarmBusyNumThreshold)
{
/*
The continued number of busy time >= threshold is larger
than number threshold so issuing a alarm.
*/
FlgIsAlarmNeeded = TRUE;
pAd->phy_ctrl.QloadAlarmDuration ++;
}
}
}
else
pAd->phy_ctrl.QloadAlarmBusyNum = 0;
if (pAd->phy_ctrl.QloadAlarmDuration > 0)
{
/*
New alarm occurs so we can not re-issue new alarm during
QBSS_LOAD_ALARM_DURATION * TBTT.
*/
if (++pAd->phy_ctrl.QloadAlarmDuration >= QBSS_LOAD_ALARM_DURATION)
{
/* can re-issue next alarm */
pAd->phy_ctrl.QloadAlarmDuration = 0;
pAd->phy_ctrl.QloadAlarmBusyNum = 0;
}
}
if (FlgIsAlarmNeeded == TRUE)
QBSS_LoadAlarm(pAd);
}
else
{
/* clear statistics counts */
pAd->phy_ctrl.QloadAlarmBusyNum = 0;
pAd->phy_ctrl.QloadAlarmDuration = 0;
pAd->phy_ctrl.FlgQloadAlarm = FALSE;
}
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
}
/*
========================================================================
Routine Description:
Clear QoS Load information.
Arguments:
pAd - WLAN control block pointer
Return Value:
None
Note:
========================================================================
*/
VOID QBSS_LoadStatusClear(
IN RTMP_ADAPTER *pAd)
{
#ifdef QLOAD_FUNC_BUSY_TIME_STATS
/* clear busy time statistics */
NdisZeroMemory(pAd->phy_ctrl.QloadBusyCountPri, sizeof(pAd->phy_ctrl.QloadBusyCountPri));
NdisZeroMemory(pAd->phy_ctrl.QloadBusyCountSec, sizeof(pAd->phy_ctrl.QloadBusyCountSec));
#endif /* QLOAD_FUNC_BUSY_TIME_STATS */
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
/* clear alarm function variables */
pAd->phy_ctrl.QloadChanUtilTotal = 0;
pAd->phy_ctrl.FlgQloadAlarm = FALSE;
pAd->phy_ctrl.QloadAlarmBusyNum = 0;
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
}
/*
========================================================================
Routine Description:
Show QoS Load information.
Arguments:
pAd - WLAN control block pointer
Arg - Input arguments
Return Value:
None
Note:
========================================================================
*/
INT Show_QoSLoad_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
#ifdef QLOAD_FUNC_BUSY_TIME_STATS
UINT32 BusyTimeId;
UINT32 Time;
Time = pAd->CommonCfg.BeaconPeriod / QLOAD_BUSY_INTERVALS;
DBGPRINT(RT_DEBUG_OFF, ("\n\tPrimary Busy Time\tTimes\n"));
for(BusyTimeId=0; BusyTimeId<QLOAD_BUSY_INTERVALS; BusyTimeId++)
{
DBGPRINT(RT_DEBUG_OFF, ("\t%dms ~ %dms\t\t%d\n",
BusyTimeId*Time,
(BusyTimeId+1)*Time,
pAd->phy_ctrl.QloadBusyCountPri[BusyTimeId]));
}
DBGPRINT(RT_DEBUG_OFF, ("\n\tSecondary Busy Time\tTimes\n"));
for(BusyTimeId=0; BusyTimeId<QLOAD_BUSY_INTERVALS; BusyTimeId++)
{
DBGPRINT(RT_DEBUG_OFF, ("\t%dms ~ %dms\t\t%d\n",
BusyTimeId*Time,
(BusyTimeId+1)*Time,
pAd->phy_ctrl.QloadBusyCountSec[BusyTimeId]));
}
#else
DBGPRINT(RT_DEBUG_OFF, ("\tBusy time statistics is not included into the driver!\n"));
#endif /* QLOAD_FUNC_BUSY_TIME_STATS */
DBGPRINT(RT_DEBUG_OFF, ("\n"));
return TRUE;
}
/*
========================================================================
Routine Description:
Command for QoS Load information clear.
Arguments:
pAd - WLAN control block pointer
Arg - Input arguments
Return Value:
None
Note:
========================================================================
*/
INT Set_QloadClr_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING Arg)
{
QBSS_LoadStatusClear(pAd);
return TRUE;
}
/*
========================================================================
Routine Description:
Command for QoS Alarm Time Threshold set.
Arguments:
pAd - WLAN control block pointer
Arg - Input arguments
Return Value:
None
Note:
========================================================================
*/
INT Set_QloadAlarmTimeThreshold_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING Arg)
{
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
pAd->phy_ctrl.QloadAlarmBusyTimeThreshold = (UCHAR)simple_strtol(Arg, 0, 10);
QBSS_LoadAlarmReset(pAd);
pAd->phy_ctrl.QloadTimePeriodLast = pAd->CommonCfg.BeaconPeriod;
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
return TRUE;
}
/*
========================================================================
Routine Description:
Command for QoS Alarm Number Threshold set.
Arguments:
pAd - WLAN control block pointer
Arg - Input arguments
Return Value:
None
Note:
========================================================================
*/
INT Set_QloadAlarmNumThreshold_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING Arg)
{
#ifdef QLOAD_FUNC_BUSY_TIME_ALARM
pAd->phy_ctrl.QloadAlarmBusyNumThreshold = (UCHAR)simple_strtol(Arg, 0, 10);
#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */
return TRUE;
}
#endif /* AP_QLOAD_SUPPORT */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,722 @@
/****************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
****************************************************************************
Module Name:
ap_sanity.c
Abstract:
Handle association related requests either from WSTA or from local MLME
Revision History:
Who When What
-------- ---------- ----------------------------------------------
John Chang 08-14-2003 created for 11g soft-AP
John Chang 12-30-2004 merge with STA driver for RT2600
*/
#include "rt_config.h"
extern UCHAR CISCO_OUI[];
extern UCHAR WPA_OUI[];
extern UCHAR RSN_OUI[];
extern UCHAR WME_INFO_ELEM[];
extern UCHAR WME_PARM_ELEM[];
extern UCHAR RALINK_OUI[];
extern UCHAR MTK_OUI[];
extern UCHAR BROADCOM_OUI[];
extern UCHAR WPS_OUI[];
/*
==========================================================================
Description:
MLME message sanity check
Return:
TRUE if all parameters are OK, FALSE otherwise
==========================================================================
*/
BOOLEAN PeerAssocReqCmmSanity(
RTMP_ADAPTER *pAd,
BOOLEAN isReassoc,
VOID *Msg,
INT MsgLen,
IE_LISTS *ie_lists)
{
PFRAME_802_11 Fr = (PFRAME_802_11)Msg;
PEID_STRUCT eid_ptr;
UCHAR Sanity = 0;
UCHAR WPA1_OUI[4] = { 0x00, 0x50, 0xF2, 0x01 };
UCHAR WPA2_OUI[3] = { 0x00, 0x0F, 0xAC };
#ifdef CONFIG_HOTSPOT_R2
UCHAR HS2_OSEN_OUI[4] = { 0x50, 0x6f, 0x9a, 0x12 };
UCHAR HS2OUIBYTE[4] = {0x50, 0x6f, 0x9a, 0x10};
#endif
MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)NULL;
#ifdef DOT11R_FT_SUPPORT
PFT_INFO pFtInfo = &ie_lists->FtInfo;
#endif /* DOT11R_FT_SUPPORT */
#ifdef DOT11K_RRM_SUPPORT
RRM_EN_CAP_IE *pRrmEnCap = &ie_lists->RrmEnCap;
#endif /* DOT11K_RRM_SUPPORT */
HT_CAPABILITY_IE *pHtCapability = &ie_lists->HTCapability;
pEntry = MacTableLookup(pAd, &Fr->Hdr.Addr2[0]);
if (pEntry == NULL)
return FALSE;
COPY_MAC_ADDR(&ie_lists->Addr2[0], &Fr->Hdr.Addr2[0]);
NdisMoveMemory(&ie_lists->CapabilityInfo, &Fr->Octet[0], 2);
NdisMoveMemory(&ie_lists->ListenInterval, &Fr->Octet[2], 2);
if (isReassoc)
{
NdisMoveMemory(&ie_lists->ApAddr[0], &Fr->Octet[4], 6);
eid_ptr = (PEID_STRUCT) &Fr->Octet[10];
}
else
{
eid_ptr = (PEID_STRUCT) &Fr->Octet[4];
}
/* get variable fields from payload and advance the pointer */
while (((UCHAR *)eid_ptr + eid_ptr->Len + 1) < ((UCHAR *)Fr + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_SSID:
if (((Sanity&0x1) == 1))
break;
if ((eid_ptr->Len <= MAX_LEN_OF_SSID))
{
Sanity |= 0x01;
NdisMoveMemory(&ie_lists->Ssid[0], eid_ptr->Octet, eid_ptr->Len);
ie_lists->SsidLen = eid_ptr->Len;
DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - SsidLen = %d \n", ie_lists->SsidLen));
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SSID\n"));
return FALSE;
}
break;
case IE_SUPP_RATES:
if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) &&
(eid_ptr->Len > 0))
{
Sanity |= 0x02;
NdisMoveMemory(&ie_lists->SupportedRates[0], eid_ptr->Octet, eid_ptr->Len);
DBGPRINT(RT_DEBUG_TRACE,
("PeerAssocReqSanity - IE_SUPP_RATES., Len=%d. "
"Rates[0]=%x\n", eid_ptr->Len, ie_lists->SupportedRates[0]));
DBGPRINT(RT_DEBUG_TRACE,
("Rates[1]=%x %x %x %x %x %x %x\n",
ie_lists->SupportedRates[1], ie_lists->SupportedRates[2],
ie_lists->SupportedRates[3], ie_lists->SupportedRates[4],
ie_lists->SupportedRates[5], ie_lists->SupportedRates[6],
ie_lists->SupportedRates[7]));
ie_lists->SupportedRatesLen = eid_ptr->Len;
}
else
{
UCHAR RateDefault[8] = \
{ 0x82, 0x84, 0x8b, 0x96, 0x12, 0x24, 0x48, 0x6c };
/* HT rate not ready yet. return true temporarily. rt2860c */
/*DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SUPP_RATES\n")); */
Sanity |= 0x02;
ie_lists->SupportedRatesLen = 8;
NdisMoveMemory(&ie_lists->SupportedRates[0], RateDefault, 8);
DBGPRINT(RT_DEBUG_TRACE,
("PeerAssocReqSanity - wrong IE_SUPP_RATES., Len=%d\n",
eid_ptr->Len));
}
break;
case IE_EXT_SUPP_RATES:
if (eid_ptr->Len + ie_lists->SupportedRatesLen <= MAX_LEN_OF_SUPPORTED_RATES)
{
NdisMoveMemory(&ie_lists->SupportedRates[ie_lists->SupportedRatesLen], eid_ptr->Octet,
eid_ptr->Len);
ie_lists->SupportedRatesLen += eid_ptr->Len;
}
else
{
NdisMoveMemory(&ie_lists->SupportedRates[ie_lists->SupportedRatesLen], eid_ptr->Octet,
MAX_LEN_OF_SUPPORTED_RATES - (ie_lists->SupportedRatesLen));
ie_lists->SupportedRatesLen = MAX_LEN_OF_SUPPORTED_RATES;
}
break;
case IE_HT_CAP:
if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE))
{
NdisMoveMemory(pHtCapability, eid_ptr->Octet, SIZE_HT_CAP_IE);
*(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
#ifdef UNALIGNMENT_SUPPORT
{
EXT_HT_CAP_INFO extHtCapInfo;
NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO));
*(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo));
NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO));
}
#else
*(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
#endif /* UNALIGNMENT_SUPPORT */
ie_lists->ht_cap_len = SIZE_HT_CAP_IE;
Sanity |= 0x10;
DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - IE_HT_CAP\n"));
}
else
{
DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len));
}
break;
case IE_EXT_CAPABILITY:
if (eid_ptr->Len)
{
INT ext_len = eid_ptr->Len;
ext_len = ext_len > sizeof(EXT_CAP_INFO_ELEMENT) ? sizeof(EXT_CAP_INFO_ELEMENT) : ext_len;
NdisMoveMemory(&ie_lists->ExtCapInfo, eid_ptr->Octet, ext_len);
DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - IE_EXT_CAPABILITY!\n"));
}
break;
case IE_WPA: /* same as IE_VENDOR_SPECIFIC */
case IE_WPA2:
#ifdef CONFIG_HOTSPOT_R2
if (NdisEqualMemory(eid_ptr->Octet, HS2OUIBYTE, sizeof(HS2OUIBYTE)) && (eid_ptr->Len >= 5))
{
//UCHAR tmp2 = 0x12;
UCHAR *hs2_config = (UCHAR *)&eid_ptr->Octet[4];
UCHAR ppomo_exist = ((*hs2_config) >> 1) & 0x01;
UCHAR hs2_version = ((*hs2_config) >> 4) & 0x0f;
//UCHAR *tmp3 = (UCHAR *)&pEntry->hs_info.ppsmo_id;
//UCHAR tmp[2] = {0x12,0x34};
pEntry->hs_info.version = hs2_version;
pEntry->hs_info.ppsmo_exist = ppomo_exist;
if (pEntry->hs_info.ppsmo_exist)
{
NdisMoveMemory(&pEntry->hs_info.ppsmo_id, &eid_ptr->Octet[5], 2);
//NdisMoveMemory(tmp3, tmp, 2);
}
printk("Assoc HS2 STA:version:%d,ppomo exist:%d, value:0x%x\n", pEntry->hs_info.version, pEntry->hs_info.ppsmo_exist, pEntry->hs_info.ppsmo_id);
break;
}
#endif /* CONFIG_HOTSPOT_R2 */
#ifdef DOT11R_FT_SUPPORT
#endif /* DOT11R_FT_SUPPORT */
if (NdisEqualMemory(eid_ptr->Octet, WPS_OUI, 4))
{
#ifdef WSC_AP_SUPPORT
#ifdef WSC_V2_SUPPORT
if ((pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscV2Info.bWpsEnable) ||
(pAd->ApCfg.MBSSID[pEntry->apidx].WscControl.WscV2Info.bEnableWpsV2 == FALSE))
#endif /* WSC_V2_SUPPORT */
ie_lists->bWscCapable = TRUE;
#endif /* WSC_AP_SUPPORT */
break;
}
#ifdef SMART_MESH
if ((eid_ptr->Len >= NTGR_OUI_LEN) && NdisEqualMemory(eid_ptr->Octet, NETGEAR_OUI, NTGR_OUI_LEN))
{
if(pEntry)
{
if(eid_ptr->Len > NTGR_OUI_LEN)
{
PSMART_MESH_CFG pSmartMeshCfg = NULL;
pSmartMeshCfg = &pAd->ApCfg.MBSSID[pEntry->apidx].SmartMeshCfg;
if ((eid_ptr->Octet[3] & 0x02))
{
pEntry->bSupportSmartMesh = TRUE;
if(pSmartMeshCfg->bSupportSmartMesh)
pEntry->bEnableSmartMesh = TRUE;
DBGPRINT(RT_DEBUG_ERROR, ("Peer supports SMART MESH\n"));
}
else
pEntry->bEnableSmartMesh = FALSE;
if (((pSmartMeshCfg->HiFiFlagMask != 0) && (pSmartMeshCfg->HiFiFlagValue != 0)) &&
((eid_ptr->Octet[3] & pSmartMeshCfg->HiFiFlagMask) == pSmartMeshCfg->HiFiFlagValue))
{
pEntry->bHyperFiPeer = TRUE;
DBGPRINT(RT_DEBUG_ERROR, ("Peer is Hyper-Fi device\n"));
}
else
pEntry->bHyperFiPeer = FALSE;
#ifdef MWDS
if ((eid_ptr->Octet[3] & 0x01))
{
pEntry->bSupportMWDS = TRUE;
if(pAd->ApCfg.MBSSID[pEntry->apidx].bSupportMWDS)
pEntry->bEnableMWDS = TRUE;
DBGPRINT(RT_DEBUG_ERROR, ("Peer supports MWDS\n"));
}
else
pEntry->bEnableMWDS = FALSE;
#endif /* MWDS */
#ifdef WSC_AP_SUPPORT
#ifdef SMART_MESH_HIDDEN_WPS
if ((eid_ptr->Octet[3] & 0x04))
{
pEntry->bSupportHiddenWPS = TRUE;
DBGPRINT(RT_DEBUG_ERROR, ("Peer supports HiddenWPS\n"));
}
else
pEntry->bSupportHiddenWPS = FALSE;
if((eid_ptr->Len - NTGR_OUI_LEN) >= NTGR_CUSTOM_IE_MAX_LEN)
pEntry->bRunningHiddenWPS = (eid_ptr->Octet[5] & HIDDEN_WPS_STATE_RUNNING) ? TRUE : FALSE;
#endif /* SMART_MESH_HIDDEN_WPS */
#endif /* WSC_AP_SUPPORT */
}
}
else
DBGPRINT(RT_DEBUG_ERROR, ("%s():pEntry is NULL\n",__func__));
break;
}
#endif /* SMART_MESH */
/* Handle Atheros and Broadcom draft 11n STAs */
if (NdisEqualMemory(eid_ptr->Octet, BROADCOM_OUI, 3))
{
switch (eid_ptr->Octet[3])
{
case 0x33:
if ((eid_ptr->Len-4) == sizeof(HT_CAPABILITY_IE))
{
NdisMoveMemory(pHtCapability, &eid_ptr->Octet[4], SIZE_HT_CAP_IE);
*(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo));
#ifdef UNALIGNMENT_SUPPORT
{
EXT_HT_CAP_INFO extHtCapInfo;
NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO));
*(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo));
NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO));
}
#else
*(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo));
#endif /* UNALIGNMENT_SUPPORT */
ie_lists->ht_cap_len = SIZE_HT_CAP_IE;
}
break;
default:
/* ignore other cases */
break;
}
}
if (NdisEqualMemory(eid_ptr->Octet, RALINK_OUI, 3) && (eid_ptr->Len == 7))
{
if (eid_ptr->Octet[3] != 0)
ie_lists->RalinkIe = eid_ptr->Octet[3];
else
ie_lists->RalinkIe = 0xf0000000; /* Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag. */
break;
}
if (NdisEqualMemory(eid_ptr->Octet, MTK_OUI, 3) && (eid_ptr->Len == 7))
{
if (eid_ptr->Octet[3] != 0)
ie_lists->MediatekIe= eid_ptr->Octet[3];
break;
}
/* WMM_IE */
if (NdisEqualMemory(eid_ptr->Octet, WME_INFO_ELEM, 6) && (eid_ptr->Len == 7))
{
ie_lists->bWmmCapable = TRUE;
#ifdef UAPSD_SUPPORT
if (pEntry)
{
UAPSD_AssocParse(pAd,
pEntry, (UINT8 *)&eid_ptr->Octet[6],
pAd->ApCfg.MBSSID[pEntry->apidx].UapsdInfo.bAPSDCapable);
}
#endif /* UAPSD_SUPPORT */
break;
}
if (pAd->ApCfg.MBSSID[pEntry->apidx].wdev.AuthMode < Ndis802_11AuthModeWPA)
break;
/* If this IE did not begins with 00:0x50:0xf2:0x01,
it would be proprietary. So we ignore it. */
if (!NdisEqualMemory(eid_ptr->Octet, WPA1_OUI, sizeof(WPA1_OUI))
&& !NdisEqualMemory(&eid_ptr->Octet[2], WPA2_OUI, sizeof(WPA2_OUI)))
{
DBGPRINT(RT_DEBUG_TRACE, ("Not RSN IE, maybe WMM IE!!!\n"));
#ifdef CONFIG_HOTSPOT_R2
if (!NdisEqualMemory(eid_ptr->Octet, HS2_OSEN_OUI, sizeof(HS2_OSEN_OUI)))
{
unsigned char *tmp = (unsigned char *)eid_ptr->Octet;
DBGPRINT(RT_DEBUG_OFF, ("!!!!!!not found OSEN IE,%x:%x:%x:%x\n", *tmp, *(tmp+1), *(tmp+2), *(tmp+3)));
CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_OSEN_CAPABLE);
break;
}
else
{
CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_OSEN_CAPABLE);
DBGPRINT(RT_DEBUG_OFF, ("!!!!!!found OSEN IE\n"));
}
#else
break;
#endif
}
if (/*(eid_ptr->Len <= MAX_LEN_OF_RSNIE) &&*/ (eid_ptr->Len >= MIN_LEN_OF_RSNIE))
{
hex_dump("Received RSNIE in Assoc-Req", (UCHAR *)eid_ptr, eid_ptr->Len + 2);
/* Copy whole RSNIE context */
NdisMoveMemory(&ie_lists->RSN_IE[0], eid_ptr, eid_ptr->Len + 2);
ie_lists->RSNIE_Len =eid_ptr->Len + 2;
#ifdef DOT11R_FT_SUPPORT
NdisMoveMemory(pFtInfo->RSN_IE, eid_ptr, eid_ptr->Len + 2);
pFtInfo->RSNIE_Len = eid_ptr->Len + 2;
#endif /* DOT11R_FT_SUPPORT */
}
else
{
ie_lists->RSNIE_Len = 0;
DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - missing IE_WPA(%d)\n",eid_ptr->Len));
return FALSE;
}
break;
#ifdef WAPI_SUPPORT
case IE_WAPI:
if ((pAd->ApCfg.MBSSID[pEntry->apidx].wdev.AuthMode != Ndis802_11AuthModeWAICERT) &&
(pAd->ApCfg.MBSSID[pEntry->apidx].wdev.AuthMode != Ndis802_11AuthModeWAIPSK))
break;
/* Sanity check the validity of WIE */
/* Todo - AlbertY */
/* Copy whole WAPI-IE context */
NdisMoveMemory(&ie_lists->RSN_IE[0], eid_ptr, eid_ptr->Len + 2);
ie_lists->RSNIE_Len =eid_ptr->Len + 2;
DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - IE_WAPI(%d)\n",eid_ptr->Len));
break;
#endif /* WAPI_SUPPORT */
#ifdef DOT11R_FT_SUPPORT
case IE_FT_MDIE:
FT_FillMdIeInfo(eid_ptr, &pFtInfo->MdIeInfo);
break;
case IE_FT_FTIE:
FT_FillFtIeInfo(eid_ptr, &pFtInfo->FtIeInfo);
break;
case IE_FT_RIC_DATA:
/* record the pointer of first RDIE. */
if (pFtInfo->RicInfo.pRicInfo == NULL)
{
pFtInfo->RicInfo.pRicInfo = &eid_ptr->Eid;
pFtInfo->RicInfo.Len = ((UCHAR*)Fr + MsgLen) - (UCHAR*)eid_ptr + 1;
}
case IE_FT_RIC_DESCRIPTOR:
if ((pFtInfo->RicInfo.RicIEsLen + eid_ptr->Len + 2) < MAX_RICIES_LEN)
{
NdisMoveMemory(&pFtInfo->RicInfo.RicIEs[pFtInfo->RicInfo.RicIEsLen],
&eid_ptr->Eid, eid_ptr->Len + 2);
pFtInfo->RicInfo.RicIEsLen += eid_ptr->Len + 2;
}
break;
#endif /* DOT11R_FT_SUPPORT */
#ifdef DOT11K_RRM_SUPPORT
case IE_RRM_EN_CAP:
{
UINT64 value;
NdisMoveMemory(&value, eid_ptr->Octet, sizeof(UINT64));
pRrmEnCap->word = le2cpu64(value);
}
break;
#endif /* DOT11K_RRM_SUPPORT */
#ifdef DOT11_VHT_AC
case IE_VHT_CAP:
if (eid_ptr->Len == sizeof(VHT_CAP_IE))
{
NdisMoveMemory(&ie_lists->vht_cap, eid_ptr->Octet, sizeof(VHT_CAP_IE));
ie_lists->vht_cap_len = eid_ptr->Len;
DBGPRINT(RT_DEBUG_TRACE, ("%s():IE_VHT_CAP\n", __FUNCTION__));
}
else
{
DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_VHT_CAP, eid->Len = %d\n",
__FUNCTION__, eid_ptr->Len));
}
case IE_VHT_OP:
if (eid_ptr->Len == sizeof(VHT_OP_IE))
{
NdisMoveMemory(&ie_lists->vht_op, eid_ptr->Octet, sizeof(VHT_OP_IE));
ie_lists->vht_op_len = eid_ptr->Len;
DBGPRINT(RT_DEBUG_TRACE, ("%s():IE_VHT_OP\n", __FUNCTION__));
}
case IE_OPERATING_MODE_NOTIFY:
if (eid_ptr->Len == sizeof(OPERATING_MODE)) {
ie_lists->operating_mode_len = sizeof(OPERATING_MODE);
NdisMoveMemory(&ie_lists->operating_mode, &eid_ptr->Octet[0], sizeof(OPERATING_MODE));
DBGPRINT(RT_DEBUG_TRACE, ("%s():IE_OPERATING_MODE_NOTIFY!\n", __FUNCTION__));
}
break;
#endif /* DOT11_VHT_AC */
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
if ((Sanity&0x3) != 0x03)
{
DBGPRINT(RT_DEBUG_WARN, ("%s(): - missing mandatory field\n", __FUNCTION__));
return FALSE;
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("%s() - success\n", __FUNCTION__));
return TRUE;
}
}
/*
==========================================================================
Description:
MLME message sanity check
Return:
TRUE if all parameters are OK, FALSE otherwise
==========================================================================
*/
BOOLEAN PeerDisassocReqSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *Msg,
IN ULONG MsgLen,
OUT PUCHAR pAddr1,
OUT PUCHAR pAddr2,
OUT UINT16 *SeqNum,
OUT USHORT *Reason)
{
PFRAME_802_11 Fr = (PFRAME_802_11)Msg;
COPY_MAC_ADDR(pAddr1, &Fr->Hdr.Addr1);
COPY_MAC_ADDR(pAddr2, &Fr->Hdr.Addr2);
*SeqNum = Fr->Hdr.Sequence;
NdisMoveMemory(Reason, &Fr->Octet[0], 2);
return TRUE;
}
/*
==========================================================================
Description:
MLME message sanity check
Return:
TRUE if all parameters are OK, FALSE otherwise
==========================================================================
*/
BOOLEAN PeerDeauthReqSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *Msg,
IN ULONG MsgLen,
OUT PUCHAR pAddr2,
OUT UINT16 *SeqNum,
OUT USHORT *Reason)
{
PFRAME_802_11 Fr = (PFRAME_802_11)Msg;
COPY_MAC_ADDR(pAddr2, &Fr->Hdr.Addr2);
*SeqNum = Fr->Hdr.Sequence;
NdisMoveMemory(Reason, &Fr->Octet[0], 2);
return TRUE;
}
/*
==========================================================================
Description:
MLME message sanity check
Return:
TRUE if all parameters are OK, FALSE otherwise
==========================================================================
*/
BOOLEAN APPeerAuthSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *Msg,
IN ULONG MsgLen,
OUT PUCHAR pAddr1,
OUT PUCHAR pAddr2,
OUT USHORT *Alg,
OUT USHORT *Seq,
OUT USHORT *Status,
CHAR *ChlgText
#ifdef DOT11R_FT_SUPPORT
,PFT_INFO pFtInfo
#endif /* DOT11R_FT_SUPPORT */
)
{
PFRAME_802_11 Fr = (PFRAME_802_11)Msg;
COPY_MAC_ADDR(pAddr1, &Fr->Hdr.Addr1); /* BSSID */
COPY_MAC_ADDR(pAddr2, &Fr->Hdr.Addr2); /* SA */
NdisMoveMemory(Alg, &Fr->Octet[0], 2);
NdisMoveMemory(Seq, &Fr->Octet[2], 2);
NdisMoveMemory(Status, &Fr->Octet[4], 2);
if (*Alg == AUTH_MODE_OPEN)
{
if (*Seq == 1 || *Seq == 2)
{
return TRUE;
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("APPeerAuthSanity fail - wrong Seg# (=%d)\n", *Seq));
return FALSE;
}
}
else if (*Alg == AUTH_MODE_KEY)
{
if (*Seq == 1 || *Seq == 4)
{
return TRUE;
}
else if (*Seq == 2 || *Seq == 3)
{
NdisMoveMemory(ChlgText, &Fr->Octet[8], CIPHER_TEXT_LEN);
return TRUE;
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("APPeerAuthSanity fail - wrong Seg# (=%d)\n", *Seq));
return FALSE;
}
}
#ifdef DOT11R_FT_SUPPORT
else if (*Alg == AUTH_MODE_FT)
{
PEID_STRUCT eid_ptr;
UCHAR *Ptr;
UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC};
NdisZeroMemory(pFtInfo, sizeof(FT_INFO));
Ptr = &Fr->Octet[6];
eid_ptr = (PEID_STRUCT) Ptr;
/* get variable fields from payload and advance the pointer */
while(((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_FT_MDIE:
FT_FillMdIeInfo(eid_ptr, &pFtInfo->MdIeInfo);
break;
case IE_FT_FTIE:
FT_FillFtIeInfo(eid_ptr, &pFtInfo->FtIeInfo);
break;
case IE_FT_RIC_DATA:
/* record the pointer of first RDIE. */
if (pFtInfo->RicInfo.pRicInfo == NULL)
{
pFtInfo->RicInfo.pRicInfo = &eid_ptr->Eid;
pFtInfo->RicInfo.Len = ((UCHAR*)Fr + MsgLen)
- (UCHAR*)eid_ptr + 1;
}
if ((pFtInfo->RicInfo.RicIEsLen + eid_ptr->Len + 2) < MAX_RICIES_LEN)
{
NdisMoveMemory(&pFtInfo->RicInfo.RicIEs[pFtInfo->RicInfo.RicIEsLen],
&eid_ptr->Eid, eid_ptr->Len + 2);
pFtInfo->RicInfo.RicIEsLen += eid_ptr->Len + 2;
}
break;
case IE_FT_RIC_DESCRIPTOR:
if ((pFtInfo->RicInfo.RicIEsLen + eid_ptr->Len + 2) < MAX_RICIES_LEN)
{
NdisMoveMemory(&pFtInfo->RicInfo.RicIEs[pFtInfo->RicInfo.RicIEsLen],
&eid_ptr->Eid, eid_ptr->Len + 2);
pFtInfo->RicInfo.RicIEsLen += eid_ptr->Len + 2;
}
break;
case IE_RSN:
if (NdisEqualMemory(&eid_ptr->Octet[2], WPA2_OUI, sizeof(WPA2_OUI)))
{
NdisMoveMemory(pFtInfo->RSN_IE, eid_ptr, eid_ptr->Len + 2);
pFtInfo->RSNIE_Len = eid_ptr->Len + 2;
}
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
}
#endif /* DOT11R_FT_SUPPORT */
else
{
DBGPRINT(RT_DEBUG_TRACE, ("APPeerAuthSanity fail - wrong algorithm (=%d)\n", *Alg));
return FALSE;
}
return TRUE;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,107 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
ap_wds.c
Abstract:
Support WDS function.
Revision History:
Who When What
------ ---------- ----------------------------------------------
Fonchi 02-13-2007 created
*/
#define RTMP_MODULE_OS
#ifdef WDS_SUPPORT
/*#include "rt_config.h" */
#include "rtmp_comm.h"
#include "rt_os_util.h"
#include "rt_os_net.h"
struct rtnl_link_stats64 *
RT28xx_get_wds_ether_stats64(PNET_DEV net_dev, struct rtnl_link_stats64 *stats);
/* Register WDS interface */
VOID RT28xx_WDS_Init(VOID *pAd, PNET_DEV net_dev)
{
RTMP_OS_NETDEV_OP_HOOK netDevOpHook;
NdisZeroMemory((PUCHAR)&netDevOpHook, sizeof(RTMP_OS_NETDEV_OP_HOOK));
netDevOpHook.open = WdsVirtualIF_open;
netDevOpHook.stop = WdsVirtualIF_close;
netDevOpHook.xmit = rt28xx_send_packets;
netDevOpHook.ioctl = rt28xx_ioctl;
netDevOpHook.get_stats = RT28xx_get_wds_ether_stats64;
NdisMoveMemory(&netDevOpHook.devAddr[0], RTMP_OS_NETDEV_GET_PHYADDR(net_dev), MAC_ADDR_LEN);
DBGPRINT(RT_DEBUG_TRACE, ("The new WDS interface MAC = %02X:%02X:%02X:%02X:%02X:%02X\n",
PRINT_MAC(netDevOpHook.devAddr)));
RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_WDS_INIT,
0, &netDevOpHook, 0);
}
INT WdsVirtualIF_open(PNET_DEV dev)
{
VOID *pAd;
DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> VirtualIF_open\n", RTMP_OS_NETDEV_GET_DEVNAME(dev)));
pAd = RTMP_OS_NETDEV_GET_PRIV(dev);
if (VIRTUAL_IF_UP(pAd) != 0)
return -1;
/* increase MODULE use count */
RT_MOD_INC_USE_COUNT();
RTMP_OS_NETDEV_START_QUEUE(dev);
return 0;
}
INT WdsVirtualIF_close(PNET_DEV dev)
{
VOID *pAd;
DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> VirtualIF_close\n", RTMP_OS_NETDEV_GET_DEVNAME(dev)));
pAd = RTMP_OS_NETDEV_GET_PRIV(dev);
//RTMP_OS_NETDEV_CARRIER_OFF(dev);
RTMP_OS_NETDEV_STOP_QUEUE(dev);
VIRTUAL_IF_DOWN(pAd);
RT_MOD_DEC_USE_COUNT();
return 0;
}
VOID RT28xx_WDS_Remove(VOID *pAd)
{
RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_WDS_REMOVE, 0, NULL, 0);
}
#endif /* WDS_SUPPORT */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,851 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2006, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
apcli_auth.c
Abstract:
Revision History:
Who When What
-------- ---------- -------------------------------------------
*/
#ifdef APCLI_SUPPORT
#include "rt_config.h"
static VOID ApCliAuthTimeout(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3);
DECLARE_TIMER_FUNCTION(ApCliAuthTimeout);
BUILD_TIMER_FUNCTION(ApCliAuthTimeout);
#ifdef MAC_REPEATER_SUPPORT
static VOID ApCliAuthTimeoutExt(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3);
DECLARE_TIMER_FUNCTION(ApCliAuthTimeoutExt);
BUILD_TIMER_FUNCTION(ApCliAuthTimeoutExt);
#endif /* MAC_REPEATER_SUPPORT */
/*
==========================================================================
Description:
function to be executed at timer thread when auth timer expires
==========================================================================
*/
static VOID ApCliAuthTimeout(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
DBGPRINT(RT_DEBUG_TRACE, ("%s():AuthTimeout\n", __FUNCTION__));
MlmeEnqueue(pAd, APCLI_AUTH_STATE_MACHINE, APCLI_MT2_AUTH_TIMEOUT, 0, NULL, 0);
RTMP_MLME_HANDLER(pAd);
return;
}
#ifdef MAC_REPEATER_SUPPORT
static VOID ApCliAuthTimeoutExt(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
PREPEATER_CLIENT_ENTRY pRepeaterCliEntry = (PREPEATER_CLIENT_ENTRY)FunctionContext;
PRTMP_ADAPTER pAd;
USHORT ifIndex = 0;
DBGPRINT(RT_DEBUG_TRACE, ("Repeater Cli AUTH - AuthTimeout\n"));
pAd = pRepeaterCliEntry->pAd;
ifIndex = (64 + (16*pRepeaterCliEntry->MatchApCliIdx) + pRepeaterCliEntry->MatchLinkIdx);
DBGPRINT(RT_DEBUG_ERROR, (" (%s) ifIndex = %d, CliIdx = %d !!!\n",
__FUNCTION__, pRepeaterCliEntry->MatchApCliIdx, pRepeaterCliEntry->MatchLinkIdx));
MlmeEnqueue(pAd, APCLI_AUTH_STATE_MACHINE, APCLI_MT2_AUTH_TIMEOUT, 0, NULL, ifIndex);
RTMP_MLME_HANDLER(pAd);
return;
}
#endif /* MAC_REPEATER_SUPPORT */
/*
==========================================================================
Description:
==========================================================================
*/
static VOID ApCliMlmeAuthReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
BOOLEAN Cancelled;
NDIS_STATUS NState;
UCHAR Addr[MAC_ADDR_LEN];
USHORT Alg, Seq, Status;
ULONG Timeout;
HEADER_802_11 AuthHdr;
PUCHAR pOutBuffer = NULL;
ULONG FrameLen = 0;
APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg;
USHORT ifIndex = (USHORT)(Elem->Priv);
PULONG pCurrState = NULL;
#ifdef MAC_REPEATER_SUPPORT
UCHAR CliIdx = 0xFF;
#endif /* MAC_REPEATER_SUPPORT */
if ((ifIndex >= MAX_APCLI_NUM)
#ifdef MAC_REPEATER_SUPPORT
&& (ifIndex < 64)
#endif /* MAC_REPEATER_SUPPORT */
)
return;
#ifdef MAC_REPEATER_SUPPORT
if (ifIndex >= 64)
{
CliIdx = ((ifIndex - 64) % 16);
ifIndex = ((ifIndex - 64) / 16);
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState;
}
else
#endif /* MAC_REPEATER_SUPPORT */
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState;
/* Block all authentication request durning WPA block period */
if (pAd->ApCfg.ApCliTab[ifIndex].bBlockAssoc == TRUE)
{
DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - Block Auth request durning WPA block period!\n"));
*pCurrState = APCLI_AUTH_REQ_IDLE;
ApCliCtrlMsg.Status = MLME_STATE_MACHINE_REJECT;
#ifdef MAC_REPEATER_SUPPORT
ApCliCtrlMsg.BssIdx = ifIndex;
ApCliCtrlMsg.CliIdx = CliIdx;
ifIndex = (USHORT)(Elem->Priv);
#endif /* MAC_REPEATER_SUPPORT */
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP,
sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex);
}
else if(MlmeAuthReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr, &Timeout, &Alg))
{
#ifdef MAC_REPEATER_SUPPORT
/* reset timer */
if (CliIdx != 0xFF)
RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAuthTimer, &Cancelled);
else
#endif /* MAC_REPEATER_SUPPORT */
RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.ApCliAuthTimer, &Cancelled);
pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Alg = Alg;
Seq = 1;
Status = MLME_SUCCESS;
/* allocate and send out AuthReq frame */
NState = MlmeAllocateMemory(pAd, &pOutBuffer);
if(NState != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR, ("APCLI AUTH - MlmeAuthReqAction() allocate memory failed\n"));
*pCurrState = APCLI_AUTH_REQ_IDLE;
ApCliCtrlMsg.Status = MLME_FAIL_NO_RESOURCE;
#ifdef MAC_REPEATER_SUPPORT
ApCliCtrlMsg.BssIdx = ifIndex;
ApCliCtrlMsg.CliIdx = CliIdx;
ifIndex = (USHORT)(Elem->Priv);
#endif /* MAC_REPEATER_SUPPORT */
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP,
sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex);
return;
}
DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - Send AUTH request seq#1 (Alg=%d)...\n", Alg));
ApCliMgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, ifIndex);
#ifdef MAC_REPEATER_SUPPORT
if (CliIdx != 0xFF)
COPY_MAC_ADDR(AuthHdr.Addr2, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress);
#endif /* MAC_REPEATER_SUPPORT */
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11),&AuthHdr,
2, &Alg,
2, &Seq,
2, &Status,
END_OF_ARGS);
#ifdef SMART_MESH
SMART_MESH_INSERT_IE(pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg,
pOutBuffer,
FrameLen,
SM_IE_AUTH_REQ);
#endif /* SMART_MESH */
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
#ifdef MAC_REPEATER_SUPPORT
if (CliIdx != 0xFF)
RTMPSetTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAuthTimer, AUTH_TIMEOUT);
else
#endif /* MAC_REPEATER_SUPPORT */
RTMPSetTimer(&pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.ApCliAuthTimer, AUTH_TIMEOUT);
*pCurrState = APCLI_AUTH_WAIT_SEQ2;
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("APCLI AUTH - MlmeAuthReqAction() sanity check failed. BUG!!!!!\n"));
*pCurrState = APCLI_AUTH_REQ_IDLE;
}
return;
}
/*
==========================================================================
Description:
==========================================================================
*/
static VOID ApCliPeerAuthRspAtSeq2Action(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM * Elem)
{
BOOLEAN Cancelled;
UCHAR Addr2[MAC_ADDR_LEN];
USHORT Seq, Status, Alg;
USHORT RemoteStatus;
UCHAR iv_hdr[LEN_WEP_IV_HDR];
/* UCHAR ChlgText[CIPHER_TEXT_LEN]; */
UCHAR *ChlgText = NULL;
UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8];
ULONG c_len = 0;
HEADER_802_11 AuthHdr;
NDIS_STATUS NState;
PUCHAR pOutBuffer = NULL;
ULONG FrameLen = 0;
APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg;
UCHAR ChallengeIe = IE_CHALLENGE_TEXT;
UCHAR len_challengeText = CIPHER_TEXT_LEN;
USHORT ifIndex = (USHORT)(Elem->Priv);
PULONG pCurrState = NULL;
APCLI_STRUCT *apcli_entry;
#ifdef MAC_REPEATER_SUPPORT
UCHAR CliIdx = 0xFF;
#endif /* MAC_REPEATER_SUPPORT */
if ((ifIndex >= MAX_APCLI_NUM)
#ifdef MAC_REPEATER_SUPPORT
&& (ifIndex < 64)
#endif /* MAC_REPEATER_SUPPORT */
)
return;
#ifdef MAC_REPEATER_SUPPORT
if (ifIndex >= 64)
{
CliIdx = ((ifIndex - 64) % 16);
ifIndex = ((ifIndex - 64) / 16);
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState;
}
else
#endif /* MAC_REPEATER_SUPPORT */
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState;
apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex];
/* allocate memory */
os_alloc_mem(NULL, (UCHAR **)&ChlgText, CIPHER_TEXT_LEN);
if (ChlgText == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
return;
}
if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, (CHAR *) ChlgText))
{
if(MAC_ADDR_EQUAL(apcli_entry->MlmeAux.Bssid, Addr2) && Seq == 2)
{
#ifdef MAC_REPEATER_SUPPORT
if (CliIdx != 0xFF)
{
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Repeater Cli Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status));
RTMPCancelTimer(&apcli_entry->RepeaterCli[CliIdx].ApCliAuthTimer, &Cancelled);
}
else
#endif /* MAC_REPEATER_SUPPORT */
{
DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status));
RTMPCancelTimer(&apcli_entry->MlmeAux.ApCliAuthTimer, &Cancelled);
}
if(Status == MLME_SUCCESS)
{
if(apcli_entry->MlmeAux.Alg == Ndis802_11AuthModeOpen)
{
*pCurrState = APCLI_AUTH_REQ_IDLE;
ApCliCtrlMsg.Status= MLME_SUCCESS;
#ifdef MAC_REPEATER_SUPPORT
ApCliCtrlMsg.CliIdx = CliIdx;
ApCliCtrlMsg.BssIdx = ifIndex;
ifIndex = (USHORT)(Elem->Priv);
#endif /* MAC_REPEATER_SUPPORT */
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP,
sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex);
}
else
{
PCIPHER_KEY pKey;
UINT default_key = apcli_entry->wdev.DefaultKeyId;
pKey = &apcli_entry->SharedKey[default_key];
/* 2. shared key, need to be challenged */
Seq++;
RemoteStatus = MLME_SUCCESS;
/* allocate and send out AuthRsp frame */
NState = MlmeAllocateMemory(pAd, &pOutBuffer);
if(NState != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - ApCliPeerAuthRspAtSeq2Action allocate memory fail\n"));
*pCurrState = APCLI_AUTH_REQ_IDLE;
ApCliCtrlMsg.Status= MLME_FAIL_NO_RESOURCE;
#ifdef MAC_REPEATER_SUPPORT
ApCliCtrlMsg.CliIdx = CliIdx;
ApCliCtrlMsg.BssIdx = ifIndex;
ifIndex = (USHORT)(Elem->Priv);
#endif /* MAC_REPEATER_SUPPORT */
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP,
sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex);
goto LabelOK;
}
#ifdef MAC_REPEATER_SUPPORT
if (CliIdx != 0xFF)
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Repeater Cli Send AUTH request seq#3...\n"));
else
#endif /* MAC_REPEATER_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n"));
ApCliMgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, apcli_entry->MlmeAux.Bssid, ifIndex);
AuthHdr.FC.Wep = 1;
#ifdef MAC_REPEATER_SUPPORT
if (CliIdx != 0xFF)
COPY_MAC_ADDR(AuthHdr.Addr2, apcli_entry->RepeaterCli[CliIdx].CurrentAddress);
#endif /* MAC_REPEATER_SUPPORT */
/* Encrypt challenge text & auth information */
/* TSC increment */
INC_TX_TSC(pKey->TxTsc, LEN_WEP_TSC);
/* Construct the 4-bytes WEP IV header */
RTMPConstructWEPIVHdr(default_key, pKey->TxTsc, iv_hdr);
Alg = cpu2le16(*(USHORT *)&Alg);
Seq = cpu2le16(*(USHORT *)&Seq);
RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus);
/* Construct message text */
MakeOutgoingFrame(CyperChlgText, &c_len,
2, &Alg,
2, &Seq,
2, &RemoteStatus,
1, &ChallengeIe,
1, &len_challengeText,
len_challengeText, ChlgText,
END_OF_ARGS);
if (RTMPSoftEncryptWEP(pAd,
iv_hdr,
pKey,
CyperChlgText,
c_len) == FALSE)
{
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - ApCliPeerAuthRspAtSeq2Action allocate memory fail\n"));
*pCurrState = APCLI_AUTH_REQ_IDLE;
ApCliCtrlMsg.Status= MLME_FAIL_NO_RESOURCE;
#ifdef MAC_REPEATER_SUPPORT
ApCliCtrlMsg.BssIdx = ifIndex;
ApCliCtrlMsg.CliIdx = CliIdx;
ifIndex = (USHORT)(Elem->Priv);
#endif /* MAC_REPEATER_SUPPORT */
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP,
sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex);
goto LabelOK;
}
/* Update the total length for 4-bytes ICV */
c_len += LEN_ICV;
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11), &AuthHdr,
LEN_WEP_IV_HDR, iv_hdr,
c_len, CyperChlgText,
END_OF_ARGS);
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
#ifdef MAC_REPEATER_SUPPORT
if (CliIdx != 0xFF)
RTMPSetTimer(&apcli_entry->RepeaterCli[CliIdx].ApCliAuthTimer, AUTH_TIMEOUT);
else
#endif /* MAC_REPEATER_SUPPORT */
RTMPSetTimer(&apcli_entry->MlmeAux.ApCliAuthTimer, AUTH_TIMEOUT);
*pCurrState = APCLI_AUTH_WAIT_SEQ4;
}
}
else
{
*pCurrState = APCLI_AUTH_REQ_IDLE;
#ifdef MAC_REPEATER_SUPPORT
ApCliCtrlMsg.CliIdx = CliIdx;
ApCliCtrlMsg.BssIdx = ifIndex;
ifIndex = (USHORT)(Elem->Priv);
#endif /* MAC_REPEATER_SUPPORT */
ApCliCtrlMsg.Status= Status;
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP,
sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex);
}
}
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - PeerAuthSanity() sanity check fail\n"));
}
LabelOK:
if (pOutBuffer != NULL)
MlmeFreeMemory(pAd, pOutBuffer);
if (ChlgText != NULL)
os_free_mem(NULL, ChlgText);
return;
}
/*
==========================================================================
Description:
==========================================================================
*/
static VOID ApCliPeerAuthRspAtSeq4Action(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem)
{
BOOLEAN Cancelled;
UCHAR Addr2[MAC_ADDR_LEN];
USHORT Alg, Seq, Status;
CHAR ChlgText[CIPHER_TEXT_LEN];
APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg;
USHORT ifIndex = (USHORT)(Elem->Priv);
PULONG pCurrState = NULL;
#ifdef MAC_REPEATER_SUPPORT
UCHAR CliIdx = 0xFF;
#endif /* MAC_REPEATER_SUPPORT */
if ((ifIndex >= MAX_APCLI_NUM)
#ifdef MAC_REPEATER_SUPPORT
&& (ifIndex < 64)
#endif /* MAC_REPEATER_SUPPORT */
)
return;
#ifdef MAC_REPEATER_SUPPORT
if (ifIndex >= 64)
{
CliIdx = ((ifIndex - 64) % 16);
ifIndex = ((ifIndex - 64) / 16);
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState;
}
else
#endif /* MAC_REPEATER_SUPPORT */
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState;
if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText))
{
if(MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, Addr2) && Seq == 4)
{
#ifdef MAC_REPEATER_SUPPORT
if (CliIdx != 0xFF)
{
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Repeater Cli Receive AUTH_RSP seq#4 to me\n"));
RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAuthTimer, &Cancelled);
}
else
#endif /* MAC_REPEATER_SUPPORT */
{
DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - Receive AUTH_RSP seq#4 to me\n"));
RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.ApCliAuthTimer, &Cancelled);
}
ApCliCtrlMsg.Status = MLME_SUCCESS;
if(Status != MLME_SUCCESS)
{
ApCliCtrlMsg.Status = Status;
}
#ifdef MAC_REPEATER_SUPPORT
ApCliCtrlMsg.CliIdx = CliIdx;
ApCliCtrlMsg.BssIdx = ifIndex;
ifIndex = (USHORT)(Elem->Priv);
#endif /* MAC_REPEATER_SUPPORT */
*pCurrState = APCLI_AUTH_REQ_IDLE;
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP,
sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex);
}
} else
{
DBGPRINT(RT_DEBUG_TRACE, ("APCLI - PeerAuthRspAtSeq4Action() sanity check fail\n"));
}
return;
}
/*
==========================================================================
Description:
==========================================================================
*/
static VOID ApCliPeerDeauthAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem)
{
UCHAR Addr1[MAC_ADDR_LEN];
UCHAR Addr2[MAC_ADDR_LEN];
UCHAR Addr3[MAC_ADDR_LEN];
USHORT Reason;
USHORT ifIndex = (USHORT)(Elem->Priv);
PULONG pCurrState = NULL;
#ifdef WPA_SUPPLICANT_SUPPORT
PMAC_TABLE_ENTRY pMacEntry = NULL;
#endif /*WPA_SUPPLICANT_SUPPORT*/
#ifdef MAC_REPEATER_SUPPORT
UCHAR CliIdx = 0xFF;
#endif /* MAC_REPEATER_SUPPORT */
if ((ifIndex >= MAX_APCLI_NUM)
#ifdef MAC_REPEATER_SUPPORT
&& (ifIndex < 64)
#endif /* MAC_REPEATER_SUPPORT */
)
return;
#ifdef MAC_REPEATER_SUPPORT
if (ifIndex >= 64)
{
CliIdx = ((ifIndex - 64) % 16);
ifIndex = ((ifIndex - 64) / 16);
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState;
}
else
#endif /* MAC_REPEATER_SUPPORT */
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState;
#ifdef WPA_SUPPLICANT_SUPPORT
pMacEntry = &pAd->MacTab.Content[pAd->ApCfg.ApCliTab[ifIndex].MacTabWCID];
if (!pMacEntry || !IS_ENTRY_APCLI(pMacEntry))
{
return;
}
#endif /*WPA_SUPPLICANT_SUPPORT*/
if (PeerDeauthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr1, Addr2, Addr3, &Reason))
{
DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH_RSP - receive DE-AUTH from our AP\n"));
*pCurrState = APCLI_AUTH_REQ_IDLE;
#ifdef WPA_SUPPLICANT_SUPPORT
if ((pAd->ApCfg.ApCliTab[ifIndex].wpa_supplicant_info.WpaSupplicantUP != WPA_SUPPLICANT_DISABLE) &&
(pAd->ApCfg.ApCliTab[ifIndex].wdev.AuthMode == Ndis802_11AuthModeWPA2)
&&(pMacEntry->PortSecured == WPA_802_1X_PORT_SECURED))
{
pAd->ApCfg.ApCliTab[ifIndex].wpa_supplicant_info.bLostAp = TRUE;
}
#endif /*WPA_SUPPLICANT_SUPPORT*/
#ifdef MAC_REPEATER_SUPPORT
if ((pAd->ApCfg.bMACRepeaterEn == TRUE) && (CliIdx != 0xFF))
{
#ifdef APCLI_LINK_COVER_SUPPORT
#ifdef DOT11_N_SUPPORT
/* free resources of BA*/
BASessionTearDownALL(pAd, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID);
#endif /* DOT11_N_SUPPORT */
#endif /* APCLI_LINK_COVER_SUPPORT */
RTMPRemoveRepeaterDisconnectEntry(pAd, ifIndex, CliIdx);
RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx);
}
else
#endif /* MAC_REPEATER_SUPPORT */
{
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_PEER_DISCONNECT_REQ, 0, NULL, ifIndex);
RTMP_MLME_HANDLER(pAd);
}
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH_RSP - ApCliPeerDeauthAction() sanity check fail\n"));
}
return;
}
/*
==========================================================================
Description:
==========================================================================
*/
static VOID ApCliAuthTimeoutAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem)
{
USHORT ifIndex = (USHORT)(Elem->Priv);
PULONG pCurrState = NULL;
#ifdef MAC_REPEATER_SUPPORT
UCHAR CliIdx = 0xFF;
#endif /* MAC_REPEATER_SUPPORT */
if ((ifIndex >= MAX_APCLI_NUM)
#ifdef MAC_REPEATER_SUPPORT
&& (ifIndex < 64)
#endif /* MAC_REPEATER_SUPPORT */
)
return;
#ifdef MAC_REPEATER_SUPPORT
if (ifIndex >= 64)
{
CliIdx = ((ifIndex - 64) % 16);
ifIndex = ((ifIndex - 64) / 16);
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState;
}
else
#endif /* MAC_REPEATER_SUPPORT */
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState;
DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - AuthTimeoutAction\n"));
*pCurrState = APCLI_AUTH_REQ_IDLE;
#ifdef MAC_REPEATER_SUPPORT
ifIndex = (USHORT)(Elem->Priv);
#endif /* MAC_REPEATER_SUPPORT */
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_REQ_TIMEOUT, 0, NULL, ifIndex);
return;
}
/*
==========================================================================
Description:
==========================================================================
*/
static VOID ApCliInvalidStateWhenAuth(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem)
{
APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg;
USHORT ifIndex = (USHORT)(Elem->Priv);
PULONG pCurrState = NULL;
#ifdef MAC_REPEATER_SUPPORT
UCHAR CliIdx = 0xFF;
#endif /* MAC_REPEATER_SUPPORT */
if ((ifIndex >= MAX_APCLI_NUM)
#ifdef MAC_REPEATER_SUPPORT
&& (ifIndex < 64)
#endif /* MAC_REPEATER_SUPPORT */
)
return;
#ifdef MAC_REPEATER_SUPPORT
if (ifIndex >= 64)
{
CliIdx = ((ifIndex - 64) % 16);
ifIndex = ((ifIndex - 64) / 16);
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState;
}
else
#endif /* MAC_REPEATER_SUPPORT */
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState;
DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", *pCurrState));
*pCurrState= APCLI_AUTH_REQ_IDLE;
#ifdef MAC_REPEATER_SUPPORT
ApCliCtrlMsg.BssIdx = ifIndex;
ApCliCtrlMsg.CliIdx = CliIdx;
ifIndex = (USHORT)(Elem->Priv);
#endif /* MAC_REPEATER_SUPPORT */
ApCliCtrlMsg.Status = MLME_STATE_MACHINE_REJECT;
MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP,
sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex);
return;
}
/*
==========================================================================
Description:
==========================================================================
*/
static VOID ApCliMlmeDeauthReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
PMLME_DEAUTH_REQ_STRUCT pDeauthReq;
HEADER_802_11 DeauthHdr;
PUCHAR pOutBuffer = NULL;
ULONG FrameLen = 0;
NDIS_STATUS NStatus;
USHORT ifIndex = (USHORT)(Elem->Priv);
PULONG pCurrState = NULL;
#ifdef MAC_REPEATER_SUPPORT
UCHAR CliIdx = 0xFF;
#endif /* MAC_REPEATER_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - ApCliMlmeAuthReqAction (state=%ld), reset AUTH state machine\n",
pAd->Mlme.ApCliAuthMachine.CurrState));
if ((ifIndex >= MAX_APCLI_NUM)
#ifdef MAC_REPEATER_SUPPORT
&& (ifIndex < 64)
#endif /* MAC_REPEATER_SUPPORT */
)
return;
#ifdef MAC_REPEATER_SUPPORT
if (ifIndex >= 64)
{
CliIdx = ((ifIndex - 64) % 16);
ifIndex = ((ifIndex - 64) / 16);
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState;
}
else
#endif /* MAC_REPEATER_SUPPORT */
pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState;
pDeauthReq = (PMLME_DEAUTH_REQ_STRUCT)(Elem->Msg);
*pCurrState= APCLI_AUTH_REQ_IDLE;
NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */
if (NStatus != NDIS_STATUS_SUCCESS)
return;
DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send DE-AUTH request (Reason=%d)...\n", pDeauthReq->Reason));
ApCliMgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pDeauthReq->Addr, pDeauthReq->Addr, ifIndex);
#ifdef MAC_REPEATER_SUPPORT
if (CliIdx != 0xFF)
COPY_MAC_ADDR(DeauthHdr.Addr2, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress);
#endif /* MAC_REPEATER_SUPPORT */
MakeOutgoingFrame(pOutBuffer, &FrameLen,
sizeof(HEADER_802_11),&DeauthHdr,
2, &pDeauthReq->Reason,
END_OF_ARGS);
MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen);
MlmeFreeMemory(pAd, pOutBuffer);
return;
}
/*
==========================================================================
Description:
authenticate state machine init, including state transition and timer init
Parameters:
Sm - pointer to the auth state machine
Note:
The state machine looks like this
==========================================================================
*/
VOID ApCliAuthStateMachineInit(
IN RTMP_ADAPTER *pAd,
IN STATE_MACHINE *Sm,
OUT STATE_MACHINE_FUNC Trans[])
{
UCHAR i;
#ifdef MAC_REPEATER_SUPPORT
UCHAR j;
#endif /* MAC_REPEATER_SUPPORT */
StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans,
APCLI_MAX_AUTH_STATE, APCLI_MAX_AUTH_MSG,
(STATE_MACHINE_FUNC)Drop, APCLI_AUTH_REQ_IDLE,
APCLI_AUTH_MACHINE_BASE);
/* the first column */
StateMachineSetAction(Sm, APCLI_AUTH_REQ_IDLE, APCLI_MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)ApCliMlmeAuthReqAction);
StateMachineSetAction(Sm, APCLI_AUTH_REQ_IDLE, APCLI_MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)ApCliPeerDeauthAction);
StateMachineSetAction(Sm, APCLI_AUTH_REQ_IDLE, APCLI_MT2_MLME_DEAUTH_REQ, (STATE_MACHINE_FUNC)ApCliMlmeDeauthReqAction);
/* the second column */
StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ2, APCLI_MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)ApCliInvalidStateWhenAuth);
StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ2, APCLI_MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)ApCliPeerAuthRspAtSeq2Action);
StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ2, APCLI_MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)ApCliPeerDeauthAction);
StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ2, APCLI_MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)ApCliAuthTimeoutAction);
StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ2, APCLI_MT2_MLME_DEAUTH_REQ, (STATE_MACHINE_FUNC)ApCliMlmeDeauthReqAction);
/* the third column */
StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ4, APCLI_MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)ApCliInvalidStateWhenAuth);
StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ4, APCLI_MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)ApCliPeerAuthRspAtSeq4Action);
StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ4, APCLI_MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)ApCliPeerDeauthAction);
StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ4, APCLI_MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)ApCliAuthTimeoutAction);
StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ4, APCLI_MT2_MLME_DEAUTH_REQ, (STATE_MACHINE_FUNC)ApCliMlmeDeauthReqAction);
for (i=0; i < MAX_APCLI_NUM; i++)
{
pAd->ApCfg.ApCliTab[i].AuthCurrState = APCLI_AUTH_REQ_IDLE;
/* timer init */
RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].MlmeAux.ApCliAuthTimer, GET_TIMER_FUNCTION(ApCliAuthTimeout), pAd, FALSE);
#ifdef MAC_REPEATER_SUPPORT
for (j = 0; j < MAX_EXT_MAC_ADDR_SIZE; j++)
{
pAd->ApCfg.ApCliTab[i].RepeaterCli[j].pAd = pAd;
pAd->ApCfg.ApCliTab[i].RepeaterCli[j].MatchApCliIdx = i;
pAd->ApCfg.ApCliTab[i].RepeaterCli[j].MatchLinkIdx = j;
pAd->ApCfg.ApCliTab[i].RepeaterCli[j].AuthCurrState = APCLI_AUTH_REQ_IDLE;
/* timer init */
RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].RepeaterCli[j].ApCliAuthTimer,
GET_TIMER_FUNCTION(ApCliAuthTimeoutExt), &pAd->ApCfg.ApCliTab[i].RepeaterCli[j], FALSE);
}
#endif /* MAC_REPEATER_SUPPORT */
}
return;
}
#endif /* APCLI_SUPPORT */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,508 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2004, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
rt65xx.c
Abstract:
Specific funcitons and configurations for RT65xx
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#ifdef RT65xx
#include "rt_config.h"
VOID RT65xxDisableTxRx(
RTMP_ADAPTER *pAd,
UCHAR Level)
{
UINT32 MacReg = 0;
UINT32 MTxCycle;
BOOLEAN bResetWLAN = FALSE;
BOOLEAN bFree = TRUE;
UINT8 CheckFreeTimes = 0;
if (!IS_RT65XX(pAd))
return;
DBGPRINT(RT_DEBUG_TRACE, ("----> %s\n", __FUNCTION__));
if (Level == RTMP_HALT)
{
RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE);
}
DBGPRINT(RT_DEBUG_TRACE, ("%s Tx success = %ld\n",
__FUNCTION__, (ULONG)pAd->WlanCounters.TransmittedFragmentCount.u.LowPart));
DBGPRINT(RT_DEBUG_TRACE, ("%s Tx success = %ld\n",
__FUNCTION__, (ULONG)pAd->WlanCounters.ReceivedFragmentCount.QuadPart));
StopDmaTx(pAd, Level);
/*
Check page count in TxQ,
*/
for (MTxCycle = 0; MTxCycle < 2000; MTxCycle++)
{
BOOLEAN bFree = TRUE;
RTMP_IO_READ32(pAd, 0x438, &MacReg);
if (MacReg != 0)
bFree = FALSE;
RTMP_IO_READ32(pAd, 0xa30, &MacReg);
if (MacReg & 0x000000FF)
bFree = FALSE;
RTMP_IO_READ32(pAd, 0xa34, &MacReg);
if (MacReg & 0xFF00FF00)
bFree = FALSE;
if (bFree)
break;
if (MacReg == 0xFFFFFFFF)
{
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
return;
}
}
if (MTxCycle >= 2000)
{
DBGPRINT(RT_DEBUG_ERROR, ("Check TxQ page count max\n"));
RTMP_IO_READ32(pAd, 0x0a30, &MacReg);
DBGPRINT(RT_DEBUG_TRACE, ("0x0a30 = 0x%08x\n", MacReg));
RTMP_IO_READ32(pAd, 0x0a34, &MacReg);
DBGPRINT(RT_DEBUG_TRACE, ("0x0a34 = 0x%08x\n", MacReg));
RTMP_IO_READ32(pAd, 0x438, &MacReg);
DBGPRINT(RT_DEBUG_TRACE, ("0x438 = 0x%08x\n", MacReg));
bResetWLAN = TRUE;
}
/*
Check MAC Tx idle
*/
for (MTxCycle = 0; MTxCycle < 2000; MTxCycle++)
{
RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacReg);
if (MacReg & 0x1)
RtmpusecDelay(50);
else
break;
if (MacReg == 0xFFFFFFFF)
{
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
return;
}
}
if (MTxCycle >= 2000)
{
DBGPRINT(RT_DEBUG_ERROR, ("Check MAC Tx idle max(0x%08x)\n", MacReg));
bResetWLAN = TRUE;
}
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) == FALSE)
{
if (Level == RTMP_HALT)
{
/*
Disable MAC TX/RX
*/
RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacReg);
MacReg &= ~(0x0000000c);
RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacReg);
}
else
{
/*
Disable MAC RX
*/
RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacReg);
MacReg &= ~(0x00000008);
RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacReg);
}
}
/*
Check page count in RxQ,
*/
for (MTxCycle = 0; MTxCycle < 2000; MTxCycle++)
{
bFree = TRUE;
RTMP_IO_READ32(pAd, 0x430, &MacReg);
if (MacReg & (0x00FF0000))
bFree = FALSE;
RTMP_IO_READ32(pAd, 0xa30, &MacReg);
if (MacReg != 0)
bFree = FALSE;
RTMP_IO_READ32(pAd, 0xa34, &MacReg);
if (MacReg != 0)
bFree = FALSE;
if (bFree && (CheckFreeTimes > 20) && (!is_inband_cmd_processing(pAd)))
break;
if (bFree)
CheckFreeTimes++;
if (MacReg == 0xFFFFFFFF)
{
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
return;
}
}
RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_POLL_IDLE);
if (MTxCycle >= 2000)
{
DBGPRINT(RT_DEBUG_ERROR, ("Check RxQ page count max\n"));
RTMP_IO_READ32(pAd, 0x0a30, &MacReg);
DBGPRINT(RT_DEBUG_TRACE, ("0x0a30 = 0x%08x\n", MacReg));
RTMP_IO_READ32(pAd, 0x0a34, &MacReg);
DBGPRINT(RT_DEBUG_TRACE, ("0x0a34 = 0x%08x\n", MacReg));
RTMP_IO_READ32(pAd, 0x0430, &MacReg);
DBGPRINT(RT_DEBUG_TRACE, ("0x0430 = 0x%08x\n", MacReg));
bResetWLAN = TRUE;
}
/*
Check MAC Rx idle
*/
for (MTxCycle = 0; MTxCycle < 2000; MTxCycle++)
{
RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacReg);
if (MacReg & 0x2)
RtmpusecDelay(50);
else
break;
if (MacReg == 0xFFFFFFFF)
{
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST);
return;
}
}
if (MTxCycle >= 2000)
{
DBGPRINT(RT_DEBUG_ERROR, ("Check MAC Rx idle max(0x%08x)\n", MacReg));
bResetWLAN = TRUE;
}
StopDmaRx(pAd, Level);
if ((Level == RTMP_HALT) &&
(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) == FALSE))
{
if (!pAd->chipCap.ram_code_protect)
NICEraseFirmware(pAd);
/*
* Disable RF/MAC and do not do reset WLAN under below cases
* 1. Combo card
* 2. suspend including wow application
* 3. radion off command
*/
if ((pAd->chipCap.IsComboChip) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_SUSPEND)
|| RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_CMD_RADIO_OFF))
bResetWLAN = 0;
rlt_wlan_chip_onoff(pAd, FALSE, bResetWLAN);
}
DBGPRINT(RT_DEBUG_TRACE, ("<---- %s\n", __FUNCTION__));
}
#ifdef RTMP_PCI_SUPPORT
void MT76xx_PciMlmeRadioOn(RTMP_ADAPTER *pAd)
{
#ifdef CONFIG_AP_SUPPORT
INT32 IdBss, MaxNumBss = pAd->ApCfg.BssidNum;
#endif /* CONFIG_AP_SUPPORT */
UINT32 mac_val = 0;
MCU_CTRL_INIT(pAd);
/* Clear Radio off flag*/
RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD);
RTMPRingCleanUp(pAd, QID_AC_BK);
RTMPRingCleanUp(pAd, QID_AC_BE);
RTMPRingCleanUp(pAd, QID_AC_VI);
RTMPRingCleanUp(pAd, QID_AC_VO);
RTMPRingCleanUp(pAd, QID_HCCA);
RTMPRingCleanUp(pAd, QID_MGMT);
RTMPRingCleanUp(pAd, QID_RX);
#ifdef CONFIG_ANDES_SUPPORT
RTMPRingCleanUp(pAd, QID_CTRL);
#endif /* CONFIG_ANDES_SUPPORT */
RTMP_ASIC_INTERRUPT_ENABLE(pAd);
PWR_SAVING_OP(pAd, RADIO_ON, 0, 0, 0, 0, 0);
andes_load_cr(pAd, RF_BBP_CR, 0, 0);
RtmpusecDelay(50);
#ifdef DOT11_VHT_AC
if (pAd->CommonCfg.BBPCurrentBW == BW_80)
pAd->hw_cfg.cent_ch = pAd->CommonCfg.vht_cent_ch;
else
#endif /* DOT11_VHT_AC */
pAd->hw_cfg.cent_ch = pAd->CommonCfg.CentralChannel;
AsicSwitchChannel(pAd, pAd->hw_cfg.cent_ch, FALSE);
AsicLockChannel(pAd, pAd->hw_cfg.cent_ch);
#ifdef MT76x2
if (IS_MT76x2(pAd)) {
/*
* add 504, 50c value per ben kao suggestion for rx receivce packet.
*/
RTMP_IO_WRITE32(pAd, 0x50c, 0x0);
RTMP_IO_WRITE32(pAd, 0x504, 0x06000000);
RtmpOsMsDelay(5);
RTMP_IO_WRITE32(pAd, 0x504, 0x0);
}
#endif
/* Enable Tx/Rx*/
RTMPEnableRxTx(pAd);
if (pAd->chipCap.ed_cca_enable == TRUE) {
RTMP_IO_READ32(pAd, TXOP_CTRL_CFG, &mac_val);
mac_val |= (1 << 20);
RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, mac_val);
}
RTMP_IO_READ32(pAd, TXOP_HLDR_ET, &mac_val);
mac_val |= 2;
RTMP_IO_WRITE32(pAd, TXOP_HLDR_ET, mac_val);
/* Restore RTS retry count */
RTMP_IO_WRITE32(pAd, 0x1344, pAd->rts_tx_retry_num);
/* Clear Radio off flag*/
RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF);
#ifdef LED_CONTROL_SUPPORT
#ifdef CONFIG_AP_SUPPORT
/* The LEN_RADIO_ON indicates "Radio on but link down",
so AP shall set LED LINK_UP status */
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
RTMPSetLED(pAd, LED_LINK_UP);
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
/* Set LED*/
RTMPSetLED(pAd, LED_RADIO_ON);
}
#endif /* CONFIG_STA_SUPPORT */
#endif /* LED_CONTROL_SUPPORT */
RTMP_OS_NETDEV_START_QUEUE(pAd->net_dev);
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
if (MaxNumBss > MAX_MBSSID_NUM(pAd))
MaxNumBss = MAX_MBSSID_NUM(pAd);
/* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */
for (IdBss = FIRST_MBSSID; IdBss < MAX_MBSSID_NUM(pAd); IdBss++)
{
if (pAd->ApCfg.MBSSID[IdBss].MSSIDDev)
RTMP_OS_NETDEV_START_QUEUE(pAd->ApCfg.MBSSID[IdBss].MSSIDDev);
}
#ifdef A_BAND_SUPPORT
if ( (pAd->CommonCfg.Channel > 14)
&& (pAd->CommonCfg.bIEEE80211H == 1)
&& RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
{
#ifdef DFS_SUPPORT
NewRadarDetectionStart(pAd);
#endif /* DFS_SUPPORT */
}
#endif /* A_BAND_SUPPORT */
}
#endif /* CONFIG_AP_SUPPORT */
RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET);
}
void MT76xx_PciMlmeRadioOFF(RTMP_ADAPTER *pAd)
{
UINT32 pwr_level = 5, mac_val = 0, bbp_val = 0, loop = 0;
#ifdef CONFIG_AP_SUPPORT
INT32 IdBss, MaxNumBss = pAd->ApCfg.BssidNum;
#endif /* CONFIG_AP_SUPPORT */
RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev);
/* disable prim/second EDCCA before disable mac TX/RX */
RTMP_IO_READ32(pAd, TXOP_CTRL_CFG, &mac_val);
if ((mac_val & 0x100000) == 0x100000) {
DBGPRINT(RT_DEBUG_OFF,("%s:: ED CCA has been enabled\n", __FUNCTION__));
pAd->chipCap.ed_cca_enable = TRUE;
mac_val &= ~(1 << 20);
RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, mac_val);
RTMP_IO_READ32(pAd, TXOP_HLDR_ET, &mac_val);
mac_val &= ~2;
RTMP_IO_WRITE32(pAd, TXOP_HLDR_ET, mac_val);
}
RTMP_IO_READ32(pAd, 0x1004, &mac_val);
mac_val &= ~0xC;
RTMP_IO_WRITE32(pAd, 0x1004, mac_val);
/* Backup the original RTS retry count and then set to 0 */
RTMP_IO_READ32(pAd, 0x1344, &pAd->rts_tx_retry_num);
RTMP_IO_WRITE32(pAd, 0x1344, 0x00092B00);
do {
RTMP_IO_READ32(pAd, 0x1200, &mac_val);
mac_val &= 0x1;
RTMP_BBP_IO_READ32(pAd, 0x2130, &bbp_val);
DBGPRINT(RT_DEBUG_OFF,("%s:: Wait until MAC 0x1200 bit0 and BBP 0x2130 become 0\n", __FUNCTION__));
RtmpusecDelay(1);
loop++;
} while (((mac_val != 0) || (bbp_val != 0)) && (loop < 300));
if (loop >= 300)
DBGPRINT(RT_DEBUG_OFF, ("%s:: Wait until MAC 0x1200 bit0 and BBP 0x2130 become 0 > 300 times\n", __FUNCTION__));
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
if (MaxNumBss > MAX_MBSSID_NUM(pAd))
MaxNumBss = MAX_MBSSID_NUM(pAd);
/* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */
for (IdBss = FIRST_MBSSID; IdBss < MAX_MBSSID_NUM(pAd); IdBss++)
{
if (pAd->ApCfg.MBSSID[IdBss].MSSIDDev)
RTMP_OS_NETDEV_STOP_QUEUE(pAd->ApCfg.MBSSID[IdBss].MSSIDDev);
}
}
#endif /* CONFIG_AP_SUPPORT */
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET);
DBGPRINT(RT_DEBUG_TRACE, ("\npwr_level = %d\n", pwr_level));
#ifdef AP_SCAN_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
BOOLEAN Cancelled;
RTMPCancelTimer(&pAd->MlmeAux.APScanTimer, &Cancelled);
}
#endif /* AP_SCAN_SUPPORT */
#ifdef LED_CONTROL_SUPPORT
RTMPSetLED(pAd, LED_RADIO_OFF);
#endif /* LED_CONTROL_SUPPORT */
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD);
PWR_SAVING_OP(pAd, RADIO_OFF, pwr_level, 0, 0, 0, 0);
RT65xxDisableTxRx(pAd, GUIRADIO_OFF);
MCU_CTRL_EXIT(pAd);
/*
Wait for Andes firmware receiving this in-band command packet
*/
RtmpusecDelay(50);
/* Set Radio off flag*/
RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF);
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE))
{
RTMP_ASIC_INTERRUPT_DISABLE(pAd);
}
}
#endif
VOID dump_bw_info(RTMP_ADAPTER *pAd)
{
#ifdef DBG
UINT32 core_r1, agc_r0, be_r0, band_cfg;
static UCHAR *bw_str[]={"20", "10", "40", "80"};
UCHAR bw, prim_ch_idx, decode_cap;
static UCHAR *decode_str[] = {"0", "20", "40", "20/40",
"80", "20/80", "40/80", "20/40/80"};
UCHAR tx_prim;
RTMP_BBP_IO_READ32(pAd, CORE_R1, &core_r1);
RTMP_BBP_IO_READ32(pAd, AGC1_R0, &agc_r0);
RTMP_BBP_IO_READ32(pAd, TXBE_R0, &be_r0);
RTMP_IO_READ32(pAd, TX_BAND_CFG, &band_cfg);
/* Tx/RX : control channel setting */
DBGPRINT(RT_DEBUG_OFF, ("\n%s():RegisterSetting: TX_BAND_CFG=0x%x, CORE_R1=0x%x, AGC1_R0=0x%x, TXBE_R0=0x%x\n",
__FUNCTION__, band_cfg, core_r1, agc_r0, be_r0));
bw = ((core_r1 & 0x18) >> 3) & 0xff;
DBGPRINT(RT_DEBUG_OFF, ("[CORE_R1]\n"));
DBGPRINT(RT_DEBUG_OFF, ("\tTx/Rx BandwidthCtrl(CORE_R1[4:3])=%d(%s MHz)\n",
bw, bw_str[bw]));
DBGPRINT(RT_DEBUG_OFF, ("[AGC_R0]\n"));
prim_ch_idx = ((agc_r0 & 0x300) >> 8) & 0xff;
DBGPRINT(RT_DEBUG_OFF, ("\tPrimary Channel Idx(AGC_R0[9:8])=%d\n", prim_ch_idx));
decode_cap = ((agc_r0 & 0x7000) >> 12);
DBGPRINT(RT_DEBUG_OFF, ("\tDecodeBWCap(AGC_R0[14:12])=%d(%s MHz Data)\n",
decode_cap, decode_str[decode_cap]));
DBGPRINT(RT_DEBUG_OFF, ("[TXBE_R0 - PPM]\n"));
tx_prim = (be_r0 & 0x3);
DBGPRINT(RT_DEBUG_OFF, ("\tTxPrimary(TXBE_R0[1:0])=%d\n", tx_prim));
#endif
}
#endif /* RT65xx */

View File

@ -0,0 +1,579 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2004, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
rt_chip.c
Abstract:
Ralink Wireless driver CHIP related functions
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#include "rt_config.h"
/*
========================================================================
Routine Description:
write high memory.
if firmware do not support auto high/low memory switching, we should switch to high memory by ourself.
Arguments:
pAd - WLAN control block pointer
Offset - Memory offsets
Value - Written value
Unit - Unit in "Byte"
Return Value:
None
Note:
========================================================================
*/
VOID RtmpChipWriteHighMemory(
IN RTMP_ADAPTER *pAd,
IN USHORT Offset,
IN UINT32 Value,
IN UINT8 Unit)
{
#ifdef RTMP_MAC_PCI
#ifdef SPECIFIC_BCN_BUF_SUPPORT
unsigned long irqFlag = 0;
RTMP_MAC_SHR_MSEL_LOCK(pAd, HIGHER_SHRMEM, irqFlag);
RtmpChipWriteMemory(pAd, Offset, Value, Unit);
RTMP_MAC_SHR_MSEL_UNLOCK(pAd, LOWER_SHRMEM, irqFlag);
#endif /* SPECIFIC_BCN_BUF_SUPPORT */
#endif /* RTMP_MAC_PCI */
}
/*
========================================================================
Routine Description:
write memory
Arguments:
pAd - WLAN control block pointer
Offset - Memory offsets
Value - Written value
Unit - Unit in "Byte"
Return Value:
None
Note:
========================================================================
*/
VOID RtmpChipWriteMemory(
IN RTMP_ADAPTER *pAd,
IN USHORT Offset,
IN UINT32 Value,
IN UINT8 Unit)
{
switch(Unit)
{
case 1:
RTMP_IO_WRITE8(pAd, Offset, Value);
break;
case 2:
RTMP_IO_WRITE16(pAd, Offset, Value);
break;
case 4:
RTMP_IO_WRITE32(pAd, Offset, Value);
default:
break;
}
}
/*
========================================================================
Routine Description:
Initialize specific beacon frame architecture.
Arguments:
pAd - WLAN control block pointer
Return Value:
None
Note:
========================================================================
*/
VOID RtmpChipBcnSpecInit(RTMP_ADAPTER *pAd)
{
#ifdef SPECIFIC_BCN_BUF_SUPPORT
RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
pChipCap->FlgIsSupSpecBcnBuf = TRUE;
pChipCap->BcnMaxHwNum = 16;
pChipCap->WcidHwRsvNum = 255;
/* In 16-MBSS support mode, if AP-Client is enabled,
the last 8-MBSS would be occupied for AP-Client using. */
#ifdef APCLI_SUPPORT
pChipCap->BcnMaxNum = (8 - MAX_MESH_NUM);
#else
pChipCap->BcnMaxNum = (16 - MAX_MESH_NUM);
#endif /* APCLI_SUPPORT */
pChipCap->BcnMaxHwSize = 0x2000;
/* It's allowed to use the higher(secordary) 8KB shared memory */
pChipCap->BcnBase[0] = 0x4000;
pChipCap->BcnBase[1] = 0x4200;
pChipCap->BcnBase[2] = 0x4400;
pChipCap->BcnBase[3] = 0x4600;
pChipCap->BcnBase[4] = 0x4800;
pChipCap->BcnBase[5] = 0x4A00;
pChipCap->BcnBase[6] = 0x4C00;
pChipCap->BcnBase[7] = 0x4E00;
pChipCap->BcnBase[8] = 0x5000;
pChipCap->BcnBase[9] = 0x5200;
pChipCap->BcnBase[10] = 0x5400;
pChipCap->BcnBase[11] = 0x5600;
pChipCap->BcnBase[12] = 0x5800;
pChipCap->BcnBase[13] = 0x5A00;
pChipCap->BcnBase[14] = 0x5C00;
pChipCap->BcnBase[15] = 0x5E00;
pAd->chipOps.BeaconUpdate = RtmpChipWriteHighMemory;
#endif /* SPECIFIC_BCN_BUF_SUPPORT */
}
/*
========================================================================
Routine Description:
Initialize normal beacon frame architecture.
Arguments:
pAd - WLAN control block pointer
Return Value:
None
Note:
========================================================================
*/
VOID RtmpChipBcnInit(
IN RTMP_ADAPTER *pAd)
{
RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
pChipCap->FlgIsSupSpecBcnBuf = FALSE;
pChipCap->BcnMaxHwNum = 8;
pChipCap->BcnMaxNum = (pChipCap->BcnMaxHwNum - MAX_MESH_NUM - MAX_APCLI_NUM);
pChipCap->BcnMaxHwSize = 0x1000;
pChipCap->BcnBase[0] = 0x7800;
pChipCap->BcnBase[1] = 0x7A00;
pChipCap->BcnBase[2] = 0x7C00;
pChipCap->BcnBase[3] = 0x7E00;
pChipCap->BcnBase[4] = 0x7200;
pChipCap->BcnBase[5] = 0x7400;
pChipCap->BcnBase[6] = 0x5DC0;
pChipCap->BcnBase[7] = 0x5BC0;
/*
If the MAX_MBSSID_NUM is larger than 6,
it shall reserve some WCID space(wcid 222~253) for beacon frames.
- these wcid 238~253 are reserved for beacon#6(ra6).
- these wcid 222~237 are reserved for beacon#7(ra7).
*/
if (pChipCap->BcnMaxNum == 8)
pChipCap->WcidHwRsvNum = 222;
else if (pChipCap->BcnMaxNum == 7)
pChipCap->WcidHwRsvNum = 238;
else
pChipCap->WcidHwRsvNum = 255;
pAd->chipOps.BeaconUpdate = RtmpChipWriteMemory;
}
#ifdef RLT_MAC
/*
========================================================================
Routine Description:
Initialize specific beacon frame architecture.
Arguments:
pAd - WLAN control block pointer
Return Value:
None
Note:
========================================================================
*/
VOID rlt_bcn_buf_init(RTMP_ADAPTER *pAd)
{
RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
pChipCap->FlgIsSupSpecBcnBuf = FALSE;
#if defined(MT7601) || defined(MT76x2)
if (IS_MT7601(pAd) || IS_MT76x2(pAd))
{
pChipCap->BcnMaxHwNum = 8;
pChipCap->WcidHwRsvNum = 127;
}
else
#endif /* MT7601 || MT76x2 */
{
pChipCap->BcnMaxHwNum = 16;
pChipCap->WcidHwRsvNum = 255;
}
/*
In 16-MBSS support mode, if AP-Client is enabled,
the last 8-MBSS would be occupied for AP-Client using.
*/
#ifdef APCLI_SUPPORT
pChipCap->BcnMaxNum = (8 - MAX_MESH_NUM);
#else
pChipCap->BcnMaxNum = (pChipCap->BcnMaxHwNum - MAX_MESH_NUM);
#endif /* APCLI_SUPPORT */
pChipCap->BcnMaxHwSize = 0x2000;
pChipCap->BcnBase[0] = 0xc000;
pChipCap->BcnBase[1] = 0xc200;
pChipCap->BcnBase[2] = 0xc400;
pChipCap->BcnBase[3] = 0xc600;
pChipCap->BcnBase[4] = 0xc800;
pChipCap->BcnBase[5] = 0xca00;
pChipCap->BcnBase[6] = 0xcc00;
pChipCap->BcnBase[7] = 0xce00;
pChipCap->BcnBase[8] = 0xd000;
pChipCap->BcnBase[9] = 0xd200;
pChipCap->BcnBase[10] = 0xd400;
pChipCap->BcnBase[11] = 0xd600;
pChipCap->BcnBase[12] = 0xd800;
pChipCap->BcnBase[13] = 0xda00;
pChipCap->BcnBase[14] = 0xdc00;
pChipCap->BcnBase[15] = 0xde00;
#ifdef CONFIG_MULTI_CHANNEL
/* Record HW Null Frame offset */
//pAd->NullBufOffset[0] = 0xd000;
pAd->NullBufOffset[0] = 0xd000;
pAd->NullBufOffset[1] = 0xd200;
#endif /* CONFIG_MULTI_CHANNEL */
pAd->chipOps.BeaconUpdate = RtmpChipWriteMemory;
}
#endif /* RLT_MAC */
#ifdef HW_ANTENNA_DIVERSITY_SUPPORT
UINT32 SetHWAntennaDivsersity(
IN PRTMP_ADAPTER pAd,
IN BOOLEAN Enable)
{
if (Enable == TRUE)
{
UINT8 BBPValue = 0, RFValue = 0;
USHORT value;
// RF_R29 bit7:6
RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_GAIN, value);
RT30xxReadRFRegister(pAd, RF_R29, &RFValue);
RFValue &= 0x3f; // clear bit7:6
RFValue |= (value << 6);
RT30xxWriteRFRegister(pAd, RF_R29, RFValue);
// BBP_R47 bit7=1
RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue);
BBPValue |= 0x80;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue);
BBPValue = 0xbe;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R150, BBPValue);
BBPValue = 0xb0;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R151, BBPValue);
BBPValue = 0x23;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R152, BBPValue);
BBPValue = 0x3a;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R153, BBPValue);
BBPValue = 0x10;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R154, BBPValue);
BBPValue = 0x3b;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R155, BBPValue);
BBPValue = 0x04;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R253, BBPValue);
DBGPRINT(RT_DEBUG_TRACE, ("HwAnDi> Enable!\n"));
}
else
{
UINT8 BBPValue = 0;
/*
main antenna: BBP_R152 bit7=1
aux antenna: BBP_R152 bit7=0
*/
if (pAd->FixDefaultAntenna == 0)
{
/* fix to main antenna */
/* do not care BBP R153, R155, R253 */
BBPValue = 0x3e;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R150, BBPValue);
BBPValue = 0x30;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R151, BBPValue);
BBPValue = 0x23;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R152, BBPValue);
BBPValue = 0x00;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R154, BBPValue);
}
else
{
/* fix to aux antenna */
/* do not care BBP R153, R155, R253 */
BBPValue = 0x3e;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R150, BBPValue);
BBPValue = 0x30;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R151, BBPValue);
BBPValue = 0xa3;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R152, BBPValue);
BBPValue = 0x00;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R154, BBPValue);
}
DBGPRINT(RT_DEBUG_TRACE, ("HwAnDi> Disable!\n"));
}
return 0;
}
#endif // HW_ANTENNA_DIVERSITY_SUPPORT //
INT WaitForAsicReady(RTMP_ADAPTER *pAd)
{
UINT32 mac_val = 0, reg = MAC_CSR0;
int idx = 0;
do
{
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
return FALSE;
RTMP_IO_READ32(pAd, reg, &mac_val);
if ((mac_val != 0x00) && (mac_val != 0xFFFFFFFF))
return TRUE;
RtmpOsMsDelay(5);
} while (idx++ < 500);
DBGPRINT(RT_DEBUG_ERROR,
("%s(0x%x):AsicNotReady!\n",
__FUNCTION__, mac_val));
return FALSE;
}
INT AsicGetMacVersion(RTMP_ADAPTER *pAd)
{
UINT32 reg = MAC_CSR0;
#ifdef RT65xx
if (IS_RT65XX(pAd))
RTMP_IO_READ32(pAd, ASIC_VERSION, &pAd->ChipID);
#endif /* RT65xx */
if (WaitForAsicReady(pAd) == TRUE)
{
RTMP_IO_READ32(pAd, reg, &pAd->MACVersion);
DBGPRINT(RT_DEBUG_OFF, ("MACVersion[Ver:Rev]=0x%08x : 0x%08x\n",
pAd->MACVersion, pAd->ChipID));
return TRUE;
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s() failed!\n", __FUNCTION__));
return FALSE;
}
}
/*
========================================================================
Routine Description:
Initialize chip related information.
Arguments:
pCB - WLAN control block pointer
Return Value:
None
Note:
========================================================================
*/
int RtmpChipOpsHook(VOID *pCB)
{
RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pCB;
RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
UINT32 MacValue;
int ret = 0;
RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
/* sanity check */
if (WaitForAsicReady(pAd) == FALSE)
return -1;
RTMP_IO_READ32(pAd, MAC_CSR0, &MacValue);
pAd->MACVersion = MacValue;
if (pAd->MACVersion == 0xffffffff)
return -1;
#ifdef RT65xx
RTMP_IO_READ32(pAd, ASIC_VERSION, &MacValue);
pAd->ChipID = MacValue;
if (pAd->ChipID == 0xffffffff)
return -1;
#endif /* RT65xx */
/* default init */
RTMP_DRS_ALG_INIT(pAd, RATE_ALG_LEGACY);
#ifdef RTMP_RBUS_SUPPORT
if (pAd->infType == RTMP_DEV_INF_RBUS)
{
RTMP_SYS_IO_READ32(0xb000000c, &pAd->CommonCfg.CID);
RTMP_SYS_IO_READ32(0xb0000000, &pAd->CommonCfg.CN);
#ifdef RT6352
if (IS_RT6352(pAd)) {
pAd->CommonCfg.PKG_ID = (UCHAR)((pAd->CommonCfg.CID >> 16) & 0x0001);
pAd->CommonCfg.Chip_VerID = (UCHAR)((pAd->CommonCfg.CID >> 8) & 0x0f);
pAd->CommonCfg.Chip_E_Number = (UCHAR)((pAd->CommonCfg.CID) & 0x0f);
}
#endif /* RT6352 */
DBGPRINT(RT_DEBUG_TRACE, ("CN: %lx\tCID = %lx\n",
pAd->CommonCfg.CN, pAd->CommonCfg.CID));
}
#endif /* RTMP_RBUS_SUPPORT */
/* EDCCA */
pChipOps->ChipSetEDCCA= NULL;
#ifdef RT8592
if (IS_RT8592(pAd)) {
RT85592_Init(pAd);
goto done;
}
#endif /* RT8592 */
#ifdef MT76x2
if (IS_MT76x2(pAd)) {
mt76x2_init(pAd);
goto done;
}
#endif
#ifdef RT6352
if (IS_RT6352(pAd)) {
RT6352_Init(pAd);
goto done;
}
#endif /* RT6352 */
#ifdef RTMP_MAC
// TODO: default settings for rest of the chips!! change this to really default chip.
RTxx_default_Init(pAd);
#endif /* RTMP_MAC */
/* We depends on RfICType and MACVersion to assign the corresponding operation callbacks. */
done:
DBGPRINT(RT_DEBUG_TRACE, ("Chip specific bbpRegTbSize=%d!\n", pChipCap->bbpRegTbSize));
DBGPRINT(RT_DEBUG_TRACE, ("Chip VCO calibration mode = %d!\n", pChipCap->FlgIsVcoReCalMode));
#ifdef DOT11W_PMF_SUPPORT
DBGPRINT(RT_DEBUG_TRACE, ("[PMF] Encryption mode = %d\n", pChipCap->FlgPMFEncrtptMode));
#endif /* DOT11W_PMF_SUPPORT */
return ret;
}
#ifdef RT65xx
BOOLEAN isExternalPAMode(RTMP_ADAPTER *ad, INT channel)
{
BOOLEAN pa_mode = FALSE;
if (channel > 14) {
if (ad->chipCap.PAType == EXT_PA_2G_5G)
pa_mode = TRUE;
else if (ad->chipCap.PAType == EXT_PA_5G_ONLY)
pa_mode = TRUE;
else
pa_mode = FALSE;
} else {
if (ad->chipCap.PAType == EXT_PA_2G_5G)
pa_mode = TRUE;
else if ((ad->chipCap.PAType == EXT_PA_5G_ONLY) ||
(ad->chipCap.PAType == INT_PA_2G_5G))
pa_mode = FALSE;
else if (ad->chipCap.PAType == EXT_PA_2G_ONLY)
pa_mode = TRUE;
}
return pa_mode;
}
BOOLEAN is_external_lna_mode(RTMP_ADAPTER *ad, INT channel)
{
BOOLEAN lna_mode = FALSE;
/* b'00: 2.4G+5G external LNA, b'01: 5G external LNA, b'10: 2.4G external LNA, b'11: Internal LNA */
if (channel > 14) {
if ((ad->chipCap.LNA_type == 0x0) || (ad->chipCap.LNA_type == 0x1))
lna_mode = TRUE;
else
lna_mode = FALSE;
} else {
if ((ad->chipCap.LNA_type == 0x0) || (ad->chipCap.LNA_type == 0x10))
lna_mode = TRUE;
else
lna_mode = FALSE;
}
return lna_mode;
}
#endif /* RT65xx */

View File

@ -0,0 +1,437 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2004, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
rtxx_dft.c
Abstract:
Ralink Wireless driver chip default init functions
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#include "rt_config.h"
FREQUENCY_ITEM RtmpFreqItems3020[] =
{
/* ISM : 2.4 to 2.483 GHz, 11g */
/*-CH---N-------R---K-----------*/
{1, 241, 2, 2},
{2, 241, 2, 7},
{3, 242, 2, 2},
{4, 242, 2, 7},
{5, 243, 2, 2},
{6, 243, 2, 7},
{7, 244, 2, 2},
{8, 244, 2, 7},
{9, 245, 2, 2},
{10, 245, 2, 7},
{11, 246, 2, 2},
{12, 246, 2, 7},
{13, 247, 2, 2},
{14, 248, 2, 4},
};
FREQUENCY_ITEM FreqItems3020_Xtal20M[] =
{
/*
* RF_R08:
* <7:0>: pll_N<7:0>
*
* RF_R09:
* <3:0>: pll_K<3:0>
* <4>: pll_N<8>
* <7:5>pll_N<11:9>
*
*/
/*-CH---N--------R---N[7:4]K[3:0]------*/
{1, 0xE2, 2, 0x14},
{2, 0xE3, 2, 0x14},
{3, 0xE4, 2, 0x14},
{4, 0xE5, 2, 0x14},
{5, 0xE6, 2, 0x14},
{6, 0xE7, 2, 0x14},
{7, 0xE8, 2, 0x14},
{8, 0xE9, 2, 0x14},
{9, 0xEA, 2, 0x14},
{10, 0xEB, 2, 0x14},
{11, 0xEC, 2, 0x14},
{12, 0xED, 2, 0x14},
{13, 0xEE, 2, 0x14},
{14, 0xF0, 2, 0x18},
};
UCHAR NUM_OF_3020_CHNL = (sizeof(RtmpFreqItems3020) / sizeof(FREQUENCY_ITEM));
FREQUENCY_ITEM *FreqItems3020 = RtmpFreqItems3020;
#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION)
/* The Tx power tuning entry*/
const TX_POWER_TUNING_ENTRY_STRUCT TxPowerTuningTableOrg[] =
{
/* idxTxPowerTable Tx power control over RF Tx power control over MAC*/
/* (zero-based array) { RF R12[4:0]: Tx0 ALC}, {MAC 0x1314~0x1324}*/
/* 0 */ {0x00, -15},
/* 1 */ {0x01, -15},
/* 2 */ {0x00, -14},
/* 3 */ {0x01, -14},
/* 4 */ {0x00, -13},
/* 5 */ {0x01, -13},
/* 6 */ {0x00, -12},
/* 7 */ {0x01, -12},
/* 8 */ {0x00, -11},
/* 9 */ {0x01, -11},
/* 10 */ {0x00, -10},
/* 11 */ {0x01, -10},
/* 12 */ {0x00, -9},
/* 13 */ {0x01, -9},
/* 14 */ {0x00, -8},
/* 15 */ {0x01, -8},
/* 16 */ {0x00, -7},
/* 17 */ {0x01, -7},
/* 18 */ {0x00, -6},
/* 19 */ {0x01, -6},
/* 20 */ {0x00, -5},
/* 21 */ {0x01, -5},
/* 22 */ {0x00, -4},
/* 23 */ {0x01, -4},
/* 24 */ {0x00, -3},
/* 25 */ {0x01, -3},
/* 26 */ {0x00, -2},
/* 27 */ {0x01, -2},
/* 28 */ {0x00, -1},
/* 29 */ {0x01, -1},
/* 30 */ {0x00, 0},
/* 31 */ {0x01, 0},
/* 32 */ {0x02, 0},
/* 33 */ {0x03, 0},
/* 34 */ {0x04, 0},
/* 35 */ {0x05, 0},
/* 36 */ {0x06, 0},
/* 37 */ {0x07, 0},
/* 38 */ {0x08, 0},
/* 39 */ {0x09, 0},
/* 40 */ {0x0A, 0},
/* 41 */ {0x0B, 0},
/* 42 */ {0x0C, 0},
/* 43 */ {0x0D, 0},
/* 44 */ {0x0E, 0},
/* 45 */ {0x0F, 0},
/* 46 */ {0x0F-1, 1},
/* 47 */ {0x0F, 1},
/* 48 */ {0x0F-1, 2},
/* 49 */ {0x0F, 2},
/* 50 */ {0x0F-1, 3},
/* 51 */ {0x0F, 3},
/* 52 */ {0x0F-1, 4},
/* 53 */ {0x0F, 4},
/* 54 */ {0x0F-1, 5},
/* 55 */ {0x0F, 5},
/* 56 */ {0x0F-1, 6},
/* 57 */ {0x0F, 6},
/* 58 */ {0x0F-1, 7},
/* 59 */ {0x0F, 7},
/* 60 */ {0x0F-1, 8},
/* 61 */ {0x0F, 8},
/* 62 */ {0x0F-1, 9},
/* 63 */ {0x0F, 9},
/* 64 */ {0x0F-1, 10},
/* 65 */ {0x0F, 10},
/* 66 */ {0x0F-1, 11},
/* 67 */ {0x0F, 11},
/* 68 */ {0x0F-1, 12},
/* 69 */ {0x0F, 12},
/* 70 */ {0x0F-1, 13},
/* 71 */ {0x0F, 13},
/* 72 */ {0x0F-1, 14},
/* 73 */ {0x0F, 14},
/* 74 */ {0x0F-1, 15},
/* 75 */ {0x0F, 15},
};
#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */
static VOID RxSensitivityTuning(RTMP_ADAPTER *pAd)
{
UCHAR R66 = 0x26 + GET_LNA_GAIN(pAd);
#ifdef RALINK_ATE
if (ATE_ON(pAd))
{
ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66);
}
else
#endif /* RALINK_ATE */
{
bbp_set_agc(pAd, R66, RX_CHAIN_ALL);
}
DBGPRINT(RT_DEBUG_TRACE,("turn off R17 tuning, restore to 0x%02x\n", R66));
}
#ifdef CONFIG_STA_SUPPORT
static UCHAR ChipAGCAdjust(
IN PRTMP_ADAPTER pAd,
IN CHAR Rssi,
IN UCHAR OrigR66Value)
{
UCHAR R66 = OrigR66Value;
CHAR lanGain = GET_LNA_GAIN(pAd);
if (pAd->LatchRfRegs.Channel <= 14)
{ /*BG band*/
R66 = 0x2E + lanGain;
if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
R66 += 0x10;
}
else
{ /*A band*/
if (pAd->CommonCfg.BBPCurrentBW == BW_20)
R66 = 0x32 + (lanGain * 5) / 3;
else
R66 = 0x3A + (lanGain * 5) / 3;
if (Rssi > RSSI_FOR_MID_LOW_SENSIBILITY)
R66 += 0x10;
}
if (OrigR66Value != R66)
bbp_set_agc(pAd, R66, RX_CHAIN_ALL);
return R66;
}
#endif /* CONFIG_STA_SUPPORT */
static VOID ChipBBPAdjust(RTMP_ADAPTER *pAd)
{
UCHAR bbp_val;
UINT8 rf_bw, ext_ch;
#ifdef DOT11_N_SUPPORT
if (get_ht_cent_ch(pAd, &rf_bw, &ext_ch) == FALSE)
#endif /* DOT11_N_SUPPORT */
{
rf_bw = BW_20;
ext_ch = EXTCHA_NONE;
pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel;
}
bbp_set_bw(pAd, rf_bw);
/* TX/RX : control channel setting */
rtmp_mac_set_ctrlch(pAd, ext_ch);
bbp_set_ctrlch(pAd, ext_ch);
/* request by Gary 20070208 for middle and long range G Band*/
#ifdef DOT11_N_SUPPORT
if (rf_bw == BW_40)
bbp_val = (pAd->CommonCfg.Channel > 14) ? 0x48 : 0x38;
else
#endif /* DOT11_N_SUPPORT */
bbp_val = (pAd->CommonCfg.Channel > 14) ? 0x40 : 0x38;
bbp_set_agc(pAd, bbp_val, RX_CHAIN_ALL);
if (pAd->MACVersion == 0x28600100)
{
#ifdef RT28xx
RT28xx_ch_tunning(pAd, BW_40);
#endif /* RT28xx */
}
else
{
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x12);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x10);
}
DBGPRINT(RT_DEBUG_TRACE, ("%s(): BW_%s, ChannelWidth=%d, Channel=%d, ExtChanOffset=%d(%d) \n",
__FUNCTION__, (rf_bw == BW_40 ? "40" : "20"),
pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth,
pAd->CommonCfg.Channel,
pAd->CommonCfg.RegTransmitSetting.field.EXTCHA,
pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset));
/* request by Gary 20070208 for middle and long range A Band*/
if (pAd->CommonCfg.Channel > 14)
bbp_val = 0x1D;
else
bbp_val = 0x2D;
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, bbp_val);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, bbp_val);
RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, bbp_val);
/*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, bbp_val);*/
}
static VOID Default_ChipSwitchChannel(
IN PRTMP_ADAPTER pAd,
IN UCHAR Channel,
IN BOOLEAN bScan)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s(): dummy channel switch function!\n", __FUNCTION__));
}
static VOID Default_ChipAGCInit(RTMP_ADAPTER *pAd, UCHAR BandWidth)
{
UCHAR R66 = 0x30, lan_gain;
lan_gain = GET_LNA_GAIN(pAd);
if (pAd->LatchRfRegs.Channel <= 14)
{ // BG band
{
R66 = 0x2E + lan_gain;
}
}
else
{ //A band
{
if (BandWidth == BW_20)
R66 = (UCHAR)(0x32 + (lan_gain * 5) / 3);
#ifdef DOT11_N_SUPPORT
else
R66 = (UCHAR)(0x3A + (lan_gain * 5) / 3);
#endif // DOT11_N_SUPPORT //
}
}
bbp_set_agc(pAd, R66, RX_CHAIN_ALL);
}
static VOID AsicAntennaDefaultReset(
IN PRTMP_ADAPTER pAd,
IN EEPROM_ANTENNA_STRUC *pAntenna)
{
{
pAntenna->word = 0;
pAntenna->field.RfIcType = RFIC_2820;
pAntenna->field.TxPath = 1;
pAntenna->field.RxPath = 2;
}
DBGPRINT(RT_DEBUG_WARN, ("E2PROM error, hard code as 0x%04x\n", pAntenna->word));
}
VOID NetDevNickNameInit(
IN PRTMP_ADAPTER pAd)
{
#ifdef CONFIG_STA_SUPPORT
#ifdef RTMP_MAC_PCI
snprintf((PSTRING) pAd->nickname, sizeof(pAd->nickname), "RT2860STA");
#endif /* RTMP_MAC_PCI */
#endif /* CONFIG_STA_SUPPORT */
}
VOID RTxx_default_Init(RTMP_ADAPTER *pAd)
{
RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
RTMP_CHIP_CAP *pChipCap = &pAd->chipCap;
/* init default value whatever chipsets */
/* default pChipOps content will be 0x00 */
pChipCap->bbpRegTbSize = 0;
pChipCap->MaxNumOfRfId = 31;
pChipCap->MaxNumOfBbpId = 136;
pChipCap->SnrFormula = SNR_FORMULA1;
pChipCap->RfReg17WtMethod = RF_REG_WT_METHOD_NONE;
pChipCap->TXWISize = 16;
pChipCap->RXWISize = 16;
#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION)
pChipCap->TxPowerTuningTable_2G = TxPowerTuningTableOrg;
#ifdef A_BAND_SUPPORT
pChipCap->TxPowerTuningTable_5G = TxPowerTuningTableOrg;
#endif /* A_BAND_SUPPORT */
#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) */
pChipOps->AsicMacInit = NULL;
pChipOps->AsicBbpInit = NULL;
pChipOps->AsicRfInit = NULL;
#ifdef RTMP_EFUSE_SUPPORT
pChipCap->EFUSE_USAGE_MAP_START = 0x2d0;
pChipCap->EFUSE_USAGE_MAP_END = 0x2fc;
pChipCap->EFUSE_USAGE_MAP_SIZE = 45;
pChipCap->EFUSE_RESERVED_SIZE = pChipCap->EFUSE_USAGE_MAP_SIZE - 5;
#endif /* RTMP_EFUSE_SUPPORT */
pChipCap->VcoPeriod = 10;
pChipCap->FlgIsVcoReCalMode = VCO_CAL_DISABLE;
pChipCap->WPDMABurstSIZE = 2; /* default 64B */
pChipCap->MBSSIDMode = MBSSID_MODE0;
#ifdef DOT11W_PMF_SUPPORT
pChipCap->FlgPMFEncrtptMode = PMF_ENCRYPT_MODE_0;
#endif /* DOT11W_PMF_SUPPORT */
RtmpChipBcnInit(pAd);
pChipOps->RxSensitivityTuning = RxSensitivityTuning;
#ifdef CONFIG_STA_SUPPORT
pChipOps->ChipAGCAdjust = ChipAGCAdjust;
#endif /* CONFIG_STA_SUPPORT */
pChipOps->ChipBBPAdjust = ChipBBPAdjust;
pChipOps->ChipSwitchChannel = Default_ChipSwitchChannel;
/* TX ALC */
pChipCap->bTempCompTxALC = FALSE;
pChipOps->AsicGetTxPowerOffset = NULL;
pChipOps->InitDesiredTSSITable = NULL;
pChipOps->AsicTxAlcGetAutoAgcOffset = NULL;
pChipOps->AsicExtraPowerOverMAC = NULL;
pChipOps->AsicAdjustTxPower = AsicAdjustTxPower;
pChipOps->ChipAGCInit = Default_ChipAGCInit;
pChipOps->AsicAntennaDefaultReset = AsicAntennaDefaultReset;
pChipOps->NetDevNickNameInit = NetDevNickNameInit;
/* Init value. If pChipOps->AsicResetBbpAgent==NULL, "AsicResetBbpAgent" as default. If your chipset has specific routine, please re-hook it at self init function */
pChipOps->AsicResetBbpAgent = NULL;
pChipOps->InitTemperCompensation = NULL;
pChipOps->TemperCompensation = NULL;
#ifdef RT28xx
RT28xx_chip_Init(pAd);
#endif /* RT28xx */
#ifdef CARRIER_DETECTION_SUPPORT
pChipCap->carrier_func = DISABLE_TONE_RADAR;
pChipOps->ToneRadarProgram = NULL;
#endif /* CARRIER_DETECTOIN_SUPPORT */
#ifdef DFS_SUPPORT
pChipCap->DfsEngineNum = 4;
#endif /* DFS_SUPPORT */
pChipOps->CckMrcStatusCtrl = NULL;
pChipOps->RadarGLRTCompensate = NULL;
#ifdef DYNAMIC_VGA_SUPPORT
pChipOps->AsicDynamicVgaGainControl = NULL;
#endif /* DYNAMIC_VGA_SUPPORT */
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,197 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
client_wds.c
Abstract:
*/
#ifdef CLIENT_WDS
#include "rt_config.h"
VOID CliWds_ProxyTabInit(
IN PRTMP_ADAPTER pAd)
{
INT idx;
ULONG i;
NdisAllocateSpinLock(pAd, &pAd->ApCfg.CliWdsTabLock);
/* pAd->ApCfg.pCliWdsEntryPool = kmalloc(sizeof(CLIWDS_PROXY_ENTRY) * CLIWDS_POOL_SIZE, GFP_ATOMIC);*/
os_alloc_mem(pAd, (UCHAR **)&(pAd->ApCfg.pCliWdsEntryPool), sizeof(CLIWDS_PROXY_ENTRY) * CLIWDS_POOL_SIZE);
if (pAd->ApCfg.pCliWdsEntryPool)
{
NdisZeroMemory(pAd->ApCfg.pCliWdsEntryPool, sizeof(CLIWDS_PROXY_ENTRY) * CLIWDS_POOL_SIZE);
initList(&pAd->ApCfg.CliWdsEntryFreeList);
for (i = 0; i < CLIWDS_POOL_SIZE; i++)
insertTailList(&pAd->ApCfg.CliWdsEntryFreeList, (PLIST_ENTRY)(pAd->ApCfg.pCliWdsEntryPool + (ULONG)i));
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pCliWdsEntryPool", __FUNCTION__));
}
for (idx = 0; idx < CLIWDS_HASH_TAB_SIZE; idx++)
initList(&pAd->ApCfg.CliWdsProxyTab[idx]);
return;
}
VOID CliWds_ProxyTabDestory(
IN PRTMP_ADAPTER pAd)
{
INT idx;
PCLIWDS_PROXY_ENTRY pCliWdsEntry;
NdisFreeSpinLock(&pAd->ApCfg.CliWdsTabLock);
for (idx = 0; idx < CLIWDS_HASH_TAB_SIZE; idx++)
{
pCliWdsEntry =
(PCLIWDS_PROXY_ENTRY)pAd->ApCfg.CliWdsProxyTab[idx].pHead;
while(pCliWdsEntry)
{
PCLIWDS_PROXY_ENTRY pCliWdsEntryNext = pCliWdsEntry->pNext;
CliWdsEntyFree(pAd, pCliWdsEntry);
pCliWdsEntry = pCliWdsEntryNext;
}
}
if (pAd->ApCfg.pCliWdsEntryPool)
/* kfree(pAd->ApCfg.pCliWdsEntryPool);*/
os_free_mem(NULL, pAd->ApCfg.pCliWdsEntryPool);
pAd->ApCfg.pCliWdsEntryPool = NULL;
return;
}
PCLIWDS_PROXY_ENTRY CliWdsEntyAlloc(
IN PRTMP_ADAPTER pAd)
{
PCLIWDS_PROXY_ENTRY pCliWdsEntry;
RTMP_SEM_LOCK(&pAd->ApCfg.CliWdsTabLock);
pCliWdsEntry = (PCLIWDS_PROXY_ENTRY)removeHeadList(&pAd->ApCfg.CliWdsEntryFreeList);
RTMP_SEM_UNLOCK(&pAd->ApCfg.CliWdsTabLock);
return pCliWdsEntry;
}
VOID CliWdsEntyFree(
IN PRTMP_ADAPTER pAd,
IN PCLIWDS_PROXY_ENTRY pCliWdsEntry)
{
RTMP_SEM_LOCK(&pAd->ApCfg.CliWdsTabLock);
insertTailList(&pAd->ApCfg.CliWdsEntryFreeList, (PLIST_ENTRY)pCliWdsEntry);
RTMP_SEM_UNLOCK(&pAd->ApCfg.CliWdsTabLock);
return;
}
PUCHAR CliWds_ProxyLookup(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pMac)
{
UINT8 HashId = (*(pMac + 5) & (CLIWDS_HASH_TAB_SIZE - 1));
PCLIWDS_PROXY_ENTRY pCliWdsEntry;
pCliWdsEntry =
(PCLIWDS_PROXY_ENTRY)pAd->ApCfg.CliWdsProxyTab[HashId].pHead;
while (pCliWdsEntry)
{
if (MAC_ADDR_EQUAL(pMac, pCliWdsEntry->Addr))
{
ULONG Now;
NdisGetSystemUpTime(&Now);
pCliWdsEntry->LastRefTime = Now;
if (VALID_WCID(pCliWdsEntry->Aid))
return pAd->MacTab.Content[pCliWdsEntry->Aid].Addr;
else
return NULL;
}
pCliWdsEntry = pCliWdsEntry->pNext;
}
return NULL;
}
VOID CliWds_ProxyTabUpdate(
IN PRTMP_ADAPTER pAd,
IN SHORT Aid,
IN PUCHAR pMac)
{
UINT8 HashId = (*(pMac + 5) & (CLIWDS_HASH_TAB_SIZE - 1));
PCLIWDS_PROXY_ENTRY pCliWdsEntry;
if (CliWds_ProxyLookup(pAd, pMac) != NULL)
return;
pCliWdsEntry = CliWdsEntyAlloc(pAd);
if (pCliWdsEntry)
{
ULONG Now;
NdisGetSystemUpTime(&Now);
pCliWdsEntry->Aid = Aid;
COPY_MAC_ADDR(&pCliWdsEntry->Addr, pMac);
pCliWdsEntry->LastRefTime = Now;
pCliWdsEntry->pNext = NULL;
insertTailList(&pAd->ApCfg.CliWdsProxyTab[HashId], (PLIST_ENTRY)pCliWdsEntry);
}
return;
}
VOID CliWds_ProxyTabMaintain(
IN PRTMP_ADAPTER pAd)
{
ULONG idx;
PCLIWDS_PROXY_ENTRY pCliWdsEntry;
ULONG Now;
NdisGetSystemUpTime(&Now);
for (idx = 0; idx < CLIWDS_HASH_TAB_SIZE; idx++)
{
pCliWdsEntry = (PCLIWDS_PROXY_ENTRY)(pAd->ApCfg.CliWdsProxyTab[idx].pHead);
while(pCliWdsEntry)
{
PCLIWDS_PROXY_ENTRY pCliWdsEntryNext = pCliWdsEntry->pNext;
if (RTMP_TIME_AFTER(Now, pCliWdsEntry->LastRefTime + (CLI_WDS_ENTRY_AGEOUT * OS_HZ / 1000)))
{
delEntryList(&pAd->ApCfg.CliWdsProxyTab[idx], (PLIST_ENTRY)pCliWdsEntry);
CliWdsEntyFree(pAd, pCliWdsEntry);
}
pCliWdsEntry = pCliWdsEntryNext;
}
}
return;
}
#endif /* CLIENT_WDS */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,169 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2006, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
cmm_cmd.c
Abstract:
All command related API.
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Name Date Modification logs
Paul Lin 06-25-2004 created
*/
#include "rt_config.h"
/*
========================================================================
Routine Description:
Arguments:
Return Value:
IRQL =
Note:
========================================================================
*/
VOID RTInitializeCmdQ(
IN PCmdQ cmdq)
{
cmdq->head = NULL;
cmdq->tail = NULL;
cmdq->size = 0;
cmdq->CmdQState = RTMP_TASK_STAT_INITED;
}
/*
========================================================================
Routine Description:
Arguments:
Return Value:
IRQL =
Note:
========================================================================
*/
VOID RTThreadDequeueCmd(
IN PCmdQ cmdq,
OUT PCmdQElmt *pcmdqelmt)
{
*pcmdqelmt = cmdq->head;
if (*pcmdqelmt != NULL)
{
cmdq->head = cmdq->head->next;
cmdq->size--;
if (cmdq->size == 0)
cmdq->tail = NULL;
}
}
/*
========================================================================
Routine Description:
Arguments:
Return Value:
IRQL =
Note:
========================================================================
*/
NDIS_STATUS RTEnqueueInternalCmd(
IN PRTMP_ADAPTER pAd,
IN NDIS_OID Oid,
IN PVOID pInformationBuffer,
IN UINT32 InformationBufferLength)
{
NDIS_STATUS status;
PCmdQElmt cmdqelmt = NULL;
status = os_alloc_mem(pAd, (PUCHAR *)&cmdqelmt, sizeof(CmdQElmt));
if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt == NULL))
return (NDIS_STATUS_RESOURCES);
NdisZeroMemory(cmdqelmt, sizeof(CmdQElmt));
if(InformationBufferLength > 0)
{
status = os_alloc_mem(pAd, (PUCHAR *)&cmdqelmt->buffer, InformationBufferLength);
if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt->buffer == NULL))
{
os_free_mem(pAd, cmdqelmt);
return (NDIS_STATUS_RESOURCES);
}
else
{
NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength);
cmdqelmt->bufferlength = InformationBufferLength;
}
}
else
{
cmdqelmt->buffer = NULL;
cmdqelmt->bufferlength = 0;
}
cmdqelmt->command = Oid;
cmdqelmt->CmdFromNdis = FALSE;
if (cmdqelmt != NULL)
{
NdisAcquireSpinLock(&pAd->CmdQLock);
if (pAd->CmdQ.CmdQState & RTMP_TASK_CAN_DO_INSERT)
{
EnqueueCmd((&pAd->CmdQ), cmdqelmt);
status = NDIS_STATUS_SUCCESS;
}
else
{
status = NDIS_STATUS_FAILURE;
}
NdisReleaseSpinLock(&pAd->CmdQLock);
if (status == NDIS_STATUS_FAILURE)
{
if (cmdqelmt->buffer)
os_free_mem(pAd, cmdqelmt->buffer);
os_free_mem(pAd, cmdqelmt);
}
else
RTCMDUp(&pAd->cmdQTask);
}
return(NDIS_STATUS_SUCCESS);
}

View File

@ -0,0 +1,920 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
cmm_cs.c
Abstract:
Carrier Sensing related functions
Revision History:
Who When What
---------------------------------------------------------------------
*/
#include "rt_config.h"
#ifdef CARRIER_DETECTION_SUPPORT
static ULONG time[20];
static ULONG idle[20];
static ULONG busy[20];
static ULONG cd_idx=0;
static void ToneRadarProgram(PRTMP_ADAPTER pAd);
#ifdef CONFIG_AP_SUPPORT
static inline VOID CarrierDetectionResetStatus(PRTMP_ADAPTER pAd)
{
if(pAd->chipCap.carrier_func == TONE_RADAR_V3)
{
RTMP_BBP_IO_WRITE32(pAd, TR_R1, 0x3);
}
#ifdef RTMP_BBP
else
{
RTMP_CARRIER_IO_WRITE8(pAd, 1, 1);
}
#endif /* RTMP_BBP */
}
static inline VOID CarrierDetectionStatusGet(PRTMP_ADAPTER pAd,
PUINT8 pStatus)
{
*pStatus = 0;
if(pAd->chipCap.carrier_func == TONE_RADAR_V3)
{
UINT32 mac_value = 0;
RTMP_BBP_IO_READ32(pAd, TR_R1, &mac_value);
*pStatus = (UINT8) mac_value;
}
#ifdef RTMP_BBP
else
{
RTMP_CARRIER_IO_READ8(pAd, 1, pStatus);
}
#endif /* RTMP_BBP */
}
static inline VOID CarrierDetectionEnable(PRTMP_ADAPTER pAd,
BOOLEAN bEnable)
{
if(pAd->chipCap.carrier_func == TONE_RADAR_V3)
{
RTMP_BBP_IO_WRITE32(pAd, TR_R0, bEnable);
}
#ifdef RTMP_BBP
else
{
RTMP_CARRIER_IO_WRITE8(pAd, 0, bEnable);
}
#endif /* RTMP_BBP */
}
/*
==========================================================================
Description:
Check current CS state, indicating Silient state (carrier exist) or not
Arguments:
pAd Pointer to our adapter
Return Value:
TRUE if the current state is SILENT state, FALSE other wise
Note:
==========================================================================
*/
INT isCarrierDetectExist(
IN PRTMP_ADAPTER pAd)
{
if (pAd->CommonCfg.CarrierDetect.CD_State == CD_SILENCE)
return TRUE;
else
return FALSE;
}
/*
==========================================================================
Description:
Enable or Disable Carrier Detection feature (AP ioctl).
Arguments:
pAd Pointer to our adapter
arg Pointer to the ioctl argument
Return Value:
None
Note:
Usage:
1.) iwpriv ra0 set CarrierDetect=[1/0]
==========================================================================
*/
INT Set_CarrierDetect_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
UCHAR apidx = pObj->ioctl_if;
UINT Enable;
if (apidx != MAIN_MBSSID)
return FALSE;
Enable = (UINT) simple_strtol(arg, 0, 10);
pAd->CommonCfg.CarrierDetect.Enable = (BOOLEAN)(Enable == 0 ? FALSE : TRUE);
RTMP_CHIP_RADAR_GLRT_COMPENSATE(pAd);
RTMP_CHIP_CCK_MRC_STATUS_CTRL(pAd);
if (pAd->CommonCfg.CarrierDetect.Enable == TRUE)
CarrierDetectionStart(pAd);
else
CarrierDetectionStop(pAd);
DBGPRINT(RT_DEBUG_TRACE, ("%s:: %s\n", __FUNCTION__,
pAd->CommonCfg.CarrierDetect.Enable == TRUE ? "Enable Carrier Detection":"Disable Carrier Detection"));
return TRUE;
}
#endif /* CONFIG_AP_SUPPORT */
/*
==========================================================================
Description:
When h/w interrupt is not available for CS, this function monitor necessary parameters that determine the CS
state periodically. (every 100ms)
Arguments:
pAd Pointer to our adapter
Return Value:
None
Note:
==========================================================================
*/
VOID CarrierDetectionPeriodicStateCtrl(
IN PRTMP_ADAPTER pAd)
{
PCARRIER_DETECTION_STRUCT pCarrierDetect = &pAd->CommonCfg.CarrierDetect;
CD_STATE *pCD_State = &pCarrierDetect->CD_State;
ULONG *pOneSecIntCount = &pCarrierDetect->OneSecIntCount;
#ifdef RALINK_ATE
/* Nothing to do in ATE mode */
if (ATE_ON(pAd))
return;
#endif /* RALINK_ATE */
if (pCarrierDetect->bCsInit == FALSE)
return;
if (pAd->chipCap.carrier_func == TONE_RADAR_V3)
{
UINT8 TrStatus = 0;
CarrierDetectionStatusGet(pAd, &TrStatus);
if (TrStatus)
{
if (*pCD_State == CD_NORMAL &&
(--pCarrierDetect->recheck) == 0)
{
DBGPRINT(RT_DEBUG_OFF,
("Carrier Detected ! (TrStatus = 0x%x)\n", TrStatus));
*pCD_State = CD_SILENCE;
/* stop all TX actions including Beacon sending.*/
AsicDisableSync(pAd);
}
else if (*pCD_State == CD_SILENCE)
{
*pOneSecIntCount = pCarrierDetect->CarrierGoneThreshold;
}
CarrierDetectionResetStatus(pAd);
}
else
{
pCarrierDetect->recheck = pCarrierDetect->recheck1;
*pOneSecIntCount = 0;
}
/*CarrierDetectionResetStatus(pAd);*/
}
#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT
if (pAd->chipCap.carrier_func == TONE_RADAR_V2)
{
CARRIER_DETECT_PARAM CarrDetectParam;
/* tell firmware to prepare Recheck and RadarToneCount */
AsicSendCommandToMcu(pAd, CD_CHECKOUT_MCU_CMD, 0xff, 0x00, 0x00, FALSE);
/* Debug */
if (pAd->CommonCfg.CarrierDetect.Debug == RT_DEBUG_TRACE)
{
CARRIER_DETECT_DEBUG CarrDetectDebug;
RTUSBMultiRead(pAd, 0x4CB0, (PUCHAR) &CarrDetectDebug, sizeof(CarrDetectDebug));
printk("delta_div = 0x%02X, rRadarToneCount = %u, Recheck = %u, Criteria = %u, Threshold = 0x%08X, VGA_Mask = 0x%04X\n",
CarrDetectDebug.delta_div,
CarrDetectDebug.RadarToneCount,
CarrDetectDebug.ReCheck,
CarrDetectDebug.Criteria << 6, /* ms -> 16us*/
CarrDetectDebug.Threshold,
CarrDetectDebug.VGA_Mask);
}
RTUSBMultiRead(pAd, RADAR_TONE_COUNT, (PUCHAR) &CarrDetectParam, sizeof(CarrDetectParam));
switch(*pCD_State)
{
case CD_NORMAL:
if (CarrDetectParam.ReCheck == 0)
{
*pCD_State = CD_SILENCE;
if (pAd->CommonCfg.CarrierDetect.Debug != RT_DEBUG_TRACE)
{
DBGPRINT(RT_DEBUG_TRACE, ("Carrier Detected\n"));
/* stop all TX actions including Beacon sending.*/
AsicDisableSync(pAd);
}
else
printk("Carrier Detected\n");
}
break;
case CD_SILENCE:
*pOneSecIntCount += CarrDetectParam.RadarToneCount;
break;
default:
break;
}
}
#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */
}
/*
==========================================================================
Description:
When there is no f/w taking care of CS operation, this function depends on h/w interrupts for every possible carrier
tone to judge the CS state
Arguments:
pAd Pointer to our adapter
Return Value:
None
Note:
==========================================================================
*/
VOID RTMPHandleRadarInterrupt(PRTMP_ADAPTER pAd)
{
UINT32 value, delta;
UCHAR bbp=0;
PCARRIER_DETECTION_STRUCT pCarrierDetect = &pAd->CommonCfg.CarrierDetect;
if (pAd->chipCap.carrier_func > TONE_RADAR_V2)
return;
DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandleRadarInterrupt()\n"));
RTMP_IO_READ32(pAd, PBF_LIFE_TIMER, &value);
RTMP_IO_READ32(pAd, CH_IDLE_STA, &pCarrierDetect->idle_time);
RTMP_IO_READ32(pAd, CH_BUSY_STA, &pCarrierDetect->busy_time);
delta = (value >> 4) - pCarrierDetect->TimeStamp;
pCarrierDetect->TimeStamp = value >> 4;
pCarrierDetect->OneSecIntCount++;
if(pAd->chipCap.carrier_func==TONE_RADAR_V2)
{
#ifdef RTMP_BBP
CarrierDetectionStatusGet(pAd, &bbp);
if (!(bbp & 0x1))
return;
else
#endif /* RTMP_BBP */
{
UINT32 RadarInt = 0;
#ifdef RLT_MAC
if (pAd->chipCap.hif_type == HIF_RLT)
RadarInt = RLT_RadarInt;
#endif /* RLT_MAC*/
#ifdef RTMP_MAC
if (pAd->chipCap.hif_type == HIF_RTMP)
RadarInt = RTMP_RadarInt;
#endif /* RTMP_MAC */
/* Disable carrier detection and clear the status bit*/
CarrierDetectionEnable(pAd, 0);
CarrierDetectionResetStatus(pAd);
/* Clear interrupt */
RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, RadarInt);
}
}
if (pCarrierDetect->Debug)
{
if (cd_idx < 20)
{
time[cd_idx] = delta;
idle[cd_idx] = pCarrierDetect->idle_time;
busy[cd_idx] = pCarrierDetect->busy_time;
cd_idx++;
}
else
{
int i;
pCarrierDetect->Debug = 0;
for (i = 0; i < 20; i++)
{
printk("%3d %4ld %ld %ld\n", i, time[i], idle[i], busy[i]);
}
cd_idx = 0;
}
}
if (pCarrierDetect->CD_State == CD_NORMAL)
{
if ((delta < pCarrierDetect->criteria) && (pCarrierDetect->recheck))
pCarrierDetect->recheck --;
else
pCarrierDetect->recheck = pCarrierDetect->recheck1;
if (pCarrierDetect->recheck == 0)
{
/* declare carrier sense*/
pCarrierDetect->CD_State = CD_SILENCE;
if (pCarrierDetect->Debug != RT_DEBUG_TRACE)
{
DBGPRINT(RT_DEBUG_TRACE, ("Carrier Detected\n"));
/* stop all TX actions including Beacon sending.*/
AsicDisableSync(pAd);
}
else
{
printk("Carrier Detected\n");
}
}
}
if(pAd->chipCap.carrier_func == TONE_RADAR_V2)
{
CarrierDetectionStatusGet(pAd, &bbp);
if (bbp & 0x1)
{
DBGPRINT(RT_DEBUG_ERROR, ("CS bit not cleared!!!\n"));
CarrierDetectionResetStatus(pAd);
}
/* re-enable carrier detection */
CarrierDetectionEnable(pAd, 1);
}
else if(pAd->chipCap.carrier_func == TONE_RADAR_V1 &&
pCarrierDetect->Enable)
{
ToneRadarProgram(pAd);
}
}
/*
==========================================================================
Description:
Reset CS state to NORMAL state.
Arguments:
pAd Pointer to our adapter
Return Value:
None
Note:
==========================================================================
*/
INT CarrierDetectReset(
IN PRTMP_ADAPTER pAd)
{
pAd->CommonCfg.CarrierDetect.CD_State = CD_NORMAL;
return 0;
}
/*
==========================================================================
Description:
Criteria in CS is a timing difference threshold for a pair of carrier tones. This function is a ioctl uesed to adjust the
Criteria. (unit: 16us)
Arguments:
pAd Pointer to our adapter
arg Pointer to the ioctl argument
Return Value:
None
Note:
==========================================================================
*/
INT Set_CarrierCriteria_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
UINT32 Value;
Value = simple_strtol(arg, 0, 10);
pAd->CommonCfg.CarrierDetect.criteria = Value;
#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT
{
USHORT sVal = (USHORT) (Value >> 6); /* convert unit from 16us to ms:(2^4 /2^10) */
RTUSBMultiWrite(pAd, CD_CRITERIA, (PUCHAR) &sVal, 2, FALSE);
/* send enable cmd to mcu to take effect */
AsicSendCommandToMcu(pAd, CD_ONOFF_MCU_CMD, 0xff, 0x01, 0x00, FALSE);
}
#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */
return TRUE;
}
/*
==========================================================================
Description:
ReCheck in CS is a value indicating how many continuous incoming carrier tones is enough us to announce that there
is carrier tone (and hence enter SILENT state). This function is a ioctl uesed to adjust the ReCheck value.
Arguments:
pAd Pointer to our adapter
arg Pointer to the ioctl argument
Return Value:
None
Note:
==========================================================================
*/
INT Set_CarrierReCheck_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
pAd->CommonCfg.CarrierDetect.recheck1 = simple_strtol(arg, 0, 10);
DBGPRINT(RT_DEBUG_TRACE, ("Set Recheck = %u\n", pAd->CommonCfg.CarrierDetect.recheck1));
#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT
RTMP_IO_WRITE8(pAd, CD_CHECK_COUNT, pAd->CommonCfg.CarrierDetect.recheck1);
/* send enable cmd to mcu to take effect */
AsicSendCommandToMcu(pAd, CD_ONOFF_MCU_CMD, 0xff, 0x01, 0x00, FALSE);
#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */
return TRUE;
}
/*
==========================================================================
Description:
CarrierGoneThreshold is used to determine whether we should leave SILENT state. When the number of carrier
tones in a certain period of time is less than CarrierGoneThreshold, we should return to NORMAL state. This function
is a ioctl uesed to adjust the CarrierGoneThreshold.
Arguments:
pAd Pointer to our adapter
arg Pointer to the ioctl argument
Return Value:
None
Note:
==========================================================================
*/
INT Set_CarrierGoneThreshold_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
pAd->CommonCfg.CarrierDetect.CarrierGoneThreshold = simple_strtol(arg, 0, 10);
DBGPRINT(RT_DEBUG_TRACE, ("Set CarrierGoneThreshold = %u\n", pAd->CommonCfg.CarrierDetect.CarrierGoneThreshold));
return TRUE;
}
/*
==========================================================================
Description:
Setting up the carrier debug level. set 0 means to turning off the carrier debug
Arguments:
pAd Pointer to our adapter
arg Pointer to the ioctl argument
Return Value:
None
Note:
==========================================================================
*/
INT Set_CarrierDebug_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
pAd->CommonCfg.CarrierDetect.Debug = simple_strtol(arg, 0, 10);
printk("pAd->CommonCfg.CarrierDetect.Debug = %ld\n", pAd->CommonCfg.CarrierDetect.Debug);
return TRUE;
}
/*
==========================================================================
Description:
Delta control the delay line characteristic of the cross correlation energy calculation.
This function is a ioctl uesed to adjust the Delta value.
Arguments:
pAd Pointer to our adapter
arg Pointer to the ioctl argument
Return Value:
None
Note:
==========================================================================
*/
INT Set_CarrierDelta_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
pAd->CommonCfg.CarrierDetect.delta = simple_strtol(arg, 0, 10);
printk("Delta = %d\n", pAd->CommonCfg.CarrierDetect.delta);
CarrierDetectionStart(pAd);
return TRUE;
}
/*
==========================================================================
Description:
To set ON/OFF of the "Not Divide Flag"
Arguments:
pAd Pointer to our adapter
arg Pointer to the ioctl argument
Return Value:
None
Note:
==========================================================================
*/
INT Set_CarrierDivFlag_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
pAd->CommonCfg.CarrierDetect.div_flag = simple_strtol(arg, 0, 10);
printk("DivFlag = %d\n", pAd->CommonCfg.CarrierDetect.div_flag);
CarrierDetectionStart(pAd);
return TRUE;
}
/*
==========================================================================
Description:
Carrier Threshold is the energy threshold for h/w to determine a carrier tone or not.
This function is a ioctl uesed to adjust the Threshold value.
Arguments:
pAd Pointer to our adapter
arg Pointer to the ioctl argument
Return Value:
None
Note:
==========================================================================
*/
INT Set_CarrierThrd_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
pAd->CommonCfg.CarrierDetect.threshold = simple_strtol(arg, 0, 10);
printk("CarrThrd = %d(0x%x)\n", pAd->CommonCfg.CarrierDetect.threshold, pAd->CommonCfg.CarrierDetect.threshold);
CarrierDetectionStart(pAd);
return TRUE;
}
/*
==========================================================================
Description:
Carrier SymRund is the number of round bits in Radar Symmetric Round Bits Option.
This function is a ioctl uesed to adjust the SymRund. (unit: bit)
Arguments:
pAd Pointer to our adapter
arg Pointer to the ioctl argument
Return Value:
None
Note:
==========================================================================
*/
INT Set_CarrierSymRund_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
pAd->CommonCfg.CarrierDetect.SymRund= simple_strtol(arg, 0, 10);
printk("SymRund = %d\n", pAd->CommonCfg.CarrierDetect.SymRund);
CarrierDetectionStart(pAd);
return TRUE;
}
/*
==========================================================================
Description:
Carrier Masks are used to prevent false trigger while doing Rx_PE, Packet_End, and AGC tuning.
This function is a ioctl uesed to adjust these three mask. (unit: 100ns)
Arguments:
pAd Pointer to our adapter
arg Pointer to the ioctl argument
Return Value:
None
Note:
==========================================================================
*/
INT Set_CarrierMask_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
pAd->CommonCfg.CarrierDetect.VGA_Mask = simple_strtol(arg, 0, 10);
pAd->CommonCfg.CarrierDetect.Packet_End_Mask = simple_strtol(arg, 0, 10);
pAd->CommonCfg.CarrierDetect.Rx_PE_Mask = simple_strtol(arg, 0, 10);
printk("CarrMask = %u(%x)\n", pAd->CommonCfg.CarrierDetect.VGA_Mask, pAd->CommonCfg.CarrierDetect.VGA_Mask);
CarrierDetectionStart(pAd);
return TRUE;
}
/*
==========================================================================
Description:
Initialize CS parameters.
Arguments:
pAd Pointer to our adapter
Return Value:
None
Note:
==========================================================================
*/
VOID CSInit(
IN PRTMP_ADAPTER pAd)
{
PCARRIER_DETECTION_STRUCT pCarrierDetect = &pAd->CommonCfg.CarrierDetect;
pCarrierDetect->TimeStamp = 0;
pCarrierDetect->recheck = pCarrierDetect->recheck1;
pCarrierDetect->OneSecIntCount = 0;
pCarrierDetect->bCsInit = FALSE;
}
/*
==========================================================================
Description:
To trigger CS start
Arguments:
pAd Pointer to our adapter
Return Value:
None
Note:
==========================================================================
*/
VOID CarrierDetectionStart(PRTMP_ADAPTER pAd)
{
/*ULONG Value;*/
/* Enable Bandwidth usage monitor*/
DBGPRINT(RT_DEBUG_TRACE, ("CarrierDetectionStart\n"));
/*RTMP_IO_READ32(pAd, CH_TIME_CFG, &Value);*/
/*RTMP_IO_WRITE32(pAd, CH_TIME_CFG, Value | 0x1f); */
/* Init Carrier Detect*/
if (pAd->CommonCfg.CarrierDetect.Enable)
{
CSInit(pAd);
ToneRadarProgram(pAd);
#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT
{
USHORT criteria = (USHORT) (pAd->CommonCfg.CarrierDetect.criteria >> 6); /* convert unit from 16us to 1ms:(2^4 /2^10) */
RTUSBMultiWrite(pAd, CD_CRITERIA, (PUCHAR) &criteria, 2, FALSE);
RTMP_IO_WRITE8(pAd, CD_CHECK_COUNT, pAd->CommonCfg.CarrierDetect.recheck1);
AsicSendCommandToMcu(pAd, CD_ONOFF_MCU_CMD, 0xff, 0x01, 0x00, FALSE);
}
#else
#ifndef MT76x2
/* trun on interrupt polling for pcie device */
if (pAd->infType == RTMP_DEV_INF_PCIE &&
pAd->chipCap.carrier_func == TONE_RADAR_V2)
{
AsicSendCommandToMcu(pAd, CD_INT_POLLING_CMD, 0xff, 0x01, 0x00, FALSE);
}
#endif /* MT76x2 */
#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */
pAd->CommonCfg.CarrierDetect.bCsInit = TRUE;
}
}
/*
==========================================================================
Description:
To stop CS
Arguments:
pAd Pointer to our adapter
Return Value:
None
Note:
==========================================================================
*/
VOID CarrierDetectionStop(IN PRTMP_ADAPTER pAd)
{
CarrierDetectReset(pAd);
CarrierDetectionEnable(pAd, 0);
#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT
/* Stop firmware CS action */
AsicSendCommandToMcu(pAd, CD_ONOFF_MCU_CMD, 0xff, 0x00, 0x00, FALSE);
#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */
if (pAd->chipCap.carrier_func == TONE_RADAR_V3
#ifdef DFS_SUPPORT
&& pAd->CommonCfg.RadarDetect.bDfsInit == FALSE
#endif
)
{
RTMP_IO_WRITE32(pAd, 0x212C, 0x00);
}
return;
}
/*
==========================================================================
Description:
To program CS related BBP registers (CS initialization)
Arguments:
pAd Pointer to our adapter
Return Value:
None
Note:
==========================================================================
*/
static VOID ToneRadarProgram(PRTMP_ADAPTER pAd)
{
ULONG threshold;
/* if wireless mode is 20Mhz mode, then the threshold should div by 2 */
if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_20)
threshold = pAd->CommonCfg.CarrierDetect.threshold >> 1;
else
threshold = pAd->CommonCfg.CarrierDetect.threshold;
/* Call ToneRadarProgram_v1/ToneRadarProgram_v2*/
RTMP_CHIP_CARRIER_PROGRAM(pAd, threshold);
}
#ifdef RTMP_BBP
/*
==========================================================================
Description:
To program CS v1 related BBP registers (CS initialization)
Arguments:
pAd Pointer to our adapter
Return Value:
None
Note:
==========================================================================
*/
VOID ToneRadarProgram_v1(PRTMP_ADAPTER pAd, ULONG threshold)
{
UCHAR bbp;
DBGPRINT(RT_DEBUG_TRACE, ("ToneRadarProgram v1\n"));
/* programe delta delay & division bit*/
BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R184, 0xf0);
bbp = pAd->CommonCfg.CarrierDetect.delta << 4;
bbp |= (pAd->CommonCfg.CarrierDetect.div_flag & 0x1) << 3;
BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R185, bbp);
/* program threshold*/
BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R184, 0x34);
BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R185, (threshold & 0xff000000) >> 24);
BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R184, 0x24);
BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R185, (threshold & 0xff0000) >> 16);
BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R184, 0x14);
BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R185, (threshold & 0xff00) >> 8);
BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R184, 0x04);
BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R185, threshold & 0xff);
/* ToneRadarEnable v1 */
BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R184, 0x05);
}
/*
==========================================================================
Description:
To program CS v2 related BBP registers (CS initialization)
Arguments:
pAd Pointer to our adapter
Return Value:
None
Note:
==========================================================================
*/
VOID ToneRadarProgram_v2(PRTMP_ADAPTER pAd, ULONG threshold)
{
UCHAR bbp;
/* programe delta delay & division bit*/
DBGPRINT(RT_DEBUG_TRACE, ("ToneRadarProgram v2\n"));
bbp = pAd->CommonCfg.CarrierDetect.delta | \
((pAd->CommonCfg.CarrierDetect.SymRund & 0x3) << 4) | \
((pAd->CommonCfg.CarrierDetect.div_flag & 0x1) << 6) | \
0x80; /* Full 40MHz Detection Mode */
RTMP_CARRIER_IO_WRITE8(pAd, 5, bbp);
/* program *_mask*/
RTMP_CARRIER_IO_WRITE8(pAd, 2, pAd->CommonCfg.CarrierDetect.VGA_Mask);
RTMP_CARRIER_IO_WRITE8(pAd, 3, pAd->CommonCfg.CarrierDetect.Packet_End_Mask);
RTMP_CARRIER_IO_WRITE8(pAd, 4, pAd->CommonCfg.CarrierDetect.Rx_PE_Mask);
/* program threshold*/
RTMP_CARRIER_IO_WRITE8(pAd, 6, threshold & 0xff);
RTMP_CARRIER_IO_WRITE8(pAd, 7, (threshold & 0xff00) >> 8);
RTMP_CARRIER_IO_WRITE8(pAd, 8, (threshold & 0xff0000) >> 16);
RTMP_CARRIER_IO_WRITE8(pAd, 9, (threshold & 0xff000000) >> 24);
/* ToneRadarEnable v2 */
CarrierDetectionEnable(pAd, 1);
}
#endif /* RTMP_BBP */
/*
==========================================================================
Description:
To program CS v3 related BBP registers (CS initialization)
Arguments:
pAd Pointer to our adapter
Return Value:
None
Note:
==========================================================================
*/
VOID ToneRadarProgram_v3(PRTMP_ADAPTER pAd, ULONG threshold)
{
/*
Carrier Sense (Tone Radar) BBP initialization
(MT7650 Carrier sense programming guide_v1_20120824.docx)
*/
DBGPRINT(RT_DEBUG_TRACE, ("ToneRadarProgram v3\n"));
CarrierDetectionEnable(pAd, 0);
RTMP_BBP_IO_WRITE32(pAd, TR_R2, 0x002d002d);
RTMP_BBP_IO_WRITE32(pAd, TR_R3, 0x0003002d);
RTMP_BBP_IO_WRITE32(pAd, TR_R5, 0x80000000);
RTMP_BBP_IO_WRITE32(pAd, TR_R6, 0x80100000);
CarrierDetectionEnable(pAd, 1);
RTMP_IO_WRITE32(pAd, 0x212C, 0x0c350001);
}
#endif /* CARRIER_DETECTION_SUPPORT */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,482 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2007, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
cmm_mat.c
Abstract:
Support Mac Address Translation function.
Note:
MAC Address Translation(MAT) engine subroutines, we should just take care
packet to bridge.
Revision History:
Who When What
-------------- ---------- ----------------------------------------------
Shiang 02-26-2007 Init version
*/
#ifdef MAT_SUPPORT
#include "rt_config.h"
extern MATProtoOps MATProtoIPHandle;
extern MATProtoOps MATProtoARPHandle;
extern MATProtoOps MATProtoPPPoEDisHandle;
extern MATProtoOps MATProtoPPPoESesHandle;
extern MATProtoOps MATProtoIPv6Handle;
extern UCHAR SNAP_802_1H[];
extern UCHAR SNAP_BRIDGE_TUNNEL[];
#define MAX_MAT_NODE_ENTRY_NUM 128 /* We support maximum 128 node entry for our system */
#define MAT_NODE_ENTRY_SIZE 40 /*28 // bytes //change to 40 for IPv6Mac Table */
typedef struct _MATNodeEntry
{
UCHAR data[MAT_NODE_ENTRY_SIZE];
struct _MATNodeEntry *next;
}MATNodeEntry, *PMATNodeEntry;
#ifdef KMALLOC_BATCH
/*static MATNodeEntry *MATNodeEntryPoll = NULL; */
#endif
static MATProtoTable MATProtoTb[]=
{
{ETH_P_IP, &MATProtoIPHandle}, /* IP handler */
{ETH_P_ARP, &MATProtoARPHandle}, /* ARP handler */
{ETH_P_PPP_DISC, &MATProtoPPPoEDisHandle}, /* PPPoE discovery stage handler */
{ETH_P_PPP_SES, &MATProtoPPPoESesHandle}, /* PPPoE session stage handler */
{ETH_P_IPV6, &MATProtoIPv6Handle}, /* IPv6 handler */
};
#define MAX_MAT_SUPPORT_PROTO_NUM (sizeof(MATProtoTb)/sizeof(MATProtoTable))
/* --------------------------------- Public Function-------------------------------- */
NDIS_STATUS MATDBEntryFree(
IN MAT_STRUCT *pMatStruct,
IN PUCHAR NodeEntry)
{
#ifdef KMALLOC_BATCH
MATNodeEntry *pPtr, *pMATNodeEntryPoll;
pMATNodeEntryPoll = (MATNodeEntry *)pAd->MatCfg.MATNodeEntryPoll;
pPtr = (MATNodeEntry *)NodeEntry;
NdisZeroMemory(pPtr, sizeof(MATNodeEntry));
if (pMATNodeEntryPoll->next)
{
pPtr->next = pMATNodeEntryPoll->next;
pMATNodeEntryPoll->next = pPtr;
} else {
pMATNodeEntryPoll->next = pPtr;
}
#else
os_free_mem(NULL, NodeEntry);
NodeEntry = NULL;
#endif
return TRUE;
}
PUCHAR MATDBEntryAlloc(IN MAT_STRUCT *pMatStruct, IN UINT32 size)
{
#ifdef KMALLOC_BATCH
MATNodeEntry *pPtr = NULL, *pMATNodeEntryPoll;
pMATNodeEntryPoll = (MATNodeEntry *)pMatStruct->pMATNodeEntryPoll;
if (pMATNodeEntryPoll->next)
{
pPtr = pMATNodeEntryPoll->next;
pMATNodeEntryPoll->next = pPtr->next;
}
#else
UCHAR *pPtr = NULL;
os_alloc_mem(NULL, (PUCHAR *)&pPtr, size);
/*pPtr = kmalloc(size, MEM_ALLOC_FLAG); */
#endif
return (PUCHAR)pPtr;
}
VOID dumpPkt(PUCHAR pHeader, int len)
{
int i;
PSTRING tmp;
tmp = (PSTRING)pHeader;
DBGPRINT(RT_DEBUG_OFF, ("--StartDump\n"));
for(i=0;i<len; i++)
{
if ( (i%16==0) && (i!=0))
DBGPRINT(RT_DEBUG_OFF, ("\n"));
DBGPRINT(RT_DEBUG_OFF, ("%02x ", tmp[i]& 0xff));
}
DBGPRINT(RT_DEBUG_OFF, ("\n--EndDump\n"));
return;
}
/*
========================================================================
Routine Description:
For each out-going packet, check the upper layer protocol type if need
to handled by our APCLI convert engine. If yes, call corresponding handler
to handle it.
Arguments:
pAd =>Pointer to our adapter
pPkt =>pointer to the 802.11 header of outgoing packet
ifIdx =>Interface Index want to dispatch to.
Return Value:
Success =>
TRUE
Mapped mac address if found, else return specific default mac address
depends on the upper layer protocol type.
Error =>
FALSE.
Note:
1.the pPktHdr must be a 802.3 packet.
2.Maybe we need a TxD arguments?
3.We check every packet here including group mac address becasue we need to
handle DHCP packet.
========================================================================
*/
PUCHAR MATEngineTxHandle(
IN PRTMP_ADAPTER pAd,
IN PNDIS_PACKET pPkt,
IN UINT ifIdx,
IN UCHAR OpMode)
{
PUCHAR pLayerHdr = NULL, pPktHdr = NULL, pMacAddr = NULL;
UINT16 protoType, protoType_ori;
INT i;
struct _MATProtoOps *pHandle = NULL;
PUCHAR retSkb = NULL;
BOOLEAN bVLANPkt = FALSE;
if(pAd->MatCfg.status != MAT_ENGINE_STAT_INITED)
return NULL;
pPktHdr = GET_OS_PKT_DATAPTR(pPkt);
if (!pPktHdr)
return NULL;
protoType_ori = get_unaligned((PUINT16)(pPktHdr + 12));
/* Get the upper layer protocol type of this 802.3 pkt. */
protoType = OS_NTOHS(protoType_ori);
/* handle 802.1q enabled packet. Skip the VLAN tag field to get the protocol type. */
if (protoType == 0x8100)
{
protoType_ori = get_unaligned((PUINT16)(pPktHdr + 12 + 4));
protoType = OS_NTOHS(protoType_ori);
bVLANPkt = TRUE;
}
/* For differnet protocol, dispatch to specific handler */
for (i=0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++)
{
if (protoType == MATProtoTb[i].protocol)
{
pHandle = MATProtoTb[i].pHandle; /* the pHandle must not be null! */
pLayerHdr = bVLANPkt ? (pPktHdr + MAT_VLAN_ETH_HDR_LEN) : (pPktHdr + MAT_ETHER_HDR_LEN);
#ifdef CONFIG_AP_SUPPORT
#ifdef APCLI_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
#ifdef MAC_REPEATER_SUPPORT
UCHAR tempIdx = ifIdx;
UCHAR CliIdx = 0xFF;
if (tempIdx >= 64)
{
CliIdx = ((tempIdx - 64) % 16);
tempIdx = ((tempIdx - 64) / 16);
pMacAddr = &pAd->ApCfg.ApCliTab[tempIdx].RepeaterCli[CliIdx].CurrentAddress[0];
}
else
#endif /* MAC_REPEATER_SUPPORT */
pMacAddr = &pAd->ApCfg.ApCliTab[ifIdx].wdev.if_addr[0];
}
#endif /* APCLI_SUPPORT */
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
#ifdef ETH_CONVERT_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
pMacAddr = &pAd->CurrentAddress[0];
#endif /* ETH_CONVERT_SUPPORT */
#endif /* CONFIG_STA_SUPPORT */
if (pHandle->tx!=NULL)
retSkb = pHandle->tx((PVOID)&pAd->MatCfg, RTPKT_TO_OSPKT(pPkt), pLayerHdr, pMacAddr);
return retSkb;
}
}
return retSkb;
}
/*
========================================================================
Routine Description:
Depends on the Received packet, check the upper layer protocol type
and search for specific mapping table to find out the real destination
MAC address.
Arguments:
pAd =>Pointer to our adapter
pPkt =>pointer to the 802.11 header of receviced packet
infIdx =>Interface Index want to dispatch to.
Return Value:
Success =>
Mapped mac address if found, else return specific default mac address
depends on the upper layer protocol type.
Error =>
NULL
Note:
========================================================================
*/
PUCHAR MATEngineRxHandle(
IN PRTMP_ADAPTER pAd,
IN PNDIS_PACKET pPkt,
IN UINT infIdx)
{
PUCHAR pMacAddr = NULL;
PUCHAR pLayerHdr = NULL, pPktHdr = NULL;
UINT16 protoType;
INT i =0;
struct _MATProtoOps *pHandle = NULL;
if(pAd->MatCfg.status != MAT_ENGINE_STAT_INITED)
return NULL;
pPktHdr = GET_OS_PKT_DATAPTR(pPkt);
if (!pPktHdr)
return NULL;
/* If it's a multicast/broadcast packet, we do nothing. */
if (IS_GROUP_MAC(pPktHdr))
return NULL;
/* Get the upper layer protocol type of this 802.3 pkt and dispatch to specific handler */
protoType = OS_NTOHS(get_unaligned((PUINT16)(pPktHdr + 12)));
for (i=0; i<MAX_MAT_SUPPORT_PROTO_NUM; i++)
{
if (protoType == MATProtoTb[i].protocol)
{
pHandle = MATProtoTb[i].pHandle; /* the pHandle must not be null! */
pLayerHdr = (pPktHdr + MAT_ETHER_HDR_LEN);
/* RTMP_SEM_LOCK(&MATDBLock); */
if(pHandle->rx!=NULL)
pMacAddr = pHandle->rx((PVOID)&pAd->MatCfg, RTPKT_TO_OSPKT(pPkt), pLayerHdr, NULL);
/* RTMP_SEM_UNLOCK(&MATDBLock); */
break;
}
}
if (pMacAddr)
NdisMoveMemory(pPktHdr, pMacAddr, MAC_ADDR_LEN);
return NULL;
}
BOOLEAN MATPktRxNeedConvert(
IN PRTMP_ADAPTER pAd,
IN PNET_DEV net_dev)
{
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
#ifdef APCLI_SUPPORT
int i = 0;
/* Check if the packet will be send to apcli interface. */
while(i<MAX_APCLI_NUM)
{
/*BSSID match the ApCliBssid ?(from a valid AP) */
if ((pAd->ApCfg.ApCliTab[i].Valid == TRUE)
&& (net_dev == pAd->ApCfg.ApCliTab[i].wdev.if_dev)
#ifdef MWDS
&& (pAd->ApCfg.ApCliTab[i].bEnableMWDS == FALSE)
#endif /* MWDS */
)
return TRUE;
i++;
}
#endif /* APCLI_SUPPORT */
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
#ifdef ETH_CONVERT_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
{
if (pAd->EthConvert.ECMode & ETH_CONVERT_MODE_DONGLE)
return TRUE;
}
#endif /* ETH_CONVERT_SUPPORT */
#endif /* CONFIG_STA_SUPPORT */
return FALSE;
}
NDIS_STATUS MATEngineExit(
IN RTMP_ADAPTER *pAd)
{
struct _MATProtoOps *pHandle = NULL;
int i;
if(pAd->MatCfg.status == MAT_ENGINE_STAT_EXITED)
return TRUE;
pAd->MatCfg.status = MAT_ENGINE_STAT_EXITED;
/* For each registered protocol, we call it's exit handler. */
for (i=0; i<MAX_MAT_SUPPORT_PROTO_NUM; i++)
{
pHandle = MATProtoTb[i].pHandle;
if (pHandle->exit!=NULL)
pHandle->exit(&pAd->MatCfg);
}
#ifdef KMALLOC_BATCH
/* Free the memory used to store node entries. */
if (pAd->MatCfg.pMATNodeEntryPoll)
{
os_free_mem(pAd, pAd->MatCfg.pMATNodeEntryPoll);
pAd->MatCfg.pMATNodeEntryPoll = NULL;
}
#endif
return TRUE;
}
NDIS_STATUS MATEngineInit(
IN RTMP_ADAPTER *pAd)
{
MATProtoOps *pHandle = NULL;
int i, status;
if(pAd->MatCfg.status == MAT_ENGINE_STAT_INITED)
return TRUE;
#ifdef KMALLOC_BATCH
/* Allocate memory for node entry, we totally allocate 128 entries and link them together. */
/* pAd->MatCfg.pMATNodeEntryPoll = kmalloc(sizeof(MATNodeEntry) * MAX_MAT_NODE_ENTRY_NUM, GFP_KERNEL); */
os_alloc_mem_suspend(NULL, (UCHAR **)&(pAd->MatCfg.pMATNodeEntryPoll), sizeof(MATNodeEntry) * MAX_MAT_NODE_ENTRY_NUM);
if (pAd->MatCfg.pMATNodeEntryPoll != NULL)
{
MATNodeEntry *pPtr=NULL;
NdisZeroMemory(pAd->MatCfg.pMATNodeEntryPoll, sizeof(MATNodeEntry) * MAX_MAT_NODE_ENTRY_NUM);
pPtr = pAd->MatCfg.pMATNodeEntryPoll;
for (i = 0; i < (MAX_MAT_NODE_ENTRY_NUM -1); i++)
{
pPtr->next = (MATNodeEntry *)(pPtr+1);
pPtr = pPtr->next;
}
pPtr->next = NULL;
} else {
return FALSE;
}
#endif
/* For each specific protocol, call it's init function. */
for (i = 0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++)
{
pHandle = MATProtoTb[i].pHandle;
ASSERT(pHandle);
if (pHandle->init != NULL)
{
status = pHandle->init(&pAd->MatCfg);
if (status == FALSE)
{
DBGPRINT(RT_DEBUG_ERROR, ("MATEngine Init Protocol (0x%x) failed, Stop the MAT Funciton initialization failed!\n", MATProtoTb[i].protocol));
goto init_failed;
}
DBGPRINT(RT_DEBUG_TRACE, ("MATEngine Init Protocol (0x%04x) success!\n", MATProtoTb[i].protocol));
}
}
NdisAllocateSpinLock(pAd, &pAd->MatCfg.MATDBLock);
#ifdef MAC_REPEATER_SUPPORT
pAd->MatCfg.bMACRepeaterEn = FALSE;
#endif /* MAC_REPEATER_SUPPORT */
pAd->MatCfg.pPriv = (VOID *)pAd;
pAd->MatCfg.status = MAT_ENGINE_STAT_INITED;
return TRUE;
init_failed:
/* For each specific protocol, call it's exit function. */
for (i = 0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++)
{
if ((pHandle = MATProtoTb[i].pHandle) != NULL)
{
if (pHandle->exit != NULL)
{
status = pHandle->exit(&pAd->MatCfg);
if (status == FALSE)
goto init_failed;
}
}
}
#ifdef KMALLOC_BATCH
if (pAd->MatCfg.pMATNodeEntryPoll)
os_free_mem(pAd, pAd->MatCfg.pMATNodeEntryPoll);
pAd->MatCfg.status = MAT_ENGINE_STAT_EXITED;
#endif /* KMALLOC_BATCH */
return FALSE;
}
#endif /* MAT_SUPPORT */

View File

@ -0,0 +1,833 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2007, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
cmm_mat_iparp.c
Abstract:
MAT convert engine subroutine for ip base protocols, currently now we
just handle IP/ARP protocols.
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Shiang 02/26/07 Init version
*/
#ifdef MAT_SUPPORT
#include "rt_config.h"
static NDIS_STATUS MATProto_IP_Init(MAT_STRUCT *pMatCfg);
static NDIS_STATUS MATProto_IP_Exit(MAT_STRUCT *pMatCfg);
static PUCHAR MATProto_IP_Rx(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pMacAddr);
static PUCHAR MATProto_IP_Tx(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pMacAddr);
static NDIS_STATUS MATProto_ARP_Init(MAT_STRUCT *pMatCfg);
static NDIS_STATUS MATProto_ARP_Exit(MAT_STRUCT *pMatCfg);
static PUCHAR MATProto_ARP_Rx(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pMacAddr);
static PUCHAR MATProto_ARP_Tx(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb,PUCHAR pLayerHdr, PUCHAR pMacAddr);
#define IPV4_ADDR_LEN 4
#define NEED_UPDATE_IPMAC_TB(Mac, IP) (IS_UCAST_MAC(Mac) && IS_GOOD_IP(IP))
typedef struct _IPMacMappingEntry
{
UINT ipAddr; /* In network order */
UCHAR macAddr[MAC_ADDR_LEN];
ULONG lastTime;
struct _IPMacMappingEntry *pNext;
}IPMacMappingEntry, *PIPMacMappingEntry;
typedef struct _IPMacMappingTable
{
BOOLEAN valid;
IPMacMappingEntry *hash[MAT_MAX_HASH_ENTRY_SUPPORT+1]; /*0~63 for specific station, 64 for broadcast MacAddress */
UCHAR curMcastAddr[MAC_ADDR_LEN]; /* The multicast mac addr for currecnt received packet destined to ipv4 multicast addr */
}IPMacMappingTable;
struct _MATProtoOps MATProtoIPHandle =
{
.init = MATProto_IP_Init,
.tx = MATProto_IP_Tx,
.rx = MATProto_IP_Rx,
.exit = MATProto_IP_Exit,
};
struct _MATProtoOps MATProtoARPHandle =
{
.init = MATProto_ARP_Init,
.tx = MATProto_ARP_Tx,
.rx = MATProto_ARP_Rx,
.exit =MATProto_ARP_Exit,
};
VOID dumpIPMacTb(
IN MAT_STRUCT *pMatCfg,
IN int index)
{
IPMacMappingTable *pIPMacTable;
IPMacMappingEntry *pHead;
int startIdx, endIdx;
if (pMatCfg->status == MAT_ENGINE_STAT_EXITED)
return;
pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
if (!pIPMacTable)
return;
if (!pIPMacTable->valid)
{
DBGPRINT(RT_DEBUG_OFF, ("%s():IPMacTable not init yet, so cannot do dump!\n", __FUNCTION__));
return;
}
if(index < 0)
{ /* dump all. */
startIdx = 0;
endIdx = MAT_MAX_HASH_ENTRY_SUPPORT;
}
else
{ /* dump specific hash index. */
startIdx = endIdx = index;
}
DBGPRINT(RT_DEBUG_OFF, ("%s():\n", __FUNCTION__));
for(; startIdx<= endIdx; startIdx++)
{
pHead = pIPMacTable->hash[startIdx];
while(pHead)
{
DBGPRINT(RT_DEBUG_OFF, ("IPMac[%d]:\n", startIdx));
DBGPRINT(RT_DEBUG_OFF, ("\t:IP=0x%x,Mac=%02x:%02x:%02x:%02x:%02x:%02x, lastTime=0x%lx, next=%p\n",
pHead->ipAddr, pHead->macAddr[0],pHead->macAddr[1],pHead->macAddr[2],
pHead->macAddr[3],pHead->macAddr[4],pHead->macAddr[5], pHead->lastTime,
pHead->pNext));
pHead = pHead->pNext;
}
}
DBGPRINT(RT_DEBUG_OFF, ("\t----EndOfDump!\n"));
}
static inline NDIS_STATUS getDstIPFromIpPkt(
IN PUCHAR pIpHdr,
IN UINT *dstIP)
{
if (!pIpHdr)
return FALSE;
NdisMoveMemory(dstIP, (pIpHdr + 16), 4); /*shift 16 for IP header len before DstIP. */
/* DBGPRINT(RT_DEBUG_TRACE, ("%s(): Get the dstIP=0x%x\n", __FUNCTION__, *dstIP)); */
return TRUE;
}
static inline NDIS_STATUS getSrcIPFromIpPkt(
IN PUCHAR pIpHdr,
IN UINT *pSrcIP)
{
if (!pIpHdr)
return FALSE;
NdisMoveMemory(pSrcIP, (pIpHdr + 12), 4); /*shift 12 for IP header len before DstIP. */
/* DBGPRINT(RT_DEBUG_TRACE, ("%s(): Get the srcIP=0x%x\n", __FUNCTION__, *pSrcIP)); */
return TRUE;
}
static NDIS_STATUS IPMacTableUpdate(
IN MAT_STRUCT *pMatCfg,
IN PUCHAR pMacAddr,
IN UINT ipAddr)
{
UINT hashIdx;
IPMacMappingTable *pIPMacTable;
IPMacMappingEntry *pEntry = NULL, *pPrev = NULL, *pNewEntry =NULL;
ULONG now;
pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
if (!pIPMacTable)
return FALSE;
if (!pIPMacTable->valid)
return FALSE;
hashIdx = MAT_IP_ADDR_HASH_INDEX(ipAddr);
pEntry = pPrev = pIPMacTable->hash[hashIdx];
while(pEntry)
{
NdisGetSystemUpTime(&now);
/* Find a existed IP-MAC Mapping entry */
if (ipAddr == pEntry->ipAddr)
{
/* DBGPRINT(RT_DEBUG_TRACE, ("%s(): Got the Mac(%02x:%02x:%02x:%02x:%02x:%02x) of mapped IP(%d.%d.%d.%d)\n",
__FUNCTION__, pEntry->macAddr[0],pEntry->macAddr[1],pEntry->macAddr[2], pEntry->macAddr[3],pEntry->macAddr[4],
pEntry->macAddr[5], (ipAddr>>24) & 0xff, (ipAddr>>16) & 0xff, (ipAddr>>8) & 0xff, ipAddr & 0xff));
*/
/* compare is useless. So we directly copy it into the entry. */
NdisMoveMemory(pEntry->macAddr, pMacAddr, 6);
pEntry->lastTime = now;
return TRUE;
}
else
{ /* handle the age-out situation */
/*if ((Now - pEntry->lastTime) > MAT_TB_ENTRY_AGEOUT_TIME) */
if (RTMP_TIME_AFTER(now, pEntry->lastTime + MAT_TB_ENTRY_AGEOUT_TIME))
{
/* Remove the aged entry */
if (pEntry == pIPMacTable->hash[hashIdx])
{
pIPMacTable->hash[hashIdx]= pEntry->pNext;
pPrev = pIPMacTable->hash[hashIdx];
}
else
{
pPrev->pNext = pEntry->pNext;
}
MATDBEntryFree(pMatCfg, (PUCHAR)pEntry);
pEntry = (pPrev == NULL ? NULL: pPrev->pNext);
pMatCfg->nodeCount--;
}
else
{
pPrev = pEntry;
pEntry = pEntry->pNext;
}
}
}
#ifdef ETH_CONVERT_SUPPORT
if (pMatCfg->nodeCount >= ETH_CONVERT_NODE_MAX)
return FALSE;
#endif /* ETH_CONVERT_SUPPORT */
/* Allocate a new IPMacMapping entry and insert into the hash */
pNewEntry = (IPMacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(IPMacMappingEntry));
if (pNewEntry != NULL)
{
pNewEntry->ipAddr = ipAddr;
NdisMoveMemory(pNewEntry->macAddr, pMacAddr, 6);
pNewEntry->pNext = NULL;
NdisGetSystemUpTime(&pNewEntry->lastTime);
if (pIPMacTable->hash[hashIdx] == NULL)
{ /* Hash list is empty, directly assign it. */
pIPMacTable->hash[hashIdx] = pNewEntry;
}
else
{
/* Ok, we insert the new entry into the root of hash[hashIdx] */
pNewEntry->pNext = pIPMacTable->hash[hashIdx];
pIPMacTable->hash[hashIdx] = pNewEntry;
}
/*dumpIPMacTb(pMatCfg, hashIdx); //for debug */
pMatCfg->nodeCount++;
return TRUE;
}
return FALSE;
}
static PUCHAR IPMacTableLookUp(
IN MAT_STRUCT *pMatCfg,
IN UINT ipAddr)
{
IPMacMappingTable *pIPMacTable;
UINT hashIdx, ip;
IPMacMappingEntry *pEntry = NULL;
PUCHAR pGroupMacAddr;
pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
if (!pIPMacTable)
return NULL;
if (!pIPMacTable->valid)
return NULL;
/*if multicast ip, need converting multicast group address to ethernet address. */
ip = ntohl(ipAddr);
if (IS_MULTICAST_IP(ip))
{
pGroupMacAddr = (PUCHAR)(&pIPMacTable->curMcastAddr);
ConvertMulticastIP2MAC((PUCHAR) &ipAddr, (UCHAR **)(&pGroupMacAddr), ETH_P_IP);
return pIPMacTable->curMcastAddr;
}
/* Use hash to find out the location of that entry and get the Mac address. */
hashIdx = MAT_IP_ADDR_HASH_INDEX(ipAddr);
/* spin_lock_irqsave(&IPMacTabLock, irqFlag); */
pEntry = pIPMacTable->hash[hashIdx];
while(pEntry)
{
if (pEntry->ipAddr == ipAddr)
{
/* DBGPRINT(RT_DEBUG_TRACE, ("%s(): dstMac=%02x:%02x:%02x:%02x:%02x:%02x for mapped dstIP(%d.%d.%d.%d)\n",
__FUNCTION__, pEntry->macAddr[0],pEntry->macAddr[1],pEntry->macAddr[2],
pEntry->macAddr[3],pEntry->macAddr[4],pEntry->macAddr[5],
(ipAddr>>24) & 0xff, (ipAddr>>16) & 0xff, (ipAddr>>8) & 0xff, ipAddr & 0xff));
*/
/*Update the lastTime to prevent the aging before pDA processed! */
NdisGetSystemUpTime(&pEntry->lastTime);
return pEntry->macAddr;
}
else
pEntry = pEntry->pNext;
}
/*
We didn't find any matched Mac address, our policy is treat it as
broadcast packet and send to all.
*/
return pIPMacTable->hash[IPMAC_TB_HASH_INDEX_OF_BCAST]->macAddr;
}
static NDIS_STATUS IPMacTable_RemoveAll(
IN MAT_STRUCT *pMatCfg)
{
IPMacMappingEntry *pEntry;
IPMacMappingTable *pIPMacTable;
INT i;
pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
if (!pIPMacTable)
return TRUE;
if (pIPMacTable->valid)
{
pIPMacTable->valid = FALSE;
for (i=0; i<IPMAC_TB_HASH_ENTRY_NUM; i++)
{
while((pEntry = pIPMacTable->hash[i]) != NULL)
{
pIPMacTable->hash[i] = pEntry->pNext;
MATDBEntryFree(pMatCfg, (PUCHAR)pEntry);
}
}
}
/* kfree(pIPMacTable); */
os_free_mem(NULL, pIPMacTable);
pMatCfg->MatTableSet.IPMacTable = NULL;
return TRUE;
}
static NDIS_STATUS IPMacTable_init(
IN MAT_STRUCT *pMatCfg)
{
IPMacMappingTable *pIPMacTable;
IPMacMappingEntry *pEntry = NULL;
if (pMatCfg->MatTableSet.IPMacTable != NULL)
{
pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
}
else
{
/* pMatCfg->MatTableSet.IPMacTable = kmalloc(sizeof(IPMacMappingTable), GFP_KERNEL); */
os_alloc_mem_suspend(NULL, (UCHAR **)&(pMatCfg->MatTableSet.IPMacTable), sizeof(IPMacMappingTable));
if (pMatCfg->MatTableSet.IPMacTable)
{
pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
NdisZeroMemory(pIPMacTable, sizeof(IPMacMappingTable));
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("IPMacTable_init(): Allocate memory for IPMacTable failed!\n"));
return FALSE;
}
}
if (pIPMacTable->valid == FALSE)
{
/*Set the last hash entry (hash[64]) as our default broadcast Mac address */
pEntry = (IPMacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(IPMacMappingEntry));
if (!pEntry)
{
DBGPRINT(RT_DEBUG_ERROR, ("IPMacTable_init(): Allocate memory for IPMacTable broadcast entry failed!\n"));
return FALSE;
}
/*pEntry->ipAddr = 0; */
NdisZeroMemory(pEntry, sizeof(IPMacMappingEntry));
NdisMoveMemory(&pEntry->macAddr[0], &BROADCAST_ADDR[0], 6);
pEntry->pNext = NULL;
pIPMacTable->hash[IPMAC_TB_HASH_INDEX_OF_BCAST] = pEntry;
pIPMacTable->valid = TRUE;
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("%s(): IPMacTable already inited!\n", __FUNCTION__));
}
return TRUE;
}
static NDIS_STATUS MATProto_ARP_Exit(
IN MAT_STRUCT *pMatCfg)
{
INT status;
status = IPMacTable_RemoveAll(pMatCfg);
return status;
}
static PUCHAR MATProto_ARP_Rx(
IN MAT_STRUCT *pMatCfg,
IN PNDIS_PACKET pSkb,
IN PUCHAR pLayerHdr,
IN PUCHAR pMacAddr)
{
PUCHAR pArpHdr = NULL, pRealMac = NULL;
PUCHAR tgtMac, tgtIP;
BOOLEAN isUcastMac, isGoodIP;
pArpHdr = pLayerHdr;
/*dumpPkt(RTPKT_TO_OSPKT(pSkb)->data, RTPKT_TO_OSPKT(pSkb)->len); */
/* We just take care about the target(Mac/IP address) fields. */
tgtMac = pArpHdr + 18;
tgtIP = tgtMac + 6;
/* isUcastMac = !(00:00:00:00:00:00|| mcastMac); */
isUcastMac = ((tgtMac[0]|tgtMac[1]|tgtMac[2]|tgtMac[3]|tgtMac[4]|tgtMac[5])!=0);
isUcastMac &= ((tgtMac[0] & 0x1)==0);
/* isGoodIP = ip address is not 0.0.0.0 */
isGoodIP = (*(UINT *)tgtIP != 0);
if (isUcastMac && isGoodIP)
pRealMac = IPMacTableLookUp(pMatCfg, *(UINT *)tgtIP);
/*
For need replaced mac, we need to replace the targetMAC as correct one to make
the real receiver can receive that.
*/
if (isUcastMac && pRealMac)
NdisMoveMemory(tgtMac, pRealMac, MAC_ADDR_LEN);
if (pRealMac == NULL)
pRealMac = &BROADCAST_ADDR[0];
/* pRealMac = pIPMacTable->hash[IPMAC_TB_HASH_INDEX_OF_BCAST]->macAddr; */
return pRealMac;
}
static PUCHAR MATProto_ARP_Tx(
IN MAT_STRUCT *pMatCfg,
IN PNDIS_PACKET pSkb,
IN PUCHAR pLayerHdr,
IN PUCHAR pMacAddr)
{
PUCHAR pSMac, pSIP;
BOOLEAN isUcastMac, isGoodIP;
NET_PRO_ARP_HDR *arpHdr;
PNDIS_PACKET newSkb = NULL;
arpHdr = (NET_PRO_ARP_HDR *)pLayerHdr;
/*
Check the arp header.
We just handle ether type hardware address and IPv4 internet
address type and opcode is ARP reuqest/response.
*/
if ((arpHdr->ar_hrd != OS_HTONS(ARPHRD_ETHER)) || (arpHdr->ar_pro != OS_HTONS(ETH_P_IP)) ||
(arpHdr->ar_op != OS_HTONS(ARPOP_REPLY) && arpHdr->ar_op != OS_HTONS(ARPOP_REQUEST)))
return NULL;
/* We just take care about the sender(Mac/IP address) fields. */
pSMac =(PUCHAR)(pLayerHdr + 8);
pSIP = (PUCHAR)(pSMac + MAC_ADDR_LEN);
isUcastMac = IS_UCAST_MAC(pSMac);
isGoodIP = IS_GOOD_IP(get_unaligned32((PUINT) pSIP));
/*
DBGPRINT(RT_DEBUG_TRACE,("%s(): ARP Pkt=>senderIP=%d.%d.%d.%d, senderMac=%02x:%02x:%02x:%02x:%02x:%02x\n",
__FUNCTION__, pSIP[0], pSIP[1], pSIP[2], pSIP[3],
pSMac[0],pSMac[1],pSMac[2],pSMac[3],pSMac[4],pSMac[5]));
*/
if (isUcastMac && isGoodIP)
IPMacTableUpdate(pMatCfg, pSMac, get_unaligned32((PUINT) pSIP));
/*
For outgoing unicast mac, we need to replace the senderMAC as ourself to make
the receiver can send to us.
*/
if (isUcastMac)
{
if(OS_PKT_CLONED(pSkb))
{
newSkb = (PNDIS_PACKET)OS_PKT_COPY(pSkb);
if(newSkb)
{
if (IS_VLAN_PACKET(GET_OS_PKT_DATAPTR(newSkb)))
pSMac = (PUCHAR)(GET_OS_PKT_DATAPTR(newSkb) + MAT_VLAN_ETH_HDR_LEN + 8);
else
pSMac = (PUCHAR)(GET_OS_PKT_DATAPTR(newSkb) + MAT_ETHER_HDR_LEN + 8);
}
}
ASSERT(pMacAddr);
NdisMoveMemory(pSMac, pMacAddr, MAC_ADDR_LEN);
}
return (PUCHAR)newSkb;
}
static NDIS_STATUS MATProto_ARP_Init(
IN MAT_STRUCT *pMatCfg)
{
BOOLEAN status = FALSE;
status = IPMacTable_init(pMatCfg);
return status;
}
static NDIS_STATUS MATProto_IP_Exit(
IN MAT_STRUCT *pMatCfg)
{
INT status;
status = IPMacTable_RemoveAll(pMatCfg);
return status;
}
static PUCHAR MATProto_IP_Rx(
IN MAT_STRUCT *pMatCfg,
IN PNDIS_PACKET pSkb,
IN PUCHAR pLayerHdr,
IN PUCHAR pDevMacAdr)
{
#ifdef MAC_REPEATER_SUPPORT
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) pMatCfg->pPriv;
#endif /* MAC_REPEATER_SUPPORT */
PUCHAR pMacAddr;
UINT dstIP;
/* Fetch the IP addres from the packet header. */
getDstIPFromIpPkt(pLayerHdr, &dstIP);
pMacAddr = IPMacTableLookUp(pMatCfg, dstIP);
#ifdef MAC_REPEATER_SUPPORT
if (pAd == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s():ERROR! pAd is null!\n", __FUNCTION__));
return pMacAddr;
}
if ((pAd->ApCfg.bMACRepeaterEn) && (pAd->ApCfg.MACRepeaterOuiMode != 1))
{
USHORT wcid = 0xFF;
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER) pMatCfg->pPriv;
PMAC_TABLE_ENTRY pEntry = NULL;
PREPEATER_CLIENT_ENTRY pReptEntry = NULL;
wcid = RTMP_GET_PACKET_WCID(pSkb);
if (VALID_WCID(wcid))
{
pEntry = &pAd->MacTab.Content[wcid];
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s():ERROR! inValid wcid!\n", __FUNCTION__));
return pMacAddr;
}
if (pEntry == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s():ERROR! pEntry is null!\n", __FUNCTION__));
return pMacAddr;
}
if (pEntry && IS_ENTRY_APCLI(pEntry) && (pEntry->bReptCli == TRUE))
{
PUCHAR pPktHdr, pLayerHdr;
pReptEntry = &pAd->ApCfg.ApCliTab[pEntry->wdev_idx].RepeaterCli[pEntry->MatchReptCliIdx];
pPktHdr = GET_OS_PKT_DATAPTR(pSkb);
pLayerHdr = (pPktHdr + MAT_ETHER_HDR_LEN);
/*For UDP packet, we need to check about the DHCP packet. */
if (*(pLayerHdr + 9) == 0x11)
{
PUCHAR pUdpHdr;
UINT16 srcPort, dstPort;
BOOLEAN bHdrChanged = FALSE;
pUdpHdr = pLayerHdr + 20;
srcPort = OS_NTOHS(get_unaligned((PUINT16)(pUdpHdr)));
dstPort = OS_NTOHS(get_unaligned((PUINT16)(pUdpHdr+2)));
if (srcPort==67 && dstPort==68) /*It's a DHCP packet */
{
PUCHAR bootpHdr, pCliHwAddr;
/*REPEATER_CLIENT_ENTRY *pReptEntry = NULL;*/
bootpHdr = pUdpHdr + 8;
pCliHwAddr = (bootpHdr+28);
if (pReptEntry)
NdisMoveMemory(pCliHwAddr, pReptEntry->OriginalAddress, MAC_ADDR_LEN);
else
{
DBGPRINT(RT_DEBUG_OFF, ("%s() MatchAPCLITabIdx = %u\n", __FUNCTION__, pEntry->wdev_idx));
}
bHdrChanged = TRUE;
}
if (bHdrChanged == TRUE)
NdisZeroMemory((pUdpHdr+6), 2); /*modify the UDP chksum as zero */
}
}
}
#endif /* MAC_REPEATER_SUPPORT */
return pMacAddr;
}
static UCHAR DHCP_MAGIC[]= {0x63, 0x82, 0x53, 0x63};
static PUCHAR MATProto_IP_Tx(
IN MAT_STRUCT *pMatCfg,
IN PNDIS_PACKET pSkb,
IN PUCHAR pLayerHdr,
IN PUCHAR pDevMacAdr)
{
PUCHAR pSrcMac;
PUCHAR pSrcIP;
BOOLEAN needUpdate;
PUCHAR pPktHdr;
PNDIS_PACKET pModSkb = NULL;
pPktHdr = GET_OS_PKT_DATAPTR(pSkb);
pSrcMac = pPktHdr + 6;
pSrcIP = pLayerHdr + 12;
needUpdate = NEED_UPDATE_IPMAC_TB(pSrcMac, get_unaligned32((PUINT)(pSrcIP)));
if (needUpdate)
IPMacTableUpdate(pMatCfg, pSrcMac, get_unaligned32((PUINT)(pSrcIP)));
/*For UDP packet, we need to check about the DHCP packet, to modify the flag of DHCP discovey/request as broadcast. */
if (*(pLayerHdr + 9) == 0x11)
{
PUCHAR udpHdr;
UINT16 srcPort, dstPort;
BOOLEAN bHdrChanged = FALSE;
udpHdr = pLayerHdr + 20;
srcPort = OS_NTOHS(get_unaligned((PUINT16)(udpHdr)));
dstPort = OS_NTOHS(get_unaligned((PUINT16)(udpHdr+2)));
if (srcPort==68 && dstPort==67) /*It's a DHCP packet */
{
PUCHAR bootpHdr;
UINT16 bootpFlag;
PUCHAR dhcpHdr;
if(OS_PKT_CLONED(pSkb))
{
pModSkb = (PNDIS_PACKET) OS_PKT_COPY(pSkb);
pPktHdr = GET_OS_PKT_DATAPTR(pModSkb);
if (IS_VLAN_PACKET(pPktHdr))
pLayerHdr = pPktHdr + MAT_VLAN_ETH_HDR_LEN;
else
pLayerHdr = pPktHdr + MAT_ETHER_HDR_LEN;
udpHdr = pLayerHdr + 20;
srcPort = OS_NTOHS(get_unaligned((PUINT16)(udpHdr)));
dstPort = OS_NTOHS(get_unaligned((PUINT16)(udpHdr+2)));
if (!pModSkb)
return NULL;
}
bootpHdr = udpHdr + 8;
bootpFlag = OS_NTOHS(get_unaligned((PUINT16)(bootpHdr+10)));
DBGPRINT(RT_DEBUG_TRACE, ("is bootp packet! bootpFlag=0x%x\n", bootpFlag));
dhcpHdr = bootpHdr + 236;
if (bootpFlag != 0x8000) /*check if it's a broadcast request. */
{
DBGPRINT(RT_DEBUG_TRACE, ("the DHCP flag is a unicast, dhcp_magic=%02x:%02x:%02x:%02x\n",
dhcpHdr[0], dhcpHdr[1], dhcpHdr[2], dhcpHdr[3]));
if (NdisEqualMemory(dhcpHdr, DHCP_MAGIC, 4))
{
DBGPRINT(RT_DEBUG_TRACE, ("dhcp magic macthed!\n"));
bootpFlag = OS_HTONS(0x8000);
NdisMoveMemory((bootpHdr+10), &bootpFlag, 2); /*Set the bootp flag as broadcast */
bHdrChanged = TRUE;
}
}
#ifdef MAC_REPEATER_SUPPORT
if (pMatCfg->bMACRepeaterEn)
{
UCHAR isLinkValid;
if (RTMPLookupRepeaterCliEntry(pMatCfg->pPriv, FALSE, pDevMacAdr, TRUE, &isLinkValid) != NULL)
{
NdisMoveMemory((bootpHdr+28), pDevMacAdr, MAC_ADDR_LEN);
if (NdisEqualMemory(dhcpHdr, DHCP_MAGIC, 4))
{
PUCHAR pOptCode, pOptLen;
UINT16 udpLen;
udpLen = OS_NTOHS(get_unaligned((PUINT16)(udpHdr+4)));
pOptCode = (dhcpHdr + 4);
do
{
pOptLen = pOptCode + 1;
if (*pOptCode == 61) /* Client Identifier */
{
DBGPRINT(RT_DEBUG_TRACE,
("Client Identifier found, change Hardware Address to "
"%02x:%02x:%02x:%02x:%02x:%02x\n",
pDevMacAdr[0], pDevMacAdr[1], pDevMacAdr[2],
pDevMacAdr[3], pDevMacAdr[4], pDevMacAdr[5]));
/* Change Hardware Address */
NdisMoveMemory((pOptCode+3), pDevMacAdr, MAC_ADDR_LEN);
break;
}
pOptCode += (2+*pOptLen);
}while ((*pOptCode != 0xFF) && ((pOptCode - udpHdr) <= udpLen));
}
bHdrChanged = TRUE;
}
}
#endif /* MAC_REPEATER_SUPPORT */
}
if (bHdrChanged == TRUE)
NdisZeroMemory((udpHdr+6), 2); /* Modify the UDP chksum as zero */
}
return pModSkb;
}
static NDIS_STATUS MATProto_IP_Init(
IN MAT_STRUCT *pMatCfg)
{
BOOLEAN status;
status = IPMacTable_init(pMatCfg);
return status;
}
static inline void IPintToIPstr(int ipint, char Ipstr[20], ULONG BufLen)
{
int temp = 0;
temp = ipint & 0x000FF;
snprintf(Ipstr, BufLen, "%d.", temp);
temp = (ipint>>8) & 0x000FF;
snprintf(Ipstr, BufLen, "%s%d.", Ipstr, temp);
temp = (ipint>>16) & 0x000FF;
snprintf(Ipstr, BufLen, "%s%d.", Ipstr, temp);
temp = (ipint>>24) & 0x000FF;
snprintf(Ipstr, BufLen, "%s%d", Ipstr, temp);
}
VOID getIPMacTbInfo(
IN MAT_STRUCT *pMatCfg,
IN char *pOutBuf,
IN ULONG BufLen)
{
IPMacMappingTable *pIPMacTable;
IPMacMappingEntry *pHead;
int startIdx, endIdx;
char Ipstr[20] = {0};
pIPMacTable = (IPMacMappingTable *)pMatCfg->MatTableSet.IPMacTable;
if ((!pIPMacTable) || (!pIPMacTable->valid))
{
DBGPRINT(RT_DEBUG_TRACE, ("%s():IPMacTable not init yet!\n", __FUNCTION__));
return;
}
/* dump all. */
startIdx = 0;
endIdx = MAT_MAX_HASH_ENTRY_SUPPORT;
sprintf(pOutBuf, "\n");
sprintf(pOutBuf+strlen(pOutBuf), "%-18s%-20s\n", "IP", "MAC");
for(; startIdx< endIdx; startIdx++)
{
pHead = pIPMacTable->hash[startIdx];
while(pHead)
{
/* if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30)) */
if (RtmpOsCmdDisplayLenCheck(strlen(pOutBuf), 30) == FALSE)
break;
NdisZeroMemory(Ipstr, 20);
IPintToIPstr(pHead->ipAddr, Ipstr, sizeof(Ipstr));
sprintf(pOutBuf+strlen(pOutBuf), "%-18s%02x:%02x:%02x:%02x:%02x:%02x\n",
Ipstr, pHead->macAddr[0],pHead->macAddr[1],pHead->macAddr[2],
pHead->macAddr[3],pHead->macAddr[4],pHead->macAddr[5]);
pHead = pHead->pNext;
}
}
}
#endif /* MAT_SUPPORT */

View File

@ -0,0 +1,827 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2007, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
cmm_mat_ipv6.c
Abstract:
MAT convert engine subroutine for ipv6 base protocols, currently now we
just handle IPv6/ICMPv6 packets without Authentication/Encryption headers.
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Shiang 06/03/07 Init version
*/
#ifdef MAT_SUPPORT
#include "rt_config.h"
#include "ipv6.h"
/*#include <asm/checksum.h> */
/*#include <net/ip6_checksum.h> */
const UCHAR IPV6_LOOPBACKADDR[] ={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
static NDIS_STATUS MATProto_IPv6_Init(MAT_STRUCT *pMatCfg);
static NDIS_STATUS MATProto_IPv6_Exit(MAT_STRUCT *pMatCfg);
static PUCHAR MATProto_IPv6_Rx(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pDevMacAdr);
static PUCHAR MATProto_IPv6_Tx(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pDevMacAdr);
#define RT_UDP_HDR_LEN 8
typedef struct _IPv6MacMappingEntry
{
UCHAR ipv6Addr[16]; /* In network order */
UCHAR macAddr[MAC_ADDR_LEN];
ULONG lastTime;
struct _IPv6MacMappingEntry *pNext;
}IPv6MacMappingEntry, *PIPv6MacMappingEntry;
typedef struct _IPv6MacMappingTable
{
BOOLEAN valid;
IPv6MacMappingEntry *hash[MAT_MAX_HASH_ENTRY_SUPPORT+1]; /*0~63 for specific station, 64 for broadcast MacAddress */
UCHAR curMcastAddr[MAC_ADDR_LEN]; /* The multicast mac addr for currecnt received packet destined to ipv6 multicast addr */
}IPv6MacMappingTable;
struct _MATProtoOps MATProtoIPv6Handle =
{
.init = MATProto_IPv6_Init,
.tx = MATProto_IPv6_Tx,
.rx = MATProto_IPv6_Rx,
.exit = MATProto_IPv6_Exit,
};
static inline BOOLEAN needUpdateIPv6MacTB(
UCHAR *pMac,
RT_IPV6_ADDR *pIPv6Addr)
{
ASSERT(pIPv6Addr);
if (isMcastEtherAddr(pMac) || isZeroEtherAddr(pMac))
return FALSE;
/* IPv6 multicast address */
if (IS_MULTICAST_IPV6_ADDR(*pIPv6Addr))
return FALSE;
/* unspecified address */
if(IS_UNSPECIFIED_IPV6_ADDR(*pIPv6Addr))
return FALSE;
/* loopback address */
if (IS_LOOPBACK_IPV6_ADDR(*pIPv6Addr))
return FALSE;
/*
DBGPRINT(RT_DEBUG_INFO, ("%s(): Good IPv6 unicast addr=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
__FUNCTION__, PRINT_IPV6_ADDR(*pIPv6Addr)));
*/
return TRUE;
}
/*
IPv6 Header Format
0 1 2 3
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| Traffic Class | Flow Label |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Payload Length | Next Header | Hop Limit |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| Source Address |
+ +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
+ +
| Destination Address |
+ +
| |
+ +
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ICMPv6 Format:
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Body |
+ +
| |
......
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
NDIS_STATUS dumpIPv6MacTb(
IN MAT_STRUCT *pMatCfg,
IN int index)
{
IPv6MacMappingTable *pIPv6MacTable;
IPv6MacMappingEntry *pHead;
int startIdx, endIdx;
pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
if ((!pIPv6MacTable) || (!pIPv6MacTable->valid))
{
DBGPRINT(RT_DEBUG_OFF, ("%s():IPv6MacTable not init yet, so cannot do dump!\n", __FUNCTION__));
return FALSE;
}
if(index < 0)
{ /* dump all. */
startIdx = 0;
endIdx = MAT_MAX_HASH_ENTRY_SUPPORT;
}
else
{ /* dump specific hash index. */
startIdx = endIdx = index;
}
DBGPRINT(RT_DEBUG_OFF, ("%s():\n", __FUNCTION__));
for(; startIdx<= endIdx; startIdx++)
{
pHead = pIPv6MacTable->hash[startIdx];
while(pHead)
{
DBGPRINT(RT_DEBUG_OFF, ("IPv6Mac[%d]:\n", startIdx));
DBGPRINT(RT_DEBUG_OFF, ("\t:IPv6=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x,Mac=%02x:%02x:%02x:%02x:%02x:%02x, lastTime=0x%lx, next=%p\n",
PRINT_IPV6_ADDR(*((RT_IPV6_ADDR *)(&pHead->ipv6Addr[0]))), pHead->macAddr[0],pHead->macAddr[1],pHead->macAddr[2],
pHead->macAddr[3],pHead->macAddr[4],pHead->macAddr[5], pHead->lastTime, pHead->pNext));
pHead = pHead->pNext;
}
}
DBGPRINT(RT_DEBUG_OFF, ("\t----EndOfDump!\n"));
return TRUE;
}
static NDIS_STATUS IPv6MacTableUpdate(
IN MAT_STRUCT *pMatCfg,
IN PUCHAR pMacAddr,
IN PCHAR pIPv6Addr)
{
UINT hashIdx;
IPv6MacMappingTable *pIPv6MacTable;
IPv6MacMappingEntry *pEntry = NULL, *pPrev = NULL, *pNewEntry =NULL;
ULONG now;
pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
if ((!pIPv6MacTable) || (!pIPv6MacTable->valid))
return FALSE;
hashIdx = MAT_IPV6_ADDR_HASH_INDEX(pIPv6Addr);
pEntry = pPrev = pIPv6MacTable->hash[hashIdx];
while(pEntry)
{
NdisGetSystemUpTime(&now);
/* Find a existed IP-MAC Mapping entry */
if (NdisEqualMemory(pIPv6Addr, pEntry->ipv6Addr, IPV6_ADDR_LEN))
{
/* comparison is useless. So we directly copy it into the entry. */
NdisMoveMemory(pEntry->macAddr, pMacAddr, 6);
NdisGetSystemUpTime(&pEntry->lastTime);
return TRUE;
}
else
{ /* handle the aging-out situation */
if (RTMP_TIME_AFTER(now, (pEntry->lastTime + MAT_TB_ENTRY_AGEOUT_TIME)))
{
/* Remove the aged entry */
if (pEntry == pIPv6MacTable->hash[hashIdx])
{
pIPv6MacTable->hash[hashIdx]= pEntry->pNext;
pPrev = pIPv6MacTable->hash[hashIdx];
}
else
{
pPrev->pNext = pEntry->pNext;
}
MATDBEntryFree(pMatCfg, (PUCHAR)pEntry);
pEntry = (pPrev == NULL ? NULL: pPrev->pNext);
pMatCfg->nodeCount--;
}
else
{
pPrev = pEntry;
pEntry = pEntry->pNext;
}
}
}
#ifdef ETH_CONVERT_SUPPORT
if (pMatCfg->nodeCount >= ETH_CONVERT_NODE_MAX)
return FALSE;
#endif /* ETH_CONVERT_SUPPORT */
/* Allocate a new IPv6MacMapping entry and insert into the hash */
pNewEntry = (IPv6MacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(IPv6MacMappingEntry));
if (pNewEntry != NULL)
{
NdisMoveMemory(pNewEntry->ipv6Addr, pIPv6Addr, IPV6_ADDR_LEN);
NdisMoveMemory(pNewEntry->macAddr, pMacAddr, 6);
pNewEntry->pNext = NULL;
NdisGetSystemUpTime(&pNewEntry->lastTime);
if (pIPv6MacTable->hash[hashIdx] == NULL)
{ /* Hash list is empty, directly assign it. */
pIPv6MacTable->hash[hashIdx] = pNewEntry;
}
else
{
/* Ok, we insert the new entry into the root of hash[hashIdx] */
pNewEntry->pNext = pIPv6MacTable->hash[hashIdx];
pIPv6MacTable->hash[hashIdx] = pNewEntry;
}
/*dumpIPv6MacTb(pMatCfg, hashIdx); //for debug */
pMatCfg->nodeCount++;
return TRUE;
}
DBGPRINT(RT_DEBUG_ERROR, ("IPv6MacTableUpdate():Insertion failed!\n"));
return FALSE;
}
static PUCHAR IPv6MacTableLookUp(
IN MAT_STRUCT *pMatCfg,
IN PUCHAR pIPv6Addr)
{
UINT hashIdx;
IPv6MacMappingTable *pIPv6MacTable;
IPv6MacMappingEntry *pEntry = NULL;
PUCHAR pGroupMacAddr;
pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
if ((!pIPv6MacTable) ||(!pIPv6MacTable->valid))
return NULL;
/*if IPV6 multicast address, need converting multicast group address to ethernet address. */
if (IS_MULTICAST_IPV6_ADDR(*(RT_IPV6_ADDR *)pIPv6Addr))
{
pGroupMacAddr = (PUCHAR)&pIPv6MacTable->curMcastAddr;
ConvertMulticastIP2MAC(pIPv6Addr, (UCHAR **)(&pGroupMacAddr), ETH_P_IPV6);
return pIPv6MacTable->curMcastAddr;
}
/* Use hash to find out the location of that entry and get the Mac address. */
hashIdx = MAT_IPV6_ADDR_HASH_INDEX(pIPv6Addr);
/* spin_lock_irqsave(&IPMacTabLock, irqFlag); */
pEntry = pIPv6MacTable->hash[hashIdx];
while(pEntry)
{
if (NdisEqualMemory(pEntry->ipv6Addr, pIPv6Addr, IPV6_ADDR_LEN))
{
/*Update the lastTime to prevent the aging before pDA processed! */
NdisGetSystemUpTime(&pEntry->lastTime);
return pEntry->macAddr;
}
else
{
pEntry = pEntry->pNext;
}
}
/*
We didn't find any matched Mac address, our policy is treat it as
broadcast packet and send to all.
*/
return pIPv6MacTable->hash[IPV6MAC_TB_HASH_INDEX_OF_BCAST]->macAddr;
}
static inline unsigned short int icmpv6_csum(
RT_IPV6_ADDR *saddr,
RT_IPV6_ADDR *daddr,
USHORT len,
UCHAR proto,
UCHAR *pICMPMsg)
{
int carry;
UINT32 ulen;
UINT32 uproto;
int i;
unsigned int csum = 0;
unsigned short int chksum;
if (len % 4)
return 0;
for( i = 0; i < 4; i++)
{
csum += saddr->ipv6_addr32[i];
carry = (csum < saddr->ipv6_addr32[i]);
csum += carry;
}
for( i = 0; i < 4; i++)
{
csum += daddr->ipv6_addr32[i];
carry = (csum < daddr->ipv6_addr32[i]);
csum += carry;
}
ulen = OS_HTONL((UINT32)len);
csum += ulen;
carry = (csum < ulen);
csum += carry;
uproto = OS_HTONL((UINT32)proto);
csum += uproto;
carry = (csum < uproto);
csum += carry;
for (i = 0; i < len; i += 4)
{
csum += get_unaligned32(((UINT32 *)&pICMPMsg[i]));
carry = (csum < get_unaligned32(((UINT32 *)&pICMPMsg[i])));
csum += carry;
}
while (csum>>16)
csum = (csum & 0xffff) + (csum >> 16);
chksum = ~csum;
return chksum;
}
static PUCHAR MATProto_IPv6_Rx(
IN MAT_STRUCT *pMatCfg,
IN PNDIS_PACKET pSkb,
IN PUCHAR pLayerHdr,
IN PUCHAR pDevMacAdr)
{
PUCHAR pMacAddr;
PUCHAR pDstIPv6Addr;
/* Fetch the IPv6 addres from the packet header. */
pDstIPv6Addr = (UCHAR *)(&((RT_IPV6_HDR *)pLayerHdr)->dstAddr);
pMacAddr = IPv6MacTableLookUp(pMatCfg, pDstIPv6Addr);
return pMacAddr;
}
static PNDIS_PACKET ICMPv6_Handle_Tx(
IN MAT_STRUCT *pMatSrtuct,
IN PNDIS_PACKET pSkb,
IN PUCHAR pLayerHdr,
IN PUCHAR pDevMacAdr,
IN UINT32 offset)
{
RT_IPV6_HDR *pIPv6Hdr;
RT_ICMPV6_HDR *pICMPv6Hdr;
RT_ICMPV6_OPTION_HDR *pOptHdr;
USHORT payloadLen;
UINT32 ICMPOffset = 0, ICMPMsgLen = 0, leftLen;
PNDIS_PACKET newSkb = NULL;
BOOLEAN needModify = FALSE;
PUCHAR pSrcMac;
pIPv6Hdr = (RT_IPV6_HDR *)pLayerHdr;
payloadLen = OS_NTOHS(pIPv6Hdr->payload_len);
pICMPv6Hdr = (RT_ICMPV6_HDR *)(pLayerHdr + offset);
ICMPOffset = offset;
ICMPMsgLen = payloadLen + IPV6_HDR_LEN - ICMPOffset;
leftLen = ICMPMsgLen;
switch (pICMPv6Hdr->type)
{
case ICMPV6_MSG_TYPE_ROUTER_SOLICITATION:
offset += ROUTER_SOLICITATION_FIXED_LEN;
/* for unspecified source address, it should not include the option about link-layer address. */
if (!(IS_UNSPECIFIED_IPV6_ADDR(pIPv6Hdr->srcAddr)))
{
while(leftLen > sizeof(RT_ICMPV6_OPTION_HDR))
{
pOptHdr = (RT_ICMPV6_OPTION_HDR *)(pLayerHdr + offset);
if (pOptHdr->len == 0)
break; /* discard it, because it's invalid. */
if (pOptHdr->type == TYPE_SRC_LL_ADDR)
{
/*replace the src link-layer address as ours. */
needModify = TRUE;
offset += 2; /* 2 = "type, len" fields. Here indicate to the place of src mac. */
break;
} else {
offset += (pOptHdr->len * 8); /* in unit of 8 octets. */
leftLen -= (pOptHdr->len * 8);
}
}
}
break;
case ICMPV6_MSG_TYPE_ROUTER_ADVERTISEMENT:
offset += ROUTER_ADVERTISEMENT_FIXED_LEN;
/* for unspecified source address, it should not include the option about link-layer address. */
if (!(IS_UNSPECIFIED_IPV6_ADDR(pIPv6Hdr->srcAddr)))
{
while(leftLen > sizeof(RT_ICMPV6_OPTION_HDR))
{
pOptHdr = (RT_ICMPV6_OPTION_HDR *)(pLayerHdr + offset);
if (pOptHdr->len == 0)
break; /* discard it, because it's invalid. */
if (pOptHdr->type == TYPE_SRC_LL_ADDR)
{
/*replace the src link-layer address as ours. */
needModify = TRUE;
offset += 2; /* 2 = "type, len" fields. Here indicate to the place of src mac. */
break;
} else {
offset += (pOptHdr->len * 8); /* in unit of 8 octets. */
leftLen -= (pOptHdr->len * 8);
}
}
}
break;
case ICMPV6_MSG_TYPE_NEIGHBOR_SOLICITATION:
offset += NEIGHBOR_SOLICITATION_FIXED_LEN;
/* for unspecified source address, it should not include the option about link-layer address. */
if (!(IS_UNSPECIFIED_IPV6_ADDR(pIPv6Hdr->srcAddr)))
{
while(leftLen > sizeof(RT_ICMPV6_OPTION_HDR))
{
pOptHdr = (RT_ICMPV6_OPTION_HDR *)(pLayerHdr + offset);
if (pOptHdr->len == 0)
break; /* discard it, because it's invalid. */
if (pOptHdr->type == TYPE_SRC_LL_ADDR)
{
/*replace the src link-layer address as ours. */
needModify = TRUE;
offset += 2; /* 2 = "type, len" fields. Here indicate to the place of src mac. */
break;
} else {
offset += (pOptHdr->len * 8); /* in unit of 8 octets. */
leftLen -= (pOptHdr->len * 8);
}
}
}
break;
case ICMPV6_MSG_TYPE_NEIGHBOR_ADVERTISEMENT:
offset += NEIGHBOR_ADVERTISEMENT_FIXED_LEN;
/* for unspecified source address, it should not include the option about link-layer address. */
if (!(IS_UNSPECIFIED_IPV6_ADDR(pIPv6Hdr->srcAddr)))
{
while(leftLen > sizeof(RT_ICMPV6_OPTION_HDR))
{
pOptHdr = (RT_ICMPV6_OPTION_HDR *)(pLayerHdr + offset);
if (pOptHdr->len == 0)
break; /* discard it, because it's invalid. */
if (pOptHdr->type == TYPE_TGT_LL_ADDR)
{
/*replace the src link-layer address as ours. */
needModify = TRUE;
offset += 2; /* 2 = "type, len" fields. */
break;
}else {
offset += (pOptHdr->len * 8); /* in unit of 8 octets. */
leftLen -= (pOptHdr->len * 8);
}
}
}
break;
case ICMPV6_MSG_TYPE_REDIRECT:
offset += REDIRECT_FIXED_LEN;
/* for unspecified source address, it should not include the options about link-layer address. */
if (!(IS_UNSPECIFIED_IPV6_ADDR(pIPv6Hdr->srcAddr)))
{
while(leftLen > sizeof(RT_ICMPV6_OPTION_HDR))
{
pOptHdr = (RT_ICMPV6_OPTION_HDR *)(pLayerHdr + offset);
if (pOptHdr->len == 0)
break; /* discard it, because it's invalid. */
if (pOptHdr->type == TYPE_TGT_LL_ADDR)
{
/* TODO: Need to check if the TGT_LL_ADDR is the inner MAC. */
/*replace the src link-layer address as ours. */
needModify = TRUE;
offset += 2; /* 2 = "type, len" fields. */
break;
}else {
offset += (pOptHdr->len * 8); /* in unit of 8 octets. */
leftLen -= (pOptHdr->len * 8);
}
}
}
break;
default:
DBGPRINT(RT_DEBUG_TRACE, ("Un-supported ICMPv6 msg type(0x%x)! Ignore it\n", pICMPv6Hdr->type));
break;
}
/* We need to handle about the solicitation/Advertisement packets. */
if (needModify)
{
if(OS_PKT_CLONED(pSkb))
{
newSkb = (PNDIS_PACKET)OS_PKT_COPY(RTPKT_TO_OSPKT(pSkb));
if(newSkb) {
if (IS_VLAN_PACKET(GET_OS_PKT_DATAPTR(newSkb)))
pIPv6Hdr = (RT_IPV6_HDR *)(GET_OS_PKT_DATAPTR(newSkb) + MAT_VLAN_ETH_HDR_LEN);
else
pIPv6Hdr = (RT_IPV6_HDR *)(GET_OS_PKT_DATAPTR(newSkb) + MAT_ETHER_HDR_LEN);
}
}
pICMPv6Hdr = (RT_ICMPV6_HDR *)((PUCHAR)pIPv6Hdr + ICMPOffset);
pSrcMac = (PUCHAR)((PUCHAR)pIPv6Hdr + offset);
NdisMoveMemory(pSrcMac, pDevMacAdr, MAC_ADDR_LEN);
/* Now re-calculate the Checksum. */
pICMPv6Hdr->chksum = 0;
pICMPv6Hdr->chksum = icmpv6_csum(&pIPv6Hdr->srcAddr, &pIPv6Hdr->dstAddr, ICMPMsgLen ,
IPV6_NEXT_HEADER_ICMPV6, (PUCHAR)pICMPv6Hdr);
}
return newSkb;
}
static PUCHAR MATProto_IPv6_Tx(
IN MAT_STRUCT *pMatCfg,
IN PNDIS_PACKET pSkb,
IN PUCHAR pLayerHdr,
IN PUCHAR pDevMacAdr)
{
PUCHAR pSrcMac;
BOOLEAN needUpdate;
UCHAR nextProtocol;
UINT32 offset;
HEADER_802_3 *pEthHdr;
RT_IPV6_HDR *pIPv6Hdr;
PNDIS_PACKET newSkb = NULL;
pIPv6Hdr = (RT_IPV6_HDR *)pLayerHdr;
pEthHdr = (HEADER_802_3 *)(GET_OS_PKT_DATAPTR(pSkb));
pSrcMac = (UCHAR *)&pEthHdr->SAAddr2;
needUpdate = needUpdateIPv6MacTB(pSrcMac, (RT_IPV6_ADDR *)(&pIPv6Hdr->srcAddr));
if (needUpdate)
IPv6MacTableUpdate(pMatCfg, pSrcMac, (CHAR *)(&pIPv6Hdr->srcAddr));
/* We need to traverse the whole IPv6 Header and extend headers to check about the ICMPv6 pacekt. */
nextProtocol = pIPv6Hdr->nextHdr;
offset = IPV6_HDR_LEN;
/*DBGPRINT(RT_DEBUG_INFO, ("NextProtocol=0x%x! payloadLen=%d! offset=%d!\n", nextProtocol, payloadLen, offset)); */
while(nextProtocol != IPV6_NEXT_HEADER_ICMPV6 &&
nextProtocol != IPV6_NEXT_HEADER_UDP &&
nextProtocol != IPV6_NEXT_HEADER_TCP &&
nextProtocol != IPV6_NEXT_HEADER_NONE)
{
if(IPv6ExtHdrHandle((RT_IPV6_EXT_HDR *)(pLayerHdr + offset), &nextProtocol, &offset) == FALSE)
{
DBGPRINT(RT_DEBUG_TRACE,("IPv6ExtHdrHandle failed!\n"));
break;
}
}
switch (nextProtocol)
{
case IPV6_NEXT_HEADER_ICMPV6:
newSkb = ICMPv6_Handle_Tx(pMatCfg, pSkb, pLayerHdr, pDevMacAdr, offset);
break;
case IPV6_NEXT_HEADER_UDP:
/*newSkb = DHCPv6_Handle_Tx(pMatStrcut, pSkb, pLayerHdr, pMacAddr, offset); */
break;
case IPV6_NEXT_HEADER_TCP:
case IPV6_NEXT_HEADER_NONE:
default:
break;
}
return (PUCHAR)newSkb;
}
static NDIS_STATUS IPv6MacTable_RemoveAll(
IN MAT_STRUCT *pMatCfg)
{
IPv6MacMappingTable *pIPv6MacTable;
IPv6MacMappingEntry *pEntry;
UINT32 i;
pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
if (!pIPv6MacTable)
return TRUE;
if (pIPv6MacTable->valid)
{
pIPv6MacTable->valid = FALSE;
for (i=0; i<IPV6MAC_TB_HASH_ENTRY_NUM; i++)
{
while((pEntry = pIPv6MacTable->hash[i]) != NULL)
{
pIPv6MacTable->hash[i] = pEntry->pNext;
MATDBEntryFree(pMatCfg, (PUCHAR)pEntry);
}
}
}
/* kfree(pIPv6MacTable); */
os_free_mem(NULL, pIPv6MacTable);
pMatCfg->MatTableSet.IPv6MacTable = NULL;
return TRUE;
}
static NDIS_STATUS IPv6MacTable_init(
IN MAT_STRUCT *pMatCfg)
{
IPv6MacMappingEntry *pEntry = NULL;
IPv6MacMappingTable *pIPv6MacTable;
if (pMatCfg->MatTableSet.IPv6MacTable != NULL)
{
pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
}
else
{
/* pMatCfg->MatTableSet.IPv6MacTable = kmalloc(sizeof(IPv6MacMappingTable), GFP_KERNEL); */
os_alloc_mem_suspend(NULL, (UCHAR **)&(pMatCfg->MatTableSet.IPv6MacTable), sizeof(IPv6MacMappingTable));
if (pMatCfg->MatTableSet.IPv6MacTable)
{
pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
NdisZeroMemory(pIPv6MacTable, sizeof(IPv6MacMappingTable));
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("IPMacTable_init(): Allocate memory for IPv6MacTable failed!\n"));
return FALSE;
}
}
if (pIPv6MacTable->valid == FALSE)
{
/*Set the last hash entry (hash[64]) as our default broadcast Mac address */
pEntry = (IPv6MacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(IPv6MacMappingEntry));
if (!pEntry)
{
DBGPRINT(RT_DEBUG_ERROR, ("IPMacTable_init(): Allocate memory for IPMacTable broadcast entry failed!\n"));
return FALSE;
}
NdisZeroMemory(pEntry, sizeof(IPv6MacMappingEntry));
NdisMoveMemory(pEntry->macAddr, BROADCAST_ADDR, MAC_ADDR_LEN);
pEntry->pNext = NULL;
pIPv6MacTable->hash[IPV6MAC_TB_HASH_INDEX_OF_BCAST] = pEntry;
pIPv6MacTable->valid = TRUE;
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("%s(): IPv6MacTable already inited!\n", __FUNCTION__));
}
return TRUE;
}
static NDIS_STATUS MATProto_IPv6_Exit(
IN MAT_STRUCT *pMatCfg)
{
INT status;
status = IPv6MacTable_RemoveAll(pMatCfg);
return status;
}
static NDIS_STATUS MATProto_IPv6_Init(
IN MAT_STRUCT *pMatCfg)
{
BOOLEAN status = FALSE;
status = IPv6MacTable_init(pMatCfg);
return status;
}
VOID getIPv6MacTbInfo(
IN MAT_STRUCT *pMatCfg,
IN char *pOutBuf,
IN ULONG BufLen)
{
IPv6MacMappingTable *pIPv6MacTable;
IPv6MacMappingEntry *pHead;
int startIdx, endIdx;
char Ipv6str[40] = {0};
pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable;
if ((!pIPv6MacTable) || (!pIPv6MacTable->valid))
{
DBGPRINT(RT_DEBUG_TRACE, ("%s():IPv6MacTable not init yet!\n", __FUNCTION__));
return;
}
/* dump all. */
startIdx = 0;
endIdx = MAT_MAX_HASH_ENTRY_SUPPORT;
sprintf(pOutBuf, "\n");
sprintf(pOutBuf+strlen(pOutBuf), "%-40s%-20s\n", "IP", "MAC");
for(; startIdx< endIdx; startIdx++)
{
pHead = pIPv6MacTable->hash[startIdx];
while(pHead)
{
/* if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30)) */
if (RtmpOsCmdDisplayLenCheck(strlen(pOutBuf), 30) == FALSE)
break;
NdisZeroMemory(Ipv6str, 40);
sprintf(Ipv6str, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", PRINT_IPV6_ADDR(*((RT_IPV6_ADDR *)(&pHead->ipv6Addr[0]))));
sprintf(pOutBuf+strlen(pOutBuf), "%-40s%02x:%02x:%02x:%02x:%02x:%02x\n",
Ipv6str, pHead->macAddr[0],pHead->macAddr[1],pHead->macAddr[2],
pHead->macAddr[3],pHead->macAddr[4],pHead->macAddr[5]);
pHead = pHead->pNext;
}
}
}
#endif /* MAT_SUPPORT */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,435 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
cmm_radar.c
Abstract:
CS/DFS common functions.
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#include "rt_config.h"
/*----- 802.11H -----*/
/* Periodic Radar detection, switch channel will occur in RTMPHandleTBTTInterrupt()*/
/* Before switch channel, driver needs doing channel switch announcement.*/
VOID RadarDetectPeriodic(
IN PRTMP_ADAPTER pAd)
{
INT i, ChIdx = 0;
/*
1. APStart(), CalBufTime = 0;
2. if bAnyUnavailableChannel, CalBufTime = DEFAULT_CAL_BUF_TIME;
3. if Calibrated, CalBufTime = DEFAULT_CAL_BUF_TIME_MAX;
*/
for (i=0; i<pAd->ChannelListNum; i++)
{
if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel)
{
ChIdx = i;
}
}
if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE)
{
/* In Silent Mode, RDCount is use to check with the CAC Time */
if (pAd->Dot11_H.RDCount++ > pAd->Dot11_H.ChMovingTime &&
pAd->ChannelList[ChIdx].RemainingTimeForUse == 0)
{
DBGPRINT(RT_DEBUG_TRACE,
("Not found radar signal, start send beacon and radar detection in service monitor\n\n"));
pAd->Dot11_H.RDMode = RD_NORMAL_MODE;
AsicEnableBssSync(pAd);
#ifdef MT76x2
if (IS_MT76x2(pAd)) {
mt76x2_tssi_calibration(pAd, pAd->hw_cfg.cent_ch);
#ifdef TXBF_SUPPORT
if (pAd->hw_cfg.cent_ch > 14)
rtmp_ate_txbf_fix_tank_code(pAd, pAd->hw_cfg.cent_ch, 0); // load tank code from efuse, iBF only for A band
#endif /* TXBF_SUPPORT */
mt76x2_calibration(pAd, pAd->hw_cfg.cent_ch);
}
#endif /* MT76x2 */
pAd->Dot11_H.RDCount = 0;
}
}
}
/*
========================================================================
Routine Description:
Radar channel check routine
Arguments:
pAd Pointer to our adapter
Return Value:
TRUE need to do radar detect
FALSE need not to do radar detect
========================================================================
*/
BOOLEAN RadarChannelCheck(
IN PRTMP_ADAPTER pAd,
IN UCHAR Ch)
{
INT i;
BOOLEAN result = FALSE;
for (i=0; i<pAd->ChannelListNum; i++)
{
if (Ch == pAd->ChannelList[i].Channel)
{
result = pAd->ChannelList[i].DfsReq;
break;
}
}
return result;
}
/*
========================================================================
Routine Description:
Determine the current radar state
Arguments:
pAd Pointer to our adapter
Return Value:
========================================================================
*/
VOID RadarStateCheck(
IN PRTMP_ADAPTER pAd)
{
pAd->Dot11_H.CalBufTime = 0;
if ((pAd->CommonCfg.Channel > 14) &&
(pAd->CommonCfg.bIEEE80211H == 1) &&
RadarChannelCheck(pAd, pAd->CommonCfg.Channel))
{
pAd->Dot11_H.RDMode = RD_SILENCE_MODE;
pAd->Dot11_H.RDCount = 0;
pAd->Dot11_H.InServiceMonitorCount = 0;
}
else
pAd->Dot11_H.RDMode = RD_NORMAL_MODE;
#ifdef CARRIER_DETECTION_SUPPORT
if ((pAd->CommonCfg.RDDurRegion == JAP)
|| (pAd->CommonCfg.RDDurRegion == JAP_W53)
|| (pAd->CommonCfg.RDDurRegion == JAP_W56))
{
if ((pAd->CommonCfg.Channel > 14) ||
(pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40))
{
pAd->CommonCfg.CarrierDetect.Enable = TRUE;
}
}
#endif /* CARRIER_DETECTION_SUPPORT */
}
ULONG JapRadarType(
IN PRTMP_ADAPTER pAd)
{
ULONG i;
const UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140};
if (pAd->CommonCfg.RDDurRegion != JAP)
{
return pAd->CommonCfg.RDDurRegion;
}
for (i=0; i<15; i++)
{
if (pAd->CommonCfg.Channel == Channel[i])
{
break;
}
}
if (i < 4)
return JAP_W53;
else if (i < 15)
return JAP_W56;
else
return JAP; /* W52*/
}
UCHAR get_channel_by_reference(
IN PRTMP_ADAPTER pAd,
IN UINT8 mode)
{
UCHAR ch = 0;
INT ch_idx;
switch (mode)
{
case 1:
{
USHORT min_time = 0xFFFF;
/* select channel with least RemainingTimeForUse */
for ( ch_idx = 0; ch_idx < pAd->ChannelListNum; ch_idx++)
{
if (pAd->ChannelList[ch_idx].RemainingTimeForUse < min_time)
{
#ifdef DOT11_N_SUPPORT
/* If the channel not in 40MHz/80MHz group, ignore it. */
if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 &&
!(pAd->ChannelList[ch_idx].Flags & CHANNEL_40M_CAP))
continue;
#ifdef DOT11_VHT_AC
if (pAd->CommonCfg.vht_bw == VHT_BW_80 &&
!(pAd->ChannelList[ch_idx].Flags & CHANNEL_80M_CAP))
continue;
#endif /* DOT11_VHT_AC */
#endif /* DOT11_N_SUPPORT */
min_time = pAd->ChannelList[ch_idx].RemainingTimeForUse;
ch = pAd->ChannelList[ch_idx].Channel;
}
}
break;
}
default:
{
ch = FirstChannel(pAd);
break;
}
}
DBGPRINT(RT_DEBUG_TRACE,("%s(): mode = %u, ch = %u\n",
__FUNCTION__, mode, ch));
return ch;
}
#ifdef CONFIG_AP_SUPPORT
/*
========================================================================
Routine Description:
Channel switching count down process upon radar detection
Arguments:
pAd Pointer to our adapter
========================================================================
*/
VOID ChannelSwitchingCountDownProc(
IN PRTMP_ADAPTER pAd)
{
DBGPRINT(RT_DEBUG_TRACE, ("%s():Channel Switching...(%d/%d)\n",
__FUNCTION__, pAd->Dot11_H.CSCount, pAd->Dot11_H.CSPeriod));
pAd->Dot11_H.CSCount++;
if (pAd->Dot11_H.CSCount >= pAd->Dot11_H.CSPeriod)
{
#ifdef DFS_SUPPORT
pAd->CommonCfg.RadarDetect.DFSAPRestart = 1;
schedule_dfs_task(pAd);
#else
APStop(pAd);
APStartUp(pAd);
#endif /* !DFS_SUPPORT */
}
}
#endif /* CONFIG_AP_SUPPORT */
/*
==========================================================================
Description:
Set channel switch Period
Return:
TRUE if all parameters are OK, FALSE otherwise
==========================================================================
*/
INT Set_CSPeriod_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
pAd->Dot11_H.CSPeriod = (USHORT) simple_strtol(arg, 0, 10);
DBGPRINT(RT_DEBUG_TRACE, ("Set_CSPeriod_Proc::(CSPeriod=%d)\n", pAd->Dot11_H.CSPeriod));
return TRUE;
}
/*
==========================================================================
Description:
change channel moving time for DFS testing.
Arguments:
pAdapter Pointer to our adapter
wrq Pointer to the ioctl argument
Return Value:
None
Note:
Usage:
1.) iwpriv ra0 set ChMovTime=[value]
==========================================================================
*/
INT Set_ChMovingTime_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
USHORT Value;
Value = (USHORT) simple_strtol(arg, 0, 10);
pAd->Dot11_H.ChMovingTime = Value;
DBGPRINT(RT_DEBUG_TRACE, ("%s: %d\n", __FUNCTION__,
pAd->Dot11_H.ChMovingTime));
return TRUE;
}
/*
==========================================================================
Description:
Reset channel block status.
Arguments:
pAd Pointer to our adapter
arg Not used
Return Value:
None
Note:
Usage:
1.) iwpriv ra0 set ChMovTime=[value]
==========================================================================
*/
INT Set_BlockChReset_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
INT i;
DBGPRINT(RT_DEBUG_TRACE, ("%s: Reset channel block status.\n", __FUNCTION__));
for (i=0; i<pAd->ChannelListNum; i++)
pAd->ChannelList[i].RemainingTimeForUse = 0;
return TRUE;
}
#if defined(DFS_SUPPORT) || defined(CARRIER_DETECTION_SUPPORT)
INT Set_RadarShow_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
#ifdef DFS_SUPPORT
UINT8 idx;
PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect;
PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam;
PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam;
PCHAR RDMode[]= {"Normal State", "Switching State", "Silent State"};
printk("DFSUseTasklet = %d\n", pRadarDetect->use_tasklet);
printk("McuRadarDebug = %x\n", (unsigned int)pRadarDetect->McuRadarDebug);
printk("PollTime = %d\n", pRadarDetect->PollTime);
printk("ChEnable = %d (0x%x)\n", pDfsProgramParam->ChEnable, pDfsProgramParam->ChEnable);
printk("DeltaDelay = %d\n", pDfsProgramParam->DeltaDelay);
printk("PeriodErr = %d\n", pDfsSwParam->dfs_period_err);
printk("MaxPeriod = %d\n", (unsigned int)pDfsSwParam->dfs_max_period);
printk("Ch0LErr = %d\n", pDfsSwParam->dfs_width_ch0_err_L);
printk("Ch0HErr = %d\n", pDfsSwParam->dfs_width_ch0_err_H);
printk("Ch1Shift = %d\n", pDfsSwParam->dfs_width_diff_ch1_Shift);
printk("Ch2Shift = %d\n", pDfsSwParam->dfs_width_diff_ch2_Shift);
printk("DfsRssiHigh = %d\n", pRadarDetect->DfsRssiHigh);
printk("DfsRssiLow = %d\n", pRadarDetect->DfsRssiLow);
printk("DfsSwDisable = %u\n", pRadarDetect->bDfsSwDisable);
printk("CheckLoop = %d\n", pDfsSwParam->dfs_check_loop);
printk("DeclareThres = %d\n", pDfsSwParam->dfs_declare_thres);
for (idx=0; idx < pAd->chipCap.DfsEngineNum; idx++)
printk("sw_idx[%u] = %u\n", idx, pDfsSwParam->sw_idx[idx]);
for (idx=0; idx < pAd->chipCap.DfsEngineNum; idx++)
printk("hw_idx[%u] = %u\n", idx, pDfsSwParam->hw_idx[idx]);
printk("pAd->Dot11_H.ChMovingTime = %d\n", pAd->Dot11_H.ChMovingTime);
printk("pAd->Dot11_H.RDMode = %s\n", RDMode[pAd->Dot11_H.RDMode]);
printk("pAd->Dot11_H.RDCount = %d\n", pAd->Dot11_H.RDCount);
printk("pAd->Dot11_H.CalBufTime = %lu\n", pAd->Dot11_H.CalBufTime);
#endif /* DFS_SUPPORT */
#ifdef CARRIER_DETECTION_SUPPORT
printk("pAd->CommonCfg.CarrierDetect.CD_State = %d\n", pAd->CommonCfg.CarrierDetect.CD_State);
printk("pAd->CommonCfg.CarrierDetect.criteria = %d\n", pAd->CommonCfg.CarrierDetect.criteria);
printk("pAd->CommonCfg.CarrierDetect.Delta = %d\n", pAd->CommonCfg.CarrierDetect.delta);
printk("pAd->CommonCfg.CarrierDetect.DivFlag = %d\n", pAd->CommonCfg.CarrierDetect.div_flag);
printk("pAd->CommonCfg.CarrierDetect.Threshold = %d(0x%x)\n", pAd->CommonCfg.CarrierDetect.threshold, pAd->CommonCfg.CarrierDetect.threshold);
#endif /* CARRIER_DETECTION_SUPPORT */
return TRUE;
}
/*
========================================================================
Routine Description:
Control CCK_MRC Status
Arguments:
pAd Pointer to our adapter
Return Value:
========================================================================
*/
VOID CckMrcStatusCtrl(IN PRTMP_ADAPTER pAd)
{
}
/*
========================================================================
Routine Description:
Enhance DFS/CS when using GLRT.
Arguments:
pAd Pointer to our adapter
Return Value:
========================================================================
*/
VOID RadarGLRTCompensate(IN PRTMP_ADAPTER pAd)
{
}
#endif /*defined(DFS_SUPPORT) || defined(CARRIER_DETECTION_SUPPORT) */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,540 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
cmm_sync.c
Abstract:
Revision History:
Who When What
-------- ---------- ----------------------------------------------
John Chang 2004-09-01 modified for rt2561/2661
*/
#include "rt_config.h"
/*BaSizeArray follows the 802.11n definition as MaxRxFactor. 2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8.*/
UCHAR BaSizeArray[4] = {8,16,32,64};
extern COUNTRY_REGION_CH_DESC Country_Region_ChDesc_2GHZ[];
extern UINT16 const Country_Region_GroupNum_2GHZ;
extern COUNTRY_REGION_CH_DESC Country_Region_ChDesc_5GHZ[];
extern UINT16 const Country_Region_GroupNum_5GHZ;
/*
==========================================================================
Description:
Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type,
and 3) PHY-mode user selected.
The outcome is used by driver when doing site survey.
IRQL = PASSIVE_LEVEL
IRQL = DISPATCH_LEVEL
==========================================================================
*/
VOID BuildChannelList(RTMP_ADAPTER *pAd)
{
UCHAR i, j, index=0, num=0;
PCH_DESC pChDesc = NULL;
BOOLEAN bRegionFound = FALSE;
PUCHAR pChannelList;
PUCHAR pChannelListFlag;
NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER));
/* if not 11a-only mode, channel list starts from 2.4Ghz band*/
if (!WMODE_5G_ONLY(pAd->CommonCfg.PhyMode))
{
for (i = 0; i < Country_Region_GroupNum_2GHZ; i++)
{
if ((pAd->CommonCfg.CountryRegion & 0x7f) ==
Country_Region_ChDesc_2GHZ[i].RegionIndex)
{
pChDesc = Country_Region_ChDesc_2GHZ[i].pChDesc;
num = TotalChNum(pChDesc);
bRegionFound = TRUE;
break;
}
}
if (!bRegionFound)
{
DBGPRINT(RT_DEBUG_ERROR,("CountryRegion=%d not support", pAd->CommonCfg.CountryRegion));
return;
}
if (num > 0)
{
os_alloc_mem(NULL, (UCHAR **)&pChannelList, num * sizeof(UCHAR));
if (!pChannelList)
{
DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelList failed\n", __FUNCTION__));
return;
}
os_alloc_mem(NULL, (UCHAR **)&pChannelListFlag, num * sizeof(UCHAR));
if (!pChannelListFlag)
{
DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelListFlag failed\n", __FUNCTION__));
os_free_mem(NULL, pChannelList);
return;
}
for (i = 0; i < num; i++)
{
pChannelList[i] = GetChannel_2GHZ(pChDesc, i);
pChannelListFlag[i] = GetChannelFlag(pChDesc, i);
}
for (i = 0; i < num; i++)
{
for (j = 0; j < MAX_NUM_OF_CHANNELS; j++)
{
if (pChannelList[i] == pAd->TxPower[j].Channel)
NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER));
pAd->ChannelList[index + i].Flags = pChannelListFlag[i];
}
#ifdef DOT11_N_SUPPORT
if (N_ChannelGroupCheck(pAd, pAd->ChannelList[index + i].Channel))
pAd->ChannelList[index + i].Flags |= CHANNEL_40M_CAP;
#ifdef DOT11_VHT_AC
if (vht80_channel_group(pAd, pAd->ChannelList[index + i].Channel))
pAd->ChannelList[index + i].Flags |= CHANNEL_80M_CAP;
#endif /* DOT11_VHT_AC */
#endif /* DOT11_N_SUPPORT */
pAd->ChannelList[index+i].MaxTxPwr = 20;
}
index += num;
os_free_mem(NULL, pChannelList);
os_free_mem(NULL, pChannelListFlag);
}
bRegionFound = FALSE;
num = 0;
}
if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode))
{
for (i = 0; i < Country_Region_GroupNum_5GHZ; i++)
{
if ((pAd->CommonCfg.CountryRegionForABand & 0x7f) ==
Country_Region_ChDesc_5GHZ[i].RegionIndex)
{
pChDesc = Country_Region_ChDesc_5GHZ[i].pChDesc;
num = TotalChNum(pChDesc);
bRegionFound = TRUE;
break;
}
}
if (!bRegionFound)
{
DBGPRINT(RT_DEBUG_ERROR,("CountryRegionABand=%d not support", pAd->CommonCfg.CountryRegionForABand));
return;
}
if (num > 0)
{
UCHAR RadarCh[16]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144};
#ifdef CONFIG_AP_SUPPORT
UCHAR q=0;
#endif /* CONFIG_AP_SUPPORT */
os_alloc_mem(NULL, (UCHAR **)&pChannelList, num * sizeof(UCHAR));
if (!pChannelList)
{
DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelList failed\n", __FUNCTION__));
return;
}
os_alloc_mem(NULL, (UCHAR **)&pChannelListFlag, num * sizeof(UCHAR));
if (!pChannelListFlag)
{
DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelListFlag failed\n", __FUNCTION__));
os_free_mem(NULL, pChannelList);
return;
}
for (i = 0; i < num; i++)
{
pChannelList[i] = GetChannel_5GHZ(pChDesc, i);
pChannelListFlag[i] = GetChannelFlag(pChDesc, i);
}
#ifdef CONFIG_AP_SUPPORT
for (i = 0; i < num; i++)
{
if((pAd->CommonCfg.bIEEE80211H == 0)|| ((pAd->CommonCfg.bIEEE80211H == 1) && (pAd->CommonCfg.RDDurRegion != FCC)))
{
pChannelList[q] = GetChannel_5GHZ(pChDesc, i);
pChannelListFlag[q] = GetChannelFlag(pChDesc, i);
q++;
}
/*Based on the requiremnt of FCC, some channles could not be used anymore when test DFS function.*/
else if ((pAd->CommonCfg.bIEEE80211H == 1) &&
(pAd->CommonCfg.RDDurRegion == FCC) &&
(pAd->Dot11_H.bDFSIndoor == 1))
{
if((GetChannel_5GHZ(pChDesc, i) < 116) || (GetChannel_5GHZ(pChDesc, i) > 128))
{
pChannelList[q] = GetChannel_5GHZ(pChDesc, i);
pChannelListFlag[q] = GetChannelFlag(pChDesc, i);
q++;
}
}
else if ((pAd->CommonCfg.bIEEE80211H == 1) &&
(pAd->CommonCfg.RDDurRegion == FCC) &&
(pAd->Dot11_H.bDFSIndoor == 0))
{
if((GetChannel_5GHZ(pChDesc, i) < 100) || (GetChannel_5GHZ(pChDesc, i) > 140) )
{
pChannelList[q] = GetChannel_5GHZ(pChDesc, i);
pChannelListFlag[q] = GetChannelFlag(pChDesc, i);
q++;
}
}
}
num = q;
#endif /* CONFIG_AP_SUPPORT */
for (i=0; i<num; i++)
{
for (j=0; j<MAX_NUM_OF_CHANNELS; j++)
{
if (pChannelList[i] == pAd->TxPower[j].Channel)
NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER));
pAd->ChannelList[index + i].Flags = pChannelListFlag[i];
}
#ifdef DOT11_N_SUPPORT
if (N_ChannelGroupCheck(pAd, pAd->ChannelList[index + i].Channel))
pAd->ChannelList[index + i].Flags |= CHANNEL_40M_CAP;
#ifdef DOT11_VHT_AC
if (vht80_channel_group(pAd, pAd->ChannelList[index + i].Channel))
pAd->ChannelList[index + i].Flags |= CHANNEL_80M_CAP;
#endif /* DOT11_VHT_AC */
#endif /* DOT11_N_SUPPORT */
for (j=0; j<16; j++)
{
if (pChannelList[i] == RadarCh[j])
{
pAd->ChannelList[index+i].DfsReq = TRUE;
#ifdef SMART_MESH
pAd->ChannelList[index+i].bDfsAPExist = FALSE;
#endif /* SMART_MESH */
}
}
#ifdef SMART_MESH
pAd->ChannelList[index+i].FalseCCA = 0;
#endif /* SMART_MESH */
pAd->ChannelList[index+i].MaxTxPwr = 20;
}
index += num;
os_free_mem(NULL, pChannelList);
os_free_mem(NULL, pChannelListFlag);
}
}
pAd->ChannelListNum = index;
DBGPRINT(RT_DEBUG_TRACE,("country code=%d/%d, RFIC=%d, PHY mode=%d, support %d channels\n",
pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryRegionForABand, pAd->RfIcType, pAd->CommonCfg.PhyMode, pAd->ChannelListNum));
#ifdef RT_CFG80211_SUPPORT
for (i=0;i<pAd->ChannelListNum;i++)
{
CFG80211OS_ChanInfoInit(
pAd->pCfg80211_CB,
i,
pAd->ChannelList[i].Channel,
pAd->ChannelList[i].MaxTxPwr,
WMODE_CAP_N(pAd->CommonCfg.PhyMode),
(pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20));
}
#endif /* RT_CFG80211_SUPPORT */
#ifdef DBG
for (i=0;i<pAd->ChannelListNum;i++)
{
DBGPRINT_RAW(RT_DEBUG_TRACE,("BuildChannel # %d :: Pwr0 = %d, Pwr1 =%d, Flags = %x\n ",
pAd->ChannelList[i].Channel,
pAd->ChannelList[i].Power,
pAd->ChannelList[i].Power2,
pAd->ChannelList[i].Flags));
}
#endif
}
/*
==========================================================================
Description:
This routine return the first channel number according to the country
code selection and RF IC selection (signal band or dual band). It is called
whenever driver need to start a site survey of all supported channels.
Return:
ch - the first channel number of current country code setting
IRQL = PASSIVE_LEVEL
==========================================================================
*/
UCHAR FirstChannel(RTMP_ADAPTER *pAd)
{
return pAd->ChannelList[0].Channel;
}
/*
==========================================================================
Description:
This routine returns the next channel number. This routine is called
during driver need to start a site survey of all supported channels.
Return:
next_channel - the next channel number valid in current country code setting.
Note:
return 0 if no more next channel
==========================================================================
*/
UCHAR NextChannel(RTMP_ADAPTER *pAd, UCHAR channel)
{
int i;
UCHAR next_channel = 0;
for (i = 0; i < (pAd->ChannelListNum - 1); i++)
{
if (channel == pAd->ChannelList[i].Channel)
{
#ifdef DOT11_N_SUPPORT
#ifdef DOT11N_DRAFT3
/* Only scan effected channel if this is a SCAN_2040_BSS_COEXIST*/
/* 2009 PF#2: Nee to handle the second channel of AP fall into affected channel range.*/
if ((pAd->MlmeAux.ScanType == SCAN_2040_BSS_COEXIST) && (pAd->ChannelList[i+1].Channel >14))
{
channel = pAd->ChannelList[i+1].Channel;
continue;
}
else
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
{
/* Record this channel's idx in ChannelList array.*/
next_channel = pAd->ChannelList[i+1].Channel;
break;
}
}
}
return next_channel;
}
/*
==========================================================================
Description:
Return:
scan_channel - channel to scan.
Note:
return 0 if no more next channel
==========================================================================
*/
UCHAR RTMPFindScanChannel(
IN PRTMP_ADAPTER pAd,
UINT8 LastScanChannel)
{
UCHAR scan_channel = 0;
#ifdef CONFIG_AP_SUPPORT
#ifdef AP_PARTIAL_SCAN_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
{
if (pAd->ApCfg.bPartialScanning == TRUE)
{
scan_channel = FindPartialScanChannel(pAd);
return scan_channel;
}
}
#endif /* AP_PARTIAL_SCAN_SUPPORT */
#endif /* CONFIG_AP_SUPPORT */
if (LastScanChannel == 0)
scan_channel = FirstChannel(pAd);
else
scan_channel = NextChannel(pAd, LastScanChannel);
return scan_channel;
}
/*
==========================================================================
Description:
This routine is for Cisco Compatible Extensions 2.X
Spec31. AP Control of Client Transmit Power
Return:
None
Note:
Required by Aironet dBm(mW)
0dBm(1mW), 1dBm(5mW), 13dBm(20mW), 15dBm(30mW),
17dBm(50mw), 20dBm(100mW)
We supported
3dBm(Lowest), 6dBm(10%), 9dBm(25%), 12dBm(50%),
14dBm(75%), 15dBm(100%)
The client station's actual transmit power shall be within +/- 5dB of
the minimum value or next lower value.
==========================================================================
*/
VOID ChangeToCellPowerLimit(RTMP_ADAPTER *pAd, UCHAR AironetCellPowerLimit)
{
/*
valud 0xFF means that hasn't found power limit information
from the AP's Beacon/Probe response
*/
if (AironetCellPowerLimit == 0xFF)
return;
if (AironetCellPowerLimit < 6) /*Used Lowest Power Percentage.*/
pAd->CommonCfg.TxPowerPercentage = 6;
else if (AironetCellPowerLimit < 9)
pAd->CommonCfg.TxPowerPercentage = 10;
else if (AironetCellPowerLimit < 12)
pAd->CommonCfg.TxPowerPercentage = 25;
else if (AironetCellPowerLimit < 14)
pAd->CommonCfg.TxPowerPercentage = 50;
else if (AironetCellPowerLimit < 15)
pAd->CommonCfg.TxPowerPercentage = 75;
else
pAd->CommonCfg.TxPowerPercentage = 100; /*else used maximum*/
if (pAd->CommonCfg.TxPowerPercentage > pAd->CommonCfg.TxPowerDefault)
pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault;
}
CHAR ConvertToRssi(RTMP_ADAPTER *pAd, CHAR Rssi, UCHAR rssi_idx)
{
UCHAR RssiOffset, LNAGain;
CHAR BaseVal;
/* Rssi equals to zero or rssi_idx larger than 3 should be an invalid value*/
if (Rssi == 0 || rssi_idx >= 3)
return -99;
LNAGain = GET_LNA_GAIN(pAd);
if (pAd->LatchRfRegs.Channel > 14)
RssiOffset = pAd->ARssiOffset[rssi_idx];
else
RssiOffset = pAd->BGRssiOffset[rssi_idx];
BaseVal = -12;
#ifdef RT6352
if (IS_RT6352(pAd))
BaseVal = -2;
#endif /* RT6352 */
#ifdef RT65xx
/*
Recommended by CSD team about MT76x0:
SW/QA owners should read the "external-LNA gain" and "RSSI OFFSET" content in EEPROM as "SIGNED".
2.4G : RSSI_report = RSSI_bpp + EEPROM_0x46[15:8 or 7:0] - EEPROM_0x44[7:0]
5G : RSSI_report = RSSI_bbp + EEPROM_0x4A[15:8 or 7:0] - EEPROM_0x44 or 0x48 or 0x4c[15:8]
*/
if (IS_MT76x0(pAd))
return (Rssi + (CHAR)RssiOffset - (CHAR)LNAGain);
if (IS_MT76x2(pAd)) {
CHAR extra_gain = 0;
if (LNAGain & 0x80) {
if (LNAGain == 0xFF)
LNAGain = 0;
else
LNAGain &= 0x7F;
extra_gain = LNAGain;
} else
extra_gain = 0 - (CHAR)LNAGain;
if (is_external_lna_mode(pAd, pAd->CommonCfg.Channel) == TRUE)
extra_gain = LNAGain = 0;
if (pAd->LatchRfRegs.Channel > 14)
return (Rssi + pAd->ARssiOffset[rssi_idx] - extra_gain);
else
return (Rssi + pAd->BGRssiOffset[rssi_idx] - extra_gain);
}
if (IS_RT8592(pAd))
return (Rssi - LNAGain - RssiOffset);
#endif /* RT65xx */
return (BaseVal - RssiOffset - LNAGain - Rssi);
}
CHAR ConvertToSnr(RTMP_ADAPTER *pAd, UCHAR Snr)
{
if (pAd->chipCap.SnrFormula == SNR_FORMULA2)
return (Snr * 3 + 8) >> 4;
else if (pAd->chipCap.SnrFormula == SNR_FORMULA3)
return (Snr * 3 / 16 ); /* * 0.1881 */
else
return ((0xeb - Snr) * 3) / 16 ;
}
#ifdef CONFIG_AP_SUPPORT
#ifdef DOT11_N_SUPPORT
#ifdef DOT11N_DRAFT3
extern int DetectOverlappingPeriodicRound;
VOID Handle_BSS_Width_Trigger_Events(RTMP_ADAPTER *pAd)
{
ULONG Now32;
#ifdef DOT11N_DRAFT3
if (pAd->CommonCfg.bBssCoexEnable == FALSE)
return;
#endif
if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) &&
(pAd->CommonCfg.Channel <=14))
{
DBGPRINT(RT_DEBUG_TRACE, ("Rcv BSS Width Trigger Event: 40Mhz --> 20Mhz \n"));
NdisGetSystemUpTime(&Now32);
pAd->CommonCfg.LastRcvBSSWidthTriggerEventsTime = Now32;
pAd->CommonCfg.bRcvBSSWidthTriggerEvents = TRUE;
pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0;
pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0;
DetectOverlappingPeriodicRound = 31;
}
}
#endif /* DOT11N_DRAFT3 */
#endif /* DOT11_N_SUPPORT */
#endif /* CONFIG_AP_SUPPORT */

View File

@ -0,0 +1,944 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2004, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
cmm_tkip.c
Abstract:
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Paul Wu 02-25-02 Initial
*/
#include "rt_config.h"
/* Rotation functions on 32 bit values */
#define ROL32( A, n ) \
( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) )
#define ROR32( A, n ) ROL32( (A), 32-(n) )
UINT Tkip_Sbox_Lower[256] =
{
0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54,
0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A,
0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B,
0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B,
0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F,
0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F,
0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5,
0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F,
0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB,
0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97,
0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED,
0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A,
0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94,
0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3,
0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04,
0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D,
0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39,
0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95,
0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83,
0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76,
0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4,
0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B,
0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0,
0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18,
0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51,
0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85,
0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12,
0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9,
0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7,
0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A,
0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8,
0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A
};
UINT Tkip_Sbox_Upper[256] =
{
0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91,
0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC,
0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB,
0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B,
0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83,
0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A,
0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F,
0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA,
0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B,
0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13,
0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6,
0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85,
0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11,
0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B,
0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1,
0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF,
0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E,
0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6,
0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B,
0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD,
0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8,
0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2,
0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49,
0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10,
0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97,
0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F,
0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C,
0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27,
0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33,
0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5,
0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0,
0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C
};
/* Expanded IV for TKIP function.*/
typedef struct GNU_PACKED _IV_CONTROL_
{
union GNU_PACKED
{
struct GNU_PACKED
{
UCHAR rc0;
UCHAR rc1;
UCHAR rc2;
union GNU_PACKED
{
struct GNU_PACKED
{
#ifdef RT_BIG_ENDIAN
UCHAR KeyID:2;
UCHAR ExtIV:1;
UCHAR Rsvd:5;
#else
UCHAR Rsvd:5;
UCHAR ExtIV:1;
UCHAR KeyID:2;
#endif
} field;
UCHAR Byte;
} CONTROL;
} field;
ULONG word;
} IV16;
ULONG IV32;
} TKIP_IV, *PTKIP_IV;
/*
========================================================================
Routine Description:
Convert from UCHAR[] to ULONG in a portable way
Arguments:
pMICKey pointer to MIC Key
Return Value:
None
Note:
========================================================================
*/
ULONG RTMPTkipGetUInt32(
IN PUCHAR pMICKey)
{
ULONG res = 0;
INT i;
for (i = 0; i < 4; i++)
{
res |= (*pMICKey++) << (8 * i);
}
return res;
}
/*
========================================================================
Routine Description:
Convert from ULONG to UCHAR[] in a portable way
Arguments:
pDst pointer to destination for convert ULONG to UCHAR[]
val the value for convert
Return Value:
None
IRQL = DISPATCH_LEVEL
Note:
========================================================================
*/
VOID RTMPTkipPutUInt32(
IN OUT PUCHAR pDst,
IN ULONG val)
{
INT i;
for(i = 0; i < 4; i++)
{
*pDst++ = (UCHAR) (val & 0xff);
val >>= 8;
}
}
/*
========================================================================
Routine Description:
Set the MIC Key.
Arguments:
pAd Pointer to our adapter
pMICKey pointer to MIC Key
Return Value:
None
IRQL = DISPATCH_LEVEL
Note:
========================================================================
*/
VOID RTMPTkipSetMICKey(
IN PTKIP_KEY_INFO pTkip,
IN PUCHAR pMICKey)
{
/* Set the key */
pTkip->K0 = RTMPTkipGetUInt32(pMICKey);
pTkip->K1 = RTMPTkipGetUInt32(pMICKey + 4);
/* and reset the message */
pTkip->L = pTkip->K0;
pTkip->R = pTkip->K1;
pTkip->nBytesInM = 0;
pTkip->M = 0;
}
/*
========================================================================
Routine Description:
Calculate the MIC Value.
Arguments:
pAd Pointer to our adapter
uChar Append this uChar
Return Value:
None
IRQL = DISPATCH_LEVEL
Note:
========================================================================
*/
VOID RTMPTkipAppendByte(
IN PTKIP_KEY_INFO pTkip,
IN UCHAR uChar)
{
/* Append the byte to our word-sized buffer */
pTkip->M |= (uChar << (8* pTkip->nBytesInM));
pTkip->nBytesInM++;
/* Process the word if it is full. */
if( pTkip->nBytesInM >= 4 )
{
pTkip->L ^= pTkip->M;
pTkip->R ^= ROL32( pTkip->L, 17 );
pTkip->L += pTkip->R;
pTkip->R ^= ((pTkip->L & 0xff00ff00) >> 8) | ((pTkip->L & 0x00ff00ff) << 8);
pTkip->L += pTkip->R;
pTkip->R ^= ROL32( pTkip->L, 3 );
pTkip->L += pTkip->R;
pTkip->R ^= ROR32( pTkip->L, 2 );
pTkip->L += pTkip->R;
/* Clear the buffer */
pTkip->M = 0;
pTkip->nBytesInM = 0;
}
}
/*
========================================================================
Routine Description:
Calculate the MIC Value.
Arguments:
pAd Pointer to our adapter
pSrc Pointer to source data for Calculate MIC Value
Len Indicate the length of the source data
Return Value:
None
IRQL = DISPATCH_LEVEL
Note:
========================================================================
*/
VOID RTMPTkipAppend(
IN PTKIP_KEY_INFO pTkip,
IN PUCHAR pSrc,
IN UINT nBytes)
{
/* This is simple */
while(nBytes > 0)
{
RTMPTkipAppendByte(pTkip, *pSrc++);
nBytes--;
}
}
/*
========================================================================
Routine Description:
Get the MIC Value.
Arguments:
pAd Pointer to our adapter
Return Value:
None
IRQL = DISPATCH_LEVEL
Note:
the MIC Value is store in pAd->PrivateInfo.MIC
========================================================================
*/
VOID RTMPTkipGetMIC(
IN PTKIP_KEY_INFO pTkip)
{
/* Append the minimum padding*/
RTMPTkipAppendByte(pTkip, 0x5a );
RTMPTkipAppendByte(pTkip, 0 );
RTMPTkipAppendByte(pTkip, 0 );
RTMPTkipAppendByte(pTkip, 0 );
RTMPTkipAppendByte(pTkip, 0 );
/* and then zeroes until the length is a multiple of 4 */
while( pTkip->nBytesInM != 0 )
{
RTMPTkipAppendByte(pTkip, 0 );
}
/* The appendByte function has already computed the result. */
RTMPTkipPutUInt32(pTkip->MIC, pTkip->L);
RTMPTkipPutUInt32(pTkip->MIC + 4, pTkip->R);
}
/*
========================================================================
Routine Description:
Init MIC Value calculation function which include set MIC key &
calculate first 16 bytes (DA + SA + priority + 0)
Arguments:
pAd Pointer to our adapter
pTKey Pointer to the Temporal Key (TK), TK shall be 128bits.
pDA Pointer to DA address
pSA Pointer to SA address
pMICKey pointer to MIC Key
Return Value:
None
Note:
========================================================================
*/
VOID RTMPInitMICEngine(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pKey,
IN PUCHAR pDA,
IN PUCHAR pSA,
IN UCHAR UserPriority,
IN PUCHAR pMICKey)
{
ULONG Priority = UserPriority;
/* Init MIC value calculation*/
RTMPTkipSetMICKey(&pAd->PrivateInfo.Tx, pMICKey);
/* DA*/
RTMPTkipAppend(&pAd->PrivateInfo.Tx, pDA, MAC_ADDR_LEN);
/* SA*/
RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSA, MAC_ADDR_LEN);
/* Priority + 3 bytes of 0*/
RTMPTkipAppend(&pAd->PrivateInfo.Tx, (PUCHAR)&Priority, 4);
}
/*
========================================================================
Routine Description:
Compare MIC value of received MSDU
Arguments:
pAd Pointer to our adapter
pSrc Pointer to the received Plain text data
pDA Pointer to DA address
pSA Pointer to SA address
pMICKey pointer to MIC Key
Len the length of the received plain text data exclude MIC value
Return Value:
TRUE MIC value matched
FALSE MIC value mismatched
IRQL = DISPATCH_LEVEL
Note:
========================================================================
*/
BOOLEAN RTMPTkipCompareMICValue(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pSrc,
IN PUCHAR pDA,
IN PUCHAR pSA,
IN PUCHAR pMICKey,
IN UCHAR UserPriority,
IN UINT Len)
{
UCHAR OldMic[8];
ULONG Priority = UserPriority;
/* Init MIC value calculation*/
RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey);
/* DA*/
RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN);
/* SA*/
RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN);
/* Priority + 3 bytes of 0*/
RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4);
/* Calculate MIC value from plain text data*/
RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len);
/* Get MIC valude from received frame*/
NdisMoveMemory(OldMic, pSrc + Len, 8);
/* Get MIC value from decrypted plain data*/
RTMPTkipGetMIC(&pAd->PrivateInfo.Rx);
/* Move MIC value from MSDU, this steps should move to data path.*/
/* Since the MIC value might cross MPDUs.*/
if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8))
{
DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValue(): TKIP MIC Error !\n")); /*MIC error.*/
return (FALSE);
}
return (TRUE);
}
/*
========================================================================
Routine Description:
Copy frame from waiting queue into relative ring buffer and set
appropriate ASIC register to kick hardware transmit function
Arguments:
pAd Pointer to our adapter
PNDIS_PACKET Pointer to Ndis Packet for MIC calculation
pEncap Pointer to LLC encap data
LenEncap Total encap length, might be 0 which indicates no encap
Return Value:
None
IRQL = DISPATCH_LEVEL
Note:
========================================================================
*/
VOID RTMPCalculateMICValue(
IN PRTMP_ADAPTER pAd,
IN PNDIS_PACKET pPacket,
IN PUCHAR pEncap,
IN PCIPHER_KEY pKey,
IN UCHAR apidx)
{
PACKET_INFO PacketInfo;
PUCHAR pSrcBufVA;
UINT SrcBufLen;
PUCHAR pSrc;
UCHAR UserPriority;
UCHAR vlan_offset = 0;
RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen);
UserPriority = RTMP_GET_PACKET_UP(pPacket);
pSrc = pSrcBufVA;
/* determine if this is a vlan packet */
if (((*(pSrc + 12) << 8) + *(pSrc + 13)) == 0x8100)
vlan_offset = 4;
#ifdef CONFIG_AP_SUPPORT
#ifdef APCLI_SUPPORT
/* Start Calculate MIC Value*/
if (apidx >= MIN_NET_DEVICE_FOR_APCLI && ((apidx - MIN_NET_DEVICE_FOR_APCLI) < MAX_APCLI_NUM) && (pAd->OpMode == OPMODE_AP))
{ /* For packet which need to do MATConvert, we need to use the CurrentAddress of specific ApCli interface.*/
RTMPInitMICEngine(
pAd,
pKey->Key,
pSrc,
pAd->ApCfg.ApCliTab[apidx-MIN_NET_DEVICE_FOR_APCLI].wdev.if_addr,
UserPriority,
pKey->TxMic);
}
else
#endif /* APCLI_SUPPORT */
#ifdef IGMP_SNOOP_SUPPORT
if ((RTMP_GET_PACKET_WCID(pPacket) != MCAST_WCID) && (*pSrc & 0x01) && (pAd->OpMode == OPMODE_AP))
{
UCHAR wcid = RTMP_GET_PACKET_WCID(pPacket);
RTMPInitMICEngine(
pAd,
pKey->Key,
pAd->MacTab.Content[wcid].Addr,
pSrc + 6,
UserPriority,
pKey->TxMic);
}
else
#endif /* IGMP_SNOOP_SUPPORT */
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
#ifdef ETH_CONVERT_SUPPORT
/* If the packet is need to do MATConvert in station mode, the "apidx" used for indicate "pkt->bDonglePkt"; */
if ((apidx > 0) && (pAd->OpMode == OPMODE_STA))
{ /* For packets which need to do MATConvert, we need to use the pAd->CurrentAddress to calculate the MIC.*/
RTMPInitMICEngine(
pAd,
pKey->Key,
pSrc,
pAd->CurrentAddress,
UserPriority,
pKey->TxMic);
}
else
#endif /* ETH_CONVERT_SUPPORT */
#endif /* CONFIG_STA_SUPPORT */
{
RTMPInitMICEngine(
pAd,
pKey->Key,
pSrc,
pSrc + 6,
UserPriority,
pKey->TxMic);
}
if (pEncap != NULL)
{
/* LLC encapsulation*/
RTMPTkipAppend(&pAd->PrivateInfo.Tx, pEncap, 6);
/* Protocol Type*/
RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc + 12 + vlan_offset, 2);
}
SrcBufLen -= (14 + vlan_offset);
pSrc += (14 + vlan_offset);
do
{
if (SrcBufLen > 0)
{
RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc, SrcBufLen);
}
break; /* No need handle next packet */
} while (TRUE);
/* Compute the final MIC Value*/
RTMPTkipGetMIC(&pAd->PrivateInfo.Tx);
}
/************************************************************/
/* tkip_sbox() */
/* Returns a 16 bit value from a 64K entry table. The Table */
/* is synthesized from two 256 entry byte wide tables. */
/************************************************************/
UINT tkip_sbox(UINT index)
{
UINT index_low;
UINT index_high;
UINT left, right;
index_low = (index % 256);
index_high = ((index >> 8) % 256);
left = Tkip_Sbox_Lower[index_low] + (Tkip_Sbox_Upper[index_low] * 256);
right = Tkip_Sbox_Upper[index_high] + (Tkip_Sbox_Lower[index_high] * 256);
return (left ^ right);
}
UINT rotr1(UINT a)
{
unsigned int b;
if ((a & 0x01) == 0x01)
{
b = (a >> 1) | 0x8000;
}
else
{
b = (a >> 1) & 0x7fff;
}
b = b % 65536;
return b;
}
VOID RTMPTkipMixKey(
UCHAR *key,
UCHAR *ta,
ULONG pnl, /* Least significant 16 bits of PN */
ULONG pnh, /* Most significant 32 bits of PN */
UCHAR *rc4key,
UINT *p1k)
{
UINT tsc0;
UINT tsc1;
UINT tsc2;
UINT ppk0;
UINT ppk1;
UINT ppk2;
UINT ppk3;
UINT ppk4;
UINT ppk5;
INT i;
INT j;
tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */
tsc1 = (unsigned int)(pnh % 65536);
tsc2 = (unsigned int)(pnl % 65536); /* lsb */
/* Phase 1, step 1 */
p1k[0] = tsc1;
p1k[1] = tsc0;
p1k[2] = (UINT)(ta[0] + (ta[1]*256));
p1k[3] = (UINT)(ta[2] + (ta[3]*256));
p1k[4] = (UINT)(ta[4] + (ta[5]*256));
/* Phase 1, step 2 */
for (i=0; i<8; i++)
{
j = 2*(i & 1);
p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((256*key[1+j]) + key[j])) % 65536 )) % 65536;
p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((256*key[5+j]) + key[4+j])) % 65536 )) % 65536;
p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((256*key[9+j]) + key[8+j])) % 65536 )) % 65536;
p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((256*key[13+j]) + key[12+j])) % 65536 )) % 65536;
p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((256*key[1+j]) + key[j]))) % 65536 )) % 65536;
p1k[4] = (p1k[4] + i) % 65536;
}
/* Phase 2, Step 1 */
ppk0 = p1k[0];
ppk1 = p1k[1];
ppk2 = p1k[2];
ppk3 = p1k[3];
ppk4 = p1k[4];
ppk5 = (p1k[4] + tsc2) % 65536;
/* Phase2, Step 2 */
ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((256*key[1]) + key[0])) % 65536);
ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((256*key[3]) + key[2])) % 65536);
ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((256*key[5]) + key[4])) % 65536);
ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((256*key[7]) + key[6])) % 65536);
ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((256*key[9]) + key[8])) % 65536);
ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((256*key[11]) + key[10])) % 65536);
ppk0 = ppk0 + rotr1(ppk5 ^ ((256*key[13]) + key[12]));
ppk1 = ppk1 + rotr1(ppk0 ^ ((256*key[15]) + key[14]));
ppk2 = ppk2 + rotr1(ppk1);
ppk3 = ppk3 + rotr1(ppk2);
ppk4 = ppk4 + rotr1(ppk3);
ppk5 = ppk5 + rotr1(ppk4);
/* Phase 2, Step 3 */
/* Phase 2, Step 3 */
tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */
tsc1 = (unsigned int)(pnh % 65536);
tsc2 = (unsigned int)(pnl % 65536); /* lsb */
rc4key[0] = (tsc2 >> 8) % 256;
rc4key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f;
rc4key[2] = tsc2 % 256;
rc4key[3] = ((ppk5 ^ ((256*key[1]) + key[0])) >> 1) % 256;
rc4key[4] = ppk0 % 256;
rc4key[5] = (ppk0 >> 8) % 256;
rc4key[6] = ppk1 % 256;
rc4key[7] = (ppk1 >> 8) % 256;
rc4key[8] = ppk2 % 256;
rc4key[9] = (ppk2 >> 8) % 256;
rc4key[10] = ppk3 % 256;
rc4key[11] = (ppk3 >> 8) % 256;
rc4key[12] = ppk4 % 256;
rc4key[13] = (ppk4 >> 8) % 256;
rc4key[14] = ppk5 % 256;
rc4key[15] = (ppk5 >> 8) % 256;
}
/*
TRUE: Success!
FALSE: Decrypt Error!
*/
NDIS_STATUS RTMPSoftDecryptTKIP(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pHdr,
IN UCHAR UserPriority,
IN PCIPHER_KEY pKey,
INOUT PUCHAR pData,
IN UINT16 *DataByteCnt)
{
PHEADER_802_11 pFrame;
UINT8 from_ds;
UINT8 to_ds;
UCHAR TA[MAC_ADDR_LEN];
UCHAR DA[MAC_ADDR_LEN];
UCHAR SA[MAC_ADDR_LEN];
UCHAR RC4Key[16];
UINT p1k[5]; /*for mix_key;*/
ULONG pnl;/* Least significant 16 bits of PN */
ULONG pnh;/* Most significant 32 bits of PN */
ARC4_CTX_STRUC ARC4_CTX;
PUCHAR plaintext_ptr;
UINT32 plaintext_len;
PUCHAR ciphertext_ptr;
UINT32 ciphertext_len;
UINT crc32 = 0;
UINT trailfcs = 0;
UCHAR MIC[8];
UCHAR TrailMIC[8];
#ifdef RT_BIG_ENDIAN
RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE);
#endif
if (pKey->KeyLen == 0)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s : the key is empty)\n", __FUNCTION__));
return NDIS_STATUS_FAILURE;
}
/* Indicate type and subtype of Frame Control field */
/* Indicate the fromDS and ToDS */
from_ds = ((*(pHdr + 1)) & 0x2) >> 1;
to_ds = ((*(pHdr + 1)) & 0x1);
/* pointer to 802.11 header */
pFrame = (PHEADER_802_11)pHdr;
/* Assign DA, SA and TA for TKIP calculation */
if (to_ds == 0 && from_ds == 1)
{
NdisMoveMemory(DA, pFrame->Addr1, MAC_ADDR_LEN);
NdisMoveMemory(TA, pFrame->Addr2, MAC_ADDR_LEN); /*BSSID */
NdisMoveMemory(SA, pFrame->Addr3, MAC_ADDR_LEN);
}
else if (to_ds == 0 && from_ds == 0 )
{
NdisMoveMemory(DA, pFrame->Addr1, MAC_ADDR_LEN);
NdisMoveMemory(TA, pFrame->Addr2, MAC_ADDR_LEN);
NdisMoveMemory(SA, pFrame->Addr2, MAC_ADDR_LEN);
}
else if (to_ds == 1 && from_ds == 0)
{
NdisMoveMemory(SA, pFrame->Addr2, MAC_ADDR_LEN);
NdisMoveMemory(TA, pFrame->Addr2, MAC_ADDR_LEN);
NdisMoveMemory(DA, pFrame->Addr3, MAC_ADDR_LEN);
}
else if (to_ds == 1 && from_ds == 1)
{
NdisMoveMemory(TA, pFrame->Addr2, MAC_ADDR_LEN);
NdisMoveMemory(DA, pFrame->Addr3, MAC_ADDR_LEN);
NdisMoveMemory(SA, pFrame->Octet, MAC_ADDR_LEN);
}
pnl = (*(pData)) << 8 | (*(pData + 2));
pnh = *((PULONG)(pData + 4));
pnh = cpu2le32(pnh);
RTMPTkipMixKey(pKey->Key, TA, pnl, pnh, RC4Key, p1k);
/* skip 8-bytes TKIP IV/EIV header */
ciphertext_ptr = pData + LEN_TKIP_IV_HDR;
ciphertext_len = *DataByteCnt - LEN_TKIP_IV_HDR;
/* skip payload length is zero*/
if ((*DataByteCnt) <= LEN_TKIP_IV_HDR)
return NDIS_STATUS_FAILURE;
/* WEP Decapsulation */
/* Generate an RC4 key stream */
ARC4_INIT(&ARC4_CTX, &RC4Key[0], 16);
/* Decrypt the TKIP MPDU by ARC4.
It shall include plaintext, MIC and ICV.
The result output would overwrite the original TKIP IV/EIV header position */
ARC4_Compute(&ARC4_CTX, ciphertext_ptr, ciphertext_len, pData);
/* Point to the decrypted data frame and its length shall exclude ICV length */
plaintext_ptr = pData;
plaintext_len = ciphertext_len - LEN_ICV;
/* Extract peer's ICV */
NdisMoveMemory(&trailfcs, plaintext_ptr + plaintext_len, LEN_ICV);
/* Re-computes the ICV and
bit-wise compares with the peer's ICV. */
crc32 = RTMP_CALC_FCS32(PPPINITFCS32, plaintext_ptr, plaintext_len);
crc32 ^= 0xffffffff; /* complement */
if(crc32 != cpu2le32(trailfcs))
{
DBGPRINT(RT_DEBUG_ERROR, ("! WEP Data CRC Error !\n")); /*CRC error.*/
return NDIS_STATUS_FAILURE;
}
/* Extract peer's MIC and subtract MIC length from total data length */
plaintext_len -= LEN_TKIP_MIC;
NdisMoveMemory(TrailMIC, plaintext_ptr + plaintext_len, LEN_TKIP_MIC);
RTMPInitMICEngine(pAd, pKey->Key, DA, SA, UserPriority, pKey->RxMic);
RTMPTkipAppend(&pAd->PrivateInfo.Tx, plaintext_ptr, plaintext_len);
RTMPTkipGetMIC(&pAd->PrivateInfo.Tx);
NdisMoveMemory(MIC, pAd->PrivateInfo.Tx.MIC, LEN_TKIP_MIC);
if (!NdisEqualMemory(MIC, TrailMIC, LEN_TKIP_MIC))
{
DBGPRINT(RT_DEBUG_ERROR, ("! TKIP MIC Error !\n")); /*MIC error.*/
#ifdef CONFIG_STA_SUPPORT
/*RTMPReportMicError(pAd, &pWpaKey[KeyID]); marked by AlbertY @ 20060630 */
#ifdef WPA_SUPPLICANT_SUPPORT
if (pAd->StaCfg.wpa_supplicant_info.WpaSupplicantUP) {
WpaSendMicFailureToWpaSupplicant(pAd->net_dev, pFrame->Addr2,
(pKey->Type == PAIRWISEKEY) ? TRUE : FALSE,
0 /*key id need be retrived by IV, actually supplicant didn't need it!*/,
NULL);
} else
#endif /* WPA_SUPPLICANT_SUPPORT */
RTMPReportMicError(pAd, pKey);
#endif /* CONFIG_STA_SUPPORT */
return NDIS_STATUS_MICERROR;
}
/* Update the total data length */
*DataByteCnt = plaintext_len;
#ifdef RT_BIG_ENDIAN
RTMPFrameEndianChange(pAd, pHdr, DIR_READ, FALSE);
#endif
return NDIS_STATUS_SUCCESS;
}
/*
========================================================================
Routine Description:
Use RC4 to protect the Key Data field of EAPoL frame.
It's defined in IEEE 802.11i-2004 p.84
Arguments:
Return Value:
None
Note:
========================================================================
*/
VOID TKIP_GTK_KEY_WRAP(
IN UCHAR *key,
IN UCHAR *iv,
IN UCHAR *input_text,
IN UINT32 input_len,
OUT UCHAR *output_text)
{
UCHAR ekey[LEN_KEY_DESC_IV + LEN_PTK_KEK];
/* ARC4_CTX_STRUC ARC4_CTX;*/
ARC4_CTX_STRUC *pARC4_CTX = NULL;
/* allocate memory */
os_alloc_mem(NULL, (UCHAR **)&pARC4_CTX, sizeof(ARC4_CTX_STRUC));
if (pARC4_CTX == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
return;
}
/* The encryption key is generated by concatenating the
EAPOL-Key IV field and the KEK. */
NdisMoveMemory(ekey, iv, LEN_KEY_DESC_IV);
NdisMoveMemory(&ekey[LEN_KEY_DESC_IV], key, LEN_PTK_KEK);
/* RC4 stream cipher initialization with the KEK */
ARC4_INIT(pARC4_CTX, &ekey[0], LEN_KEY_DESC_IV + LEN_PTK_KEK);
/* The first 256 octets of the RC4 key stream shall be discarded */
ARC4_Discard_KeyLength(pARC4_CTX, 256);
/* encryption begins using the 257th key stream octet */
ARC4_Compute(pARC4_CTX, input_text, input_len, output_text);
if (pARC4_CTX != NULL)
os_free_mem(NULL, pARC4_CTX);
}
VOID TKIP_GTK_KEY_UNWRAP(
IN UCHAR *key,
IN UCHAR *iv,
IN UCHAR *input_text,
IN UINT32 input_len,
OUT UCHAR *output_text)
{
TKIP_GTK_KEY_WRAP(key, iv, input_text, input_len, output_text);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,168 @@
/****************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
****************************************************************************
Module Name:
cmm_video.c
Abstract:
Ralink WiFi Driver video mode related subroutines
Revision History:
Who When What
--------- ---------- ----------------------------------------------
*/
#include "rt_config.h"
#ifdef VIDEO_TURBINE_SUPPORT
BOOLEAN UpdateFromGlobal = FALSE;
void VideoTurbineUpdate(
IN PRTMP_ADAPTER pAd)
{
if (UpdateFromGlobal == TRUE)
{
pAd->VideoTurbine.Enable = GLOBAL_AP_VIDEO_CONFIG.Enable;
pAd->VideoTurbine.ClassifierEnable = GLOBAL_AP_VIDEO_CONFIG.ClassifierEnable;
pAd->VideoTurbine.HighTxMode = GLOBAL_AP_VIDEO_CONFIG.HighTxMode;
pAd->VideoTurbine.TxPwr = GLOBAL_AP_VIDEO_CONFIG.TxPwr;
pAd->VideoTurbine.VideoMCSEnable = GLOBAL_AP_VIDEO_CONFIG.VideoMCSEnable;
pAd->VideoTurbine.VideoMCS = GLOBAL_AP_VIDEO_CONFIG.VideoMCS;
pAd->VideoTurbine.TxBASize = GLOBAL_AP_VIDEO_CONFIG.TxBASize;
pAd->VideoTurbine.TxLifeTimeMode = GLOBAL_AP_VIDEO_CONFIG.TxLifeTimeMode;
pAd->VideoTurbine.TxLifeTime = GLOBAL_AP_VIDEO_CONFIG.TxLifeTime;
pAd->VideoTurbine.TxRetryLimit = GLOBAL_AP_VIDEO_CONFIG.TxRetryLimit;
}
}
VOID TxSwQDepthAdjust(IN RTMP_ADAPTER *pAd, IN UINT32 qLen)
{
ULONG IrqFlags;
INT qIdx;
QUEUE_HEADER *pTxQ, *pEntry;
PNDIS_PACKET pPacket;
RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
pAd->TxSwQMaxLen = qLen;
for (qIdx = 0; qIdx < NUM_OF_TX_RING; qIdx++)
{
pTxQ = &pAd->TxSwQueue[qIdx];
while(pTxQ->Number >= pAd->TxSwQMaxLen)
{
pEntry = RemoveHeadQueue(pTxQ);
if (pEntry)
{
pPacket = QUEUE_ENTRY_TO_PACKET(pEntry);
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
}
else
break;
}
}
RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
DBGPRINT(RT_DEBUG_OFF, ("%s():Set TxSwQMaxLen as %d\n",
__FUNCTION__, pAd->TxSwQMaxLen));
}
VOID VideoTurbineDynamicTune(
IN PRTMP_ADAPTER pAd)
{
if (pAd->VideoTurbine.Enable == TRUE)
{
UINT32 MacReg = 0;
{
/* Tx retry limit = 2F,1F */
RTMP_IO_READ32(pAd, TX_RTY_CFG, &MacReg);
MacReg &= 0xFFFF0000;
MacReg |= GetAsicVideoRetry(pAd);
RTMP_IO_WRITE32(pAd, TX_RTY_CFG, MacReg);
}
pAd->VideoTurbine.TxBASize = GetAsicVideoTxBA(pAd);
Set_RateAdaptInterval(pAd, "100:50");
TxSwQDepthAdjust(pAd, 1024);
}
else
{
UINT32 MacReg = 0;
/* Default Tx retry limit = 1F,0F */
RTMP_IO_READ32(pAd, TX_RTY_CFG, &MacReg);
MacReg &= 0xFFFF0000;
MacReg |= GetAsicDefaultRetry(pAd);
RTMP_IO_WRITE32(pAd, TX_RTY_CFG, MacReg);
pAd->VideoTurbine.TxBASize = GetAsicDefaultTxBA(pAd);
/* reset to default rate adaptation simping interval */
if ((pAd->ra_interval != DEF_RA_TIME_INTRVAL) ||
(pAd->ra_fast_interval != DEF_QUICK_RA_TIME_INTERVAL))
Set_RateAdaptInterval(pAd, "500:100");
TxSwQDepthAdjust(pAd, MAX_PACKETS_IN_QUEUE);
}
}
UINT32 GetAsicDefaultRetry(
IN PRTMP_ADAPTER pAd)
{
UINT32 RetryLimit;
RetryLimit = 0x1F0F;
return RetryLimit;
}
UCHAR GetAsicDefaultTxBA(
IN PRTMP_ADAPTER pAd)
{
return pAd->CommonCfg.TxBASize;
}
UINT32 GetAsicVideoRetry(
IN PRTMP_ADAPTER pAd)
{
return pAd->VideoTurbine.TxRetryLimit;
}
UCHAR GetAsicVideoTxBA(
IN PRTMP_ADAPTER pAd)
{
return pAd->VideoTurbine.TxBASize;
}
VOID VideoConfigInit(
IN PRTMP_ADAPTER pAd)
{
pAd->VideoTurbine.Enable = FALSE;
pAd->VideoTurbine.TxRetryLimit = 0x2F1F;
pAd->VideoTurbine.TxBASize = pAd->CommonCfg.TxBASize;
}
#endif /* VIDEO_TURBINE_SUPPORT */

View File

@ -0,0 +1,373 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2004, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
rtmp_wep.c
Abstract:
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Paul Wu 10-28-02 Initial
*/
#include "rt_config.h"
UINT FCSTAB_32[256] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
/*
========================================================================
Routine Description:
Calculate a new FCS given the current FCS and the new data.
Arguments:
Fcs the original FCS value
Cp pointer to the data which will be calculate the FCS
Len the length of the data
Return Value:
UINT - FCS 32 bits
IRQL = DISPATCH_LEVEL
Note:
========================================================================
*/
UINT RTMP_CALC_FCS32(
IN UINT Fcs,
IN PUCHAR Cp,
IN INT Len)
{
while (Len--)
Fcs = (((Fcs) >> 8) ^ FCSTAB_32[((Fcs) ^ (*Cp++)) & 0xff]);
return (Fcs);
}
/*
========================================================================
Routine Description:
Init WEP function.
Arguments:
pAd Pointer to our adapter
pKey Pointer to the WEP KEY
KeyId WEP Key ID
KeyLen the length of WEP KEY
pDest Pointer to the destination which Encryption data will store in.
Return Value:
None
IRQL = DISPATCH_LEVEL
Note:
========================================================================
*/
VOID RTMPInitWepEngine(
IN PUCHAR pIv,
IN PUCHAR pKey,
IN UCHAR KeyLen,
OUT ARC4_CTX_STRUC *pARC4_CTX)
{
PUCHAR seed = NULL;
UINT8 seed_len;
os_alloc_mem(NULL, (UCHAR **)&seed, sizeof(UCHAR)*16);
if (seed == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: seed Allocate memory fail!!!\n", __FUNCTION__));
return;
}
/* WEP seed construction */
NdisZeroMemory(seed, 16);
NdisMoveMemory(seed, pIv, 3);
NdisMoveMemory(&seed[3], pKey, KeyLen);
seed_len = 3 + KeyLen;
/* RC4 uses a pseudo-random number generator (PRNG)
to generate a key stream */
ARC4_INIT(pARC4_CTX, &seed[0], seed_len);
if (seed != NULL)
os_free_mem(NULL, seed);
}
/*
========================================================================
Routine Description:
Construct WEP IV header.
Arguments:
Return Value:
Note:
It's a 4-octets header.
========================================================================
*/
VOID RTMPConstructWEPIVHdr(
IN UINT8 key_idx,
IN UCHAR *pn,
OUT UCHAR *iv_hdr)
{
NdisZeroMemory(iv_hdr, LEN_WEP_IV_HDR);
NdisMoveMemory(iv_hdr, pn, LEN_WEP_TSC);
/* Append key index */
iv_hdr[3] = (key_idx << 6);
}
/*
========================================================================
Routine Description:
WEP MPDU cryptographic encapsulation
Arguments:
pAdapter Pointer to our adapter
pSrc Pointer to the received data
Len the length of the received data
Return Value:
Note:
========================================================================
*/
BOOLEAN RTMPSoftEncryptWEP(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pIvHdr,
IN PCIPHER_KEY pKey,
INOUT PUCHAR pData,
IN ULONG DataByteCnt)
{
ARC4_CTX_STRUC *ARC4_CTX = NULL;
UINT FCSCRC32;
os_alloc_mem(NULL, (UCHAR **)&ARC4_CTX, sizeof(ARC4_CTX_STRUC));
if (ARC4_CTX == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: ARC4_CTX Allocate memory fail!!!\n", __FUNCTION__));
return FALSE;
}
if (pKey->KeyLen == 0)
{
os_free_mem(NULL, ARC4_CTX);
DBGPRINT(RT_DEBUG_ERROR, ("%s : The key is empty !\n", __FUNCTION__));
return FALSE;
}
/* Initialize WEP key stream */
RTMPInitWepEngine(pIvHdr,
pKey->Key,
pKey->KeyLen,
ARC4_CTX);
/* WEP computes the ICV over the plaintext data */
FCSCRC32 = RTMP_CALC_FCS32(PPPINITFCS32, pData, DataByteCnt);
FCSCRC32 ^= 0xffffffff; /* complement */
FCSCRC32 = cpu2le32(FCSCRC32);
/* Append 4-bytes ICV after the MPDU data */
NdisMoveMemory(pData + DataByteCnt, (PUCHAR)&FCSCRC32, LEN_ICV);
/* Encrypt the MPDU plaintext data and ICV using ARC4 with a seed */
ARC4_Compute(ARC4_CTX, pData, DataByteCnt + LEN_ICV, pData);
if (ARC4_CTX != NULL)
os_free_mem(NULL, ARC4_CTX);
return TRUE;
}
/*
========================================================================
Routine Description:
Decrypt received WEP data
Arguments:
pAdapter Pointer to our adapter
pSrc Pointer to the received data
Len the length of the received data
Return Value:
TRUE Decrypt WEP data success
FALSE Decrypt WEP data failed
Note:
========================================================================
*/
BOOLEAN RTMPSoftDecryptWEP(
IN PRTMP_ADAPTER pAd,
IN PCIPHER_KEY pKey,
INOUT PUCHAR pData,
INOUT UINT16 *DataByteCnt)
{
/*ARC4_CTX_STRUC ARC4_CTX;*/
ARC4_CTX_STRUC *ARC4_CTX = NULL;
PUCHAR plaintext_ptr;
UINT16 plaintext_len;
PUCHAR ciphertext_ptr;
UINT16 ciphertext_len;
UINT trailfcs;
UINT crc32;
os_alloc_mem(NULL, (UCHAR **)&ARC4_CTX, sizeof(ARC4_CTX_STRUC));
if (ARC4_CTX == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: ARC4_CTX Allocate memory fail!!!\n", __FUNCTION__));
return FALSE;
}
if (pKey->KeyLen == 0)
{
os_free_mem(NULL, ARC4_CTX);
DBGPRINT(RT_DEBUG_ERROR, ("%s : The key is not available !\n", __FUNCTION__));
return FALSE;
}
/* Initialize WEP key stream */
RTMPInitWepEngine(pData,
pKey->Key,
pKey->KeyLen,
ARC4_CTX);
/* Skip the WEP IV header (4-bytes) */
ciphertext_ptr = pData + LEN_WEP_IV_HDR;
ciphertext_len = *DataByteCnt - LEN_WEP_IV_HDR;
/*skip payload length is zero*/
if ((*DataByteCnt) <= LEN_WEP_IV_HDR) {
os_free_mem(NULL, ARC4_CTX);
return FALSE;
}
/* Decrypt the WEP MPDU. It shall include plaintext and ICV.
The result output would overwrite the original WEP IV header position */
ARC4_Compute(ARC4_CTX,
ciphertext_ptr,
ciphertext_len,
pData);
/* Point to the decrypted data frame and its length shall exclude ICV length */
plaintext_ptr = pData;
plaintext_len = ciphertext_len - LEN_ICV;
/* Extract peer's the ICV */
NdisMoveMemory(&trailfcs, plaintext_ptr + plaintext_len, LEN_ICV);
/* WEP recomputes the ICV and
bit-wise compares it with the decrypted ICV from the MPDU. */
crc32 = RTMP_CALC_FCS32(PPPINITFCS32, plaintext_ptr, plaintext_len);
crc32 ^= 0xffffffff; /* complement */
if(crc32 != cpu2le32(trailfcs))
{
os_free_mem(NULL, ARC4_CTX);
DBGPRINT(RT_DEBUG_ERROR, ("! WEP Data CRC Error !\n")); /*CRC error.*/
return FALSE;
}
/* Update the total data length */
*DataByteCnt = plaintext_len;
if (ARC4_CTX != NULL)
os_free_mem(NULL, ARC4_CTX);
return TRUE;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Module Name:
RC4
Abstract:
Revision History:
Who When What
-------- ---------- ------------------------------------------
Eddy 2009/05/13 ARC4
***************************************************************************/
#include "crypt_arc4.h"
/*
========================================================================
Routine Description:
ARC4 initialize the key block
Arguments:
pARC4_CTX Pointer to ARC4 CONTEXT
Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits)
KeyLength The length of cipher key in bytes
========================================================================
*/
VOID ARC4_INIT (
IN ARC4_CTX_STRUC *pARC4_CTX,
IN PUCHAR pKey,
IN UINT KeyLength)
{
UINT BlockIndex = 0, SWAPIndex = 0, KeyIndex = 0;
UINT8 TempValue = 0;
/*Initialize the block value*/
pARC4_CTX->BlockIndex1 = 0;
pARC4_CTX->BlockIndex2 = 0;
for (BlockIndex = 0; BlockIndex < ARC4_KEY_BLOCK_SIZE; BlockIndex++)
pARC4_CTX->KeyBlock[BlockIndex] = (UINT8) BlockIndex;
/*Key schedule*/
for (BlockIndex = 0; BlockIndex < ARC4_KEY_BLOCK_SIZE; BlockIndex++)
{
TempValue = pARC4_CTX->KeyBlock[BlockIndex];
KeyIndex = BlockIndex % KeyLength;
SWAPIndex = (SWAPIndex + TempValue + pKey[KeyIndex]) & 0xff;
pARC4_CTX->KeyBlock[BlockIndex] = pARC4_CTX->KeyBlock[SWAPIndex];
pARC4_CTX->KeyBlock[SWAPIndex] = TempValue;
} /* End of for */
} /* End of ARC4_INIT */
/*
========================================================================
Routine Description:
ARC4 encryption/decryption
Arguments:
pARC4_CTX Pointer to ARC4 CONTEXT
InputText Input text
InputTextLength The length of input text in bytes
Return Value:
OutputBlock Return output text
========================================================================
*/
VOID ARC4_Compute (
IN ARC4_CTX_STRUC *pARC4_CTX,
IN UINT8 InputBlock[],
IN UINT InputBlockSize,
OUT UINT8 OutputBlock[])
{
UINT InputIndex = 0;
UINT8 TempValue = 0;
for (InputIndex = 0; InputIndex < InputBlockSize; InputIndex++)
{
pARC4_CTX->BlockIndex1 = (pARC4_CTX->BlockIndex1 + 1) & 0xff;
TempValue = pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1];
pARC4_CTX->BlockIndex2 = (pARC4_CTX->BlockIndex2 + TempValue) & 0xff;
pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1] = pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex2];
pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex2] = TempValue;
TempValue = (TempValue + pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1]) & 0xff;
OutputBlock[InputIndex] = InputBlock[InputIndex]^pARC4_CTX->KeyBlock[TempValue];
} /* End of for */
} /* End of ARC4_Compute */
/*
========================================================================
Routine Description:
Discard the key length
Arguments:
pARC4_CTX Pointer to ARC4 CONTEXT
Length Discard the key length
========================================================================
*/
VOID ARC4_Discard_KeyLength (
IN ARC4_CTX_STRUC *pARC4_CTX,
IN UINT Length)
{
UINT Index = 0;
UINT8 TempValue = 0;
for (Index = 0; Index < Length; Index++)
{
pARC4_CTX->BlockIndex1 = (pARC4_CTX->BlockIndex1 + 1) & 0xff;
TempValue = pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1];
pARC4_CTX->BlockIndex2 = (pARC4_CTX->BlockIndex2 + TempValue) & 0xff;
pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1] = pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex2];
pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex2] = TempValue;
} /* End of for */
} /* End of ARC4_Discard_KeyLength */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,227 @@
/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Module Name:
DH
Abstract:
RFC 2631: Diffie-Hellman Key Agreement Method
Revision History:
Who When What
-------- ---------- ------------------------------------------
Eddy 2009/01/21 Create Diffie-Hellman
***************************************************************************/
#include "crypt_dh.h"
#include "crypt_biginteger.h"
/*
========================================================================
Routine Description:
Diffie-Hellman public key generation
Arguments:
GValue Array in UINT8
GValueLength The length of G in bytes
PValue Array in UINT8
PValueLength The length of P in bytes
PrivateKey Private key
PrivateKeyLength The length of Private key in bytes
Return Value:
PublicKey Public key
PublicKeyLength The length of public key in bytes
Note:
Reference to RFC2631
PublicKey = G^PrivateKey (mod P)
========================================================================
*/
void DH_PublicKey_Generate (
IN UINT8 GValue[],
IN UINT GValueLength,
IN UINT8 PValue[],
IN UINT PValueLength,
IN UINT8 PrivateKey[],
IN UINT PrivateKeyLength,
OUT UINT8 PublicKey[],
INOUT UINT *PublicKeyLength)
{
PBIG_INTEGER pBI_G = NULL;
PBIG_INTEGER pBI_P = NULL;
PBIG_INTEGER pBI_PrivateKey = NULL;
PBIG_INTEGER pBI_PublicKey = NULL;
/*
* 1. Check the input parameters
* - GValueLength, PValueLength and PrivateLength must be large than zero
* - PublicKeyLength must be large or equal than PValueLength
* - PValue must be odd
*
* - PValue must be prime number (no implement)
* - GValue must be greater than 0 but less than the PValue (no implement)
*/
if (GValueLength == 0) {
DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: G length is (%d)\n", GValueLength));
return;
} /* End of if */
if (PValueLength == 0) {
DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: P length is (%d)\n", PValueLength));
return;
} /* End of if */
if (PrivateKeyLength == 0) {
DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: private key length is (%d)\n", PrivateKeyLength));
return;
} /* End of if */
if (*PublicKeyLength < PValueLength) {
DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: public key length(%d) must be large or equal than P length(%d)\n",
*PublicKeyLength, PValueLength));
return;
} /* End of if */
if (!(PValue[PValueLength - 1] & 0x1)) {
DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: P value must be odd\n"));
return;
} /* End of if */
/*
* 2. Transfer parameters to BigInteger structure
*/
BigInteger_Init(&pBI_G);
BigInteger_Init(&pBI_P);
BigInteger_Init(&pBI_PrivateKey);
BigInteger_Init(&pBI_PublicKey);
BigInteger_Bin2BI(GValue, GValueLength, &pBI_G);
BigInteger_Bin2BI(PValue, PValueLength, &pBI_P);
BigInteger_Bin2BI(PrivateKey, PrivateKeyLength, &pBI_PrivateKey);
/*
* 3. Calculate PublicKey = G^PrivateKey (mod P)
* - BigInteger Operation
* - Montgomery reduction
*/
BigInteger_Montgomery_ExpMod(pBI_G, pBI_PrivateKey, pBI_P, &pBI_PublicKey);
/*
* 4. Transfer BigInteger structure to char array
*/
BigInteger_BI2Bin(pBI_PublicKey, PublicKey, PublicKeyLength);
BigInteger_Free(&pBI_G);
BigInteger_Free(&pBI_P);
BigInteger_Free(&pBI_PrivateKey);
BigInteger_Free(&pBI_PublicKey);
} /* End of DH_PublicKey_Generate */
/*
========================================================================
Routine Description:
Diffie-Hellman secret key generation
Arguments:
PublicKey Public key
PublicKeyLength The length of Public key in bytes
PValue Array in UINT8
PValueLength The length of P in bytes
PrivateKey Private key
PrivateKeyLength The length of Private key in bytes
Return Value:
SecretKey Secret key
SecretKeyLength The length of secret key in bytes
Note:
Reference to RFC2631
SecretKey = PublicKey^PrivateKey (mod P)
========================================================================
*/
void DH_SecretKey_Generate (
IN UINT8 PublicKey[],
IN UINT PublicKeyLength,
IN UINT8 PValue[],
IN UINT PValueLength,
IN UINT8 PrivateKey[],
IN UINT PrivateKeyLength,
OUT UINT8 SecretKey[],
INOUT UINT *SecretKeyLength)
{
PBIG_INTEGER pBI_P = NULL;
PBIG_INTEGER pBI_SecretKey = NULL;
PBIG_INTEGER pBI_PrivateKey = NULL;
PBIG_INTEGER pBI_PublicKey = NULL;
/*
* 1. Check the input parameters
* - PublicKeyLength, PValueLength and PrivateLength must be large than zero
* - SecretKeyLength must be large or equal than PValueLength
* - PValue must be odd
*
* - PValue must be prime number (no implement)
*/
if (PublicKeyLength == 0) {
DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: public key length is (%d)\n", PublicKeyLength));
return;
} /* End of if */
if (PValueLength == 0) {
DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: P length is (%d)\n", PValueLength));
return;
} /* End of if */
if (PrivateKeyLength == 0) {
DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: private key length is (%d)\n", PrivateKeyLength));
return;
} /* End of if */
if (*SecretKeyLength < PValueLength) {
DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: secret key length(%d) must be large or equal than P length(%d)\n",
*SecretKeyLength, PValueLength));
return;
} /* End of if */
if (!(PValue[PValueLength - 1] & 0x1)) {
DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: P value must be odd\n"));
return;
} /* End of if */
/*
* 2. Transfer parameters to BigInteger structure
*/
BigInteger_Init(&pBI_P);
BigInteger_Init(&pBI_PrivateKey);
BigInteger_Init(&pBI_PublicKey);
BigInteger_Init(&pBI_SecretKey);
BigInteger_Bin2BI(PublicKey, PublicKeyLength, &pBI_PublicKey);
BigInteger_Bin2BI(PValue, PValueLength, &pBI_P);
BigInteger_Bin2BI(PrivateKey, PrivateKeyLength, &pBI_PrivateKey);
/*
* 3. Calculate SecretKey = PublicKey^PrivateKey (mod P)
* - BigInteger Operation
* - Montgomery reduction
*/
BigInteger_Montgomery_ExpMod(pBI_PublicKey, pBI_PrivateKey, pBI_P, &pBI_SecretKey);
/*
* 4. Transfer BigInteger structure to char array
*/
BigInteger_BI2Bin(pBI_SecretKey, SecretKey, SecretKeyLength);
BigInteger_Free(&pBI_P);
BigInteger_Free(&pBI_PrivateKey);
BigInteger_Free(&pBI_PublicKey);
BigInteger_Free(&pBI_SecretKey);
} /* End of DH_SecretKey_Generate */

View File

@ -0,0 +1,282 @@
/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Module Name:
HMAC
Abstract:
FIPS 198: The Keyed-Hash Message Authentication Code (HMAC)
Revision History:
Who When What
-------- ---------- ------------------------------------------
Eddy 2008/11/24 Create HMAC-SHA1, HMAC-SHA256
***************************************************************************/
#include "crypt_hmac.h"
#ifdef HMAC_SHA1_SUPPORT
/*
========================================================================
Routine Description:
HMAC using SHA1 hash function
Arguments:
key Secret key
key_len The length of the key in bytes
message Message context
message_len The length of message in bytes
macLen Request the length of message authentication code
Return Value:
mac Message authentication code
Note:
None
========================================================================
*/
VOID RT_HMAC_SHA1 (
IN const UINT8 Key[],
IN UINT KeyLen,
IN const UINT8 Message[],
IN UINT MessageLen,
OUT UINT8 MAC[],
IN UINT MACLen)
{
SHA1_CTX_STRUC sha_ctx1;
SHA1_CTX_STRUC sha_ctx2;
UINT8 K0[SHA1_BLOCK_SIZE];
UINT8 Digest[SHA1_DIGEST_SIZE];
UINT index;
NdisZeroMemory(&sha_ctx1, sizeof(SHA1_CTX_STRUC));
NdisZeroMemory(&sha_ctx2, sizeof(SHA1_CTX_STRUC));
/*
* If the length of K = B(Block size): K0 = K.
* If the length of K > B: hash K to obtain an L byte string,
* then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00).
* If the length of K < B: append zeros to the end of K to create a B-byte string K0
*/
NdisZeroMemory(K0, SHA1_BLOCK_SIZE);
if (KeyLen <= SHA1_BLOCK_SIZE)
NdisMoveMemory(K0, Key, KeyLen);
else
RT_SHA1(Key, KeyLen, K0);
/* End of if */
/* Exclusive-Or K0 with ipad */
/* ipad: Inner pad; the byte x・36・ repeated B times. */
for (index = 0; index < SHA1_BLOCK_SIZE; index++)
K0[index] ^= 0x36;
/* End of for */
RT_SHA1_Init(&sha_ctx1);
/* H(K0^ipad) */
RT_SHA1_Append(&sha_ctx1, K0, sizeof(K0));
/* H((K0^ipad)||text) */
RT_SHA1_Append(&sha_ctx1, Message, MessageLen);
RT_SHA1_End(&sha_ctx1, Digest);
/* Exclusive-Or K0 with opad and remove ipad */
/* opad: Outer pad; the byte x・5c・ repeated B times. */
for (index = 0; index < SHA1_BLOCK_SIZE; index++)
K0[index] ^= 0x36^0x5c;
/* End of for */
RT_SHA1_Init(&sha_ctx2);
/* H(K0^opad) */
RT_SHA1_Append(&sha_ctx2, K0, sizeof(K0));
/* H( (K0^opad) || H((K0^ipad)||text) ) */
RT_SHA1_Append(&sha_ctx2, Digest, SHA1_DIGEST_SIZE);
RT_SHA1_End(&sha_ctx2, Digest);
if (MACLen > SHA1_DIGEST_SIZE)
NdisMoveMemory(MAC, Digest, SHA1_DIGEST_SIZE);
else
NdisMoveMemory(MAC, Digest, MACLen);
} /* End of RT_HMAC_SHA1 */
#endif /* HMAC_SHA1_SUPPORT */
#ifdef HMAC_SHA256_SUPPORT
/*
========================================================================
Routine Description:
HMAC using SHA256 hash function
Arguments:
key Secret key
key_len The length of the key in bytes
message Message context
message_len The length of message in bytes
macLen Request the length of message authentication code
Return Value:
mac Message authentication code
Note:
None
========================================================================
*/
VOID RT_HMAC_SHA256 (
IN const UINT8 Key[],
IN UINT KeyLen,
IN const UINT8 Message[],
IN UINT MessageLen,
OUT UINT8 MAC[],
IN UINT MACLen)
{
SHA256_CTX_STRUC sha_ctx1;
SHA256_CTX_STRUC sha_ctx2;
UINT8 K0[SHA256_BLOCK_SIZE];
UINT8 Digest[SHA256_DIGEST_SIZE];
UINT index;
NdisZeroMemory(&sha_ctx1, sizeof(SHA256_CTX_STRUC));
NdisZeroMemory(&sha_ctx2, sizeof(SHA256_CTX_STRUC));
/*
* If the length of K = B(Block size): K0 = K.
* If the length of K > B: hash K to obtain an L byte string,
* then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00).
* If the length of K < B: append zeros to the end of K to create a B-byte string K0
*/
NdisZeroMemory(K0, SHA256_BLOCK_SIZE);
if (KeyLen <= SHA256_BLOCK_SIZE) {
NdisMoveMemory(K0, Key, KeyLen);
} else {
RT_SHA256(Key, KeyLen, K0);
}
/* Exclusive-Or K0 with ipad */
/* ipad: Inner pad; the byte x・36・ repeated B times. */
for (index = 0; index < SHA256_BLOCK_SIZE; index++)
K0[index] ^= 0x36;
/* End of for */
RT_SHA256_Init(&sha_ctx1);
/* H(K0^ipad) */
RT_SHA256_Append(&sha_ctx1, K0, sizeof(K0));
/* H((K0^ipad)||text) */
RT_SHA256_Append(&sha_ctx1, Message, MessageLen);
RT_SHA256_End(&sha_ctx1, Digest);
/* Exclusive-Or K0 with opad and remove ipad */
/* opad: Outer pad; the byte x・5c・ repeated B times. */
for (index = 0; index < SHA256_BLOCK_SIZE; index++)
K0[index] ^= 0x36^0x5c;
/* End of for */
RT_SHA256_Init(&sha_ctx2);
/* H(K0^opad) */
RT_SHA256_Append(&sha_ctx2, K0, sizeof(K0));
/* H( (K0^opad) || H((K0^ipad)||text) ) */
RT_SHA256_Append(&sha_ctx2, Digest, SHA256_DIGEST_SIZE);
RT_SHA256_End(&sha_ctx2, Digest);
if (MACLen > SHA256_DIGEST_SIZE)
NdisMoveMemory(MAC, Digest,SHA256_DIGEST_SIZE);
else
NdisMoveMemory(MAC, Digest, MACLen);
} /* End of RT_HMAC_SHA256 */
#endif /* HMAC_SHA256_SUPPORT */
#ifdef HMAC_MD5_SUPPORT
/*
========================================================================
Routine Description:
HMAC using MD5 hash function
Arguments:
key Secret key
key_len The length of the key in bytes
message Message context
message_len The length of message in bytes
macLen Request the length of message authentication code
Return Value:
mac Message authentication code
Note:
None
========================================================================
*/
VOID RT_HMAC_MD5(
IN const UINT8 Key[],
IN UINT KeyLen,
IN const UINT8 Message[],
IN UINT MessageLen,
OUT UINT8 MAC[],
IN UINT MACLen)
{
MD5_CTX_STRUC md5_ctx1;
MD5_CTX_STRUC md5_ctx2;
UINT8 K0[MD5_BLOCK_SIZE];
UINT8 Digest[MD5_DIGEST_SIZE];
UINT index;
NdisZeroMemory(&md5_ctx1, sizeof(MD5_CTX_STRUC));
NdisZeroMemory(&md5_ctx2, sizeof(MD5_CTX_STRUC));
/*
* If the length of K = B(Block size): K0 = K.
* If the length of K > B: hash K to obtain an L byte string,
* then append (B-L) zeros to create a B-byte string K0 (i.e., K0 = H(K) || 00...00).
* If the length of K < B: append zeros to the end of K to create a B-byte string K0
*/
NdisZeroMemory(K0, MD5_BLOCK_SIZE);
if (KeyLen <= MD5_BLOCK_SIZE) {
NdisMoveMemory(K0, Key, KeyLen);
} else {
RT_MD5(Key, KeyLen, K0);
}
/* Exclusive-Or K0 with ipad */
/* ipad: Inner pad; the byte x・36・ repeated B times. */
for (index = 0; index < MD5_BLOCK_SIZE; index++)
K0[index] ^= 0x36;
/* End of for */
RT_MD5_Init(&md5_ctx1);
/* H(K0^ipad) */
RT_MD5_Append(&md5_ctx1, K0, sizeof(K0));
/* H((K0^ipad)||text) */
RT_MD5_Append(&md5_ctx1, Message, MessageLen);
RT_MD5_End(&md5_ctx1, Digest);
/* Exclusive-Or K0 with opad and remove ipad */
/* opad: Outer pad; the byte x・5c・ repeated B times. */
for (index = 0; index < MD5_BLOCK_SIZE; index++)
K0[index] ^= 0x36^0x5c;
/* End of for */
RT_MD5_Init(&md5_ctx2);
/* H(K0^opad) */
RT_MD5_Append(&md5_ctx2, K0, sizeof(K0));
/* H( (K0^opad) || H((K0^ipad)||text) ) */
RT_MD5_Append(&md5_ctx2, Digest, MD5_DIGEST_SIZE);
RT_MD5_End(&md5_ctx2, Digest);
if (MACLen > MD5_DIGEST_SIZE)
NdisMoveMemory(MAC, Digest, MD5_DIGEST_SIZE);
else
NdisMoveMemory(MAC, Digest, MACLen);
} /* End of RT_HMAC_SHA256 */
#endif /* HMAC_MD5_SUPPORT */
/* End of crypt_hmac.c */

View File

@ -0,0 +1,356 @@
/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Module Name:
MD5
Abstract:
RFC1321: The MD5 Message-Digest Algorithm
Revision History:
Who When What
-------- ---------- ------------------------------------------
Eddy 2008/11/24 Create md5
***************************************************************************/
#include "rt_config.h"
#ifdef MD5_SUPPORT
/*
* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
#define ROTL(x,n,w) ((x << n) | (x >> (w - n)))
#define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */
#define ROUND1(a, b, c, d, x, s, ac) { \
(a) += F((b),(c),(d)) + (x) + (UINT32)(ac); \
(a) = ROTL32((a),(s)); \
(a) += (b); \
}
#define ROUND2(a, b, c, d, x, s, ac) { \
(a) += G((b),(c),(d)) + (x) + (UINT32)(ac); \
(a) = ROTL32((a),(s)); \
(a) += (b); \
}
#define ROUND3(a, b, c, d, x, s, ac) { \
(a) += H((b),(c),(d)) + (x) + (UINT32)(ac); \
(a) = ROTL32((a),(s)); \
(a) += (b); \
}
#define ROUND4(a, b, c, d, x, s, ac) { \
(a) += I((b),(c),(d)) + (x) + (UINT32)(ac); \
(a) = ROTL32((a),(s)); \
(a) += (b); \
}
static const UINT32 MD5_DefaultHashValue[4] = {
0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL
};
#endif /* MD5_SUPPORT */
#ifdef MD5_SUPPORT
/*
========================================================================
Routine Description:
Initial Md5_CTX_STRUC
Arguments:
pMD5_CTX Pointer to Md5_CTX_STRUC
Return Value:
None
Note:
None
========================================================================
*/
VOID RT_MD5_Init (
IN MD5_CTX_STRUC *pMD5_CTX)
{
NdisMoveMemory(pMD5_CTX->HashValue, MD5_DefaultHashValue,
sizeof(MD5_DefaultHashValue));
NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE);
pMD5_CTX->BlockLen = 0;
pMD5_CTX->MessageLen = 0;
} /* End of RT_MD5_Init */
/*
========================================================================
Routine Description:
MD5 computation for one block (512 bits)
Arguments:
pMD5_CTX Pointer to Md5_CTX_STRUC
Return Value:
None
Note:
T[i] := floor(abs(sin(i + 1)) * (2 pow 32)), i is number of round
========================================================================
*/
VOID RT_MD5_Hash (
IN MD5_CTX_STRUC *pMD5_CTX)
{
UINT32 X_i;
UINT32 X[16];
UINT32 a,b,c,d;
/* Prepare the message schedule, {X_i} */
NdisMoveMemory(X, pMD5_CTX->Block, MD5_BLOCK_SIZE);
for (X_i = 0; X_i < 16; X_i++)
X[X_i] = cpu2le32(X[X_i]); /* Endian Swap */
/* End of for */
/* MD5 hash computation */
/* Initialize the working variables */
a = pMD5_CTX->HashValue[0];
b = pMD5_CTX->HashValue[1];
c = pMD5_CTX->HashValue[2];
d = pMD5_CTX->HashValue[3];
/*
* Round 1
* Let [abcd k s i] denote the operation
* a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
*/
ROUND1(a, b, c, d, X[ 0], 7, 0xd76aa478); /* 1 */
ROUND1(d, a, b, c, X[ 1], 12, 0xe8c7b756); /* 2 */
ROUND1(c, d, a, b, X[ 2], 17, 0x242070db); /* 3 */
ROUND1(b, c, d, a, X[ 3], 22, 0xc1bdceee); /* 4 */
ROUND1(a, b, c, d, X[ 4], 7, 0xf57c0faf); /* 5 */
ROUND1(d, a, b, c, X[ 5], 12, 0x4787c62a); /* 6 */
ROUND1(c, d, a, b, X[ 6], 17, 0xa8304613); /* 7 */
ROUND1(b, c, d, a, X[ 7], 22, 0xfd469501); /* 8 */
ROUND1(a, b, c, d, X[ 8], 7, 0x698098d8); /* 9 */
ROUND1(d, a, b, c, X[ 9], 12, 0x8b44f7af); /* 10 */
ROUND1(c, d, a, b, X[10], 17, 0xffff5bb1); /* 11 */
ROUND1(b, c, d, a, X[11], 22, 0x895cd7be); /* 12 */
ROUND1(a, b, c, d, X[12], 7, 0x6b901122); /* 13 */
ROUND1(d, a, b, c, X[13], 12, 0xfd987193); /* 14 */
ROUND1(c, d, a, b, X[14], 17, 0xa679438e); /* 15 */
ROUND1(b, c, d, a, X[15], 22, 0x49b40821); /* 16 */
/*
* Round 2
* Let [abcd k s i] denote the operation
* a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s)
*/
ROUND2(a, b, c, d, X[ 1], 5, 0xf61e2562); /* 17 */
ROUND2(d, a, b, c, X[ 6], 9, 0xc040b340); /* 18 */
ROUND2(c, d, a, b, X[11], 14, 0x265e5a51); /* 19 */
ROUND2(b, c, d, a, X[ 0], 20, 0xe9b6c7aa); /* 20 */
ROUND2(a, b, c, d, X[ 5], 5, 0xd62f105d); /* 21 */
ROUND2(d, a, b, c, X[10], 9, 0x2441453); /* 22 */
ROUND2(c, d, a, b, X[15], 14, 0xd8a1e681); /* 23 */
ROUND2(b, c, d, a, X[ 4], 20, 0xe7d3fbc8); /* 24 */
ROUND2(a, b, c, d, X[ 9], 5, 0x21e1cde6); /* 25 */
ROUND2(d, a, b, c, X[14], 9, 0xc33707d6); /* 26 */
ROUND2(c, d, a, b, X[ 3], 14, 0xf4d50d87); /* 27 */
ROUND2(b, c, d, a, X[ 8], 20, 0x455a14ed); /* 28 */
ROUND2(a, b, c, d, X[13], 5, 0xa9e3e905); /* 29 */
ROUND2(d, a, b, c, X[ 2], 9, 0xfcefa3f8); /* 30 */
ROUND2(c, d, a, b, X[ 7], 14, 0x676f02d9); /* 31 */
ROUND2(b, c, d, a, X[12], 20, 0x8d2a4c8a); /* 32 */
/*
* Round 3
* Let [abcd k s t] denote the operation
* a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s)
*/
ROUND3(a, b, c, d, X[ 5], 4, 0xfffa3942); /* 33 */
ROUND3(d, a, b, c, X[ 8], 11, 0x8771f681); /* 34 */
ROUND3(c, d, a, b, X[11], 16, 0x6d9d6122); /* 35 */
ROUND3(b, c, d, a, X[14], 23, 0xfde5380c); /* 36 */
ROUND3(a, b, c, d, X[ 1], 4, 0xa4beea44); /* 37 */
ROUND3(d, a, b, c, X[ 4], 11, 0x4bdecfa9); /* 38 */
ROUND3(c, d, a, b, X[ 7], 16, 0xf6bb4b60); /* 39 */
ROUND3(b, c, d, a, X[10], 23, 0xbebfbc70); /* 40 */
ROUND3(a, b, c, d, X[13], 4, 0x289b7ec6); /* 41 */
ROUND3(d, a, b, c, X[ 0], 11, 0xeaa127fa); /* 42 */
ROUND3(c, d, a, b, X[ 3], 16, 0xd4ef3085); /* 43 */
ROUND3(b, c, d, a, X[ 6], 23, 0x4881d05); /* 44 */
ROUND3(a, b, c, d, X[ 9], 4, 0xd9d4d039); /* 45 */
ROUND3(d, a, b, c, X[12], 11, 0xe6db99e5); /* 46 */
ROUND3(c, d, a, b, X[15], 16, 0x1fa27cf8); /* 47 */
ROUND3(b, c, d, a, X[ 2], 23, 0xc4ac5665); /* 48 */
/*
* Round 4
* Let [abcd k s t] denote the operation
* a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s)
*/
ROUND4(a, b, c, d, X[ 0], 6, 0xf4292244); /* 49 */
ROUND4(d, a, b, c, X[ 7], 10, 0x432aff97); /* 50 */
ROUND4(c, d, a, b, X[14], 15, 0xab9423a7); /* 51 */
ROUND4(b, c, d, a, X[ 5], 21, 0xfc93a039); /* 52 */
ROUND4(a, b, c, d, X[12], 6, 0x655b59c3); /* 53 */
ROUND4(d, a, b, c, X[ 3], 10, 0x8f0ccc92); /* 54 */
ROUND4(c, d, a, b, X[10], 15, 0xffeff47d); /* 55 */
ROUND4(b, c, d, a, X[ 1], 21, 0x85845dd1); /* 56 */
ROUND4(a, b, c, d, X[ 8], 6, 0x6fa87e4f); /* 57 */
ROUND4(d, a, b, c, X[15], 10, 0xfe2ce6e0); /* 58 */
ROUND4(c, d, a, b, X[ 6], 15, 0xa3014314); /* 59 */
ROUND4(b, c, d, a, X[13], 21, 0x4e0811a1); /* 60 */
ROUND4(a, b, c, d, X[ 4], 6, 0xf7537e82); /* 61 */
ROUND4(d, a, b, c, X[11], 10, 0xbd3af235); /* 62 */
ROUND4(c, d, a, b, X[ 2], 15, 0x2ad7d2bb); /* 63 */
ROUND4(b, c, d, a, X[ 9], 21, 0xeb86d391); /* 64 */
/* Compute the i^th intermediate hash value H^(i) */
pMD5_CTX->HashValue[0] += a;
pMD5_CTX->HashValue[1] += b;
pMD5_CTX->HashValue[2] += c;
pMD5_CTX->HashValue[3] += d;
NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE);
pMD5_CTX->BlockLen = 0;
} /* End of RT_MD5_Hash */
/*
========================================================================
Routine Description:
The message is appended to block. If block size > 64 bytes, the MD5_Hash
will be called.
Arguments:
pMD5_CTX Pointer to MD5_CTX_STRUC
message Message context
messageLen The length of message in bytes
Return Value:
None
Note:
None
========================================================================
*/
VOID RT_MD5_Append (
IN MD5_CTX_STRUC *pMD5_CTX,
IN const UINT8 Message[],
IN UINT MessageLen)
{
UINT appendLen = 0;
UINT diffLen = 0;
while (appendLen != MessageLen) {
diffLen = MessageLen - appendLen;
if ((pMD5_CTX->BlockLen + diffLen) < MD5_BLOCK_SIZE) {
NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen,
Message + appendLen, diffLen);
pMD5_CTX->BlockLen += diffLen;
appendLen += diffLen;
}
else
{
NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen,
Message + appendLen, MD5_BLOCK_SIZE - pMD5_CTX->BlockLen);
appendLen += (MD5_BLOCK_SIZE - pMD5_CTX->BlockLen);
pMD5_CTX->BlockLen = MD5_BLOCK_SIZE;
RT_MD5_Hash(pMD5_CTX);
} /* End of if */
} /* End of while */
pMD5_CTX->MessageLen += MessageLen;
} /* End of RT_MD5_Append */
/*
========================================================================
Routine Description:
1. Append bit 1 to end of the message
2. Append the length of message in rightmost 64 bits
3. Transform the Hash Value to digest message
Arguments:
pMD5_CTX Pointer to MD5_CTX_STRUC
Return Value:
digestMessage Digest message
Note:
None
========================================================================
*/
VOID RT_MD5_End (
IN MD5_CTX_STRUC *pMD5_CTX,
OUT UINT8 DigestMessage[])
{
UINT index;
UINT64 message_length_bits;
/* append 1 bits to end of the message */
NdisFillMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, 1, 0x80);
/* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */
if (pMD5_CTX->BlockLen > 55)
RT_MD5_Hash(pMD5_CTX);
/* End of if */
/* Append the length of message in rightmost 64 bits */
message_length_bits = pMD5_CTX->MessageLen*8;
message_length_bits = cpu2le64(message_length_bits);
NdisMoveMemory(&pMD5_CTX->Block[56], &message_length_bits, 8);
RT_MD5_Hash(pMD5_CTX);
/* Return message digest, transform the UINT32 hash value to bytes */
for (index = 0; index < 4;index++)
pMD5_CTX->HashValue[index] = cpu2le32(pMD5_CTX->HashValue[index]);
/* End of for */
NdisMoveMemory(DigestMessage, pMD5_CTX->HashValue, MD5_DIGEST_SIZE);
} /* End of RT_MD5_End */
/*
========================================================================
Routine Description:
MD5 algorithm
Arguments:
message Message context
messageLen The length of message in bytes
Return Value:
digestMessage Digest message
Note:
None
========================================================================
*/
VOID RT_MD5 (
IN const UINT8 Message[],
IN UINT MessageLen,
OUT UINT8 DigestMessage[])
{
MD5_CTX_STRUC md5_ctx;
NdisZeroMemory(&md5_ctx, sizeof(MD5_CTX_STRUC));
RT_MD5_Init(&md5_ctx);
RT_MD5_Append(&md5_ctx, Message, MessageLen);
RT_MD5_End(&md5_ctx, DigestMessage);
} /* End of RT_MD5 */
#endif /* MD5_SUPPORT */
/* End of crypt_md5.c */

View File

@ -0,0 +1,555 @@
/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Module Name:
SHA2
Abstract:
FIPS 180-2: Secure Hash Standard (SHS)
Revision History:
Who When What
-------- ---------- ------------------------------------------
Eddy 2008/11/24 Create SHA1
Eddy 2008/07/23 Create SHA256
***************************************************************************/
#include "rt_config.h"
/* Basic operations */
#define SHR(x,n) (x >> n) /* SHR(x)^n, right shift n bits , x is w-bit word, 0 <= n <= w */
#define ROTR(x,n,w) ((x >> n) | (x << (w - n))) /* ROTR(x)^n, circular right shift n bits , x is w-bit word, 0 <= n <= w */
#define ROTL(x,n,w) ((x << n) | (x >> (w - n))) /* ROTL(x)^n, circular left shift n bits , x is w-bit word, 0 <= n <= w */
#define ROTR32(x,n) ROTR(x,n,32) /* 32 bits word */
#define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */
/* Basic functions */
#define Ch(x,y,z) ((x & y) ^ ((~x) & z))
#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
#define Parity(x,y,z) (x ^ y ^ z)
#ifdef SHA1_SUPPORT
/* SHA1 constants */
#define SHA1_MASK 0x0000000f
static const UINT32 SHA1_K[4] = {
0x5a827999UL, 0x6ed9eba1UL, 0x8f1bbcdcUL, 0xca62c1d6UL
};
static const UINT32 SHA1_DefaultHashValue[5] = {
0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL, 0xc3d2e1f0UL
};
#endif /* SHA1_SUPPORT */
#ifdef SHA256_SUPPORT
/* SHA256 functions */
#define Zsigma_256_0(x) (ROTR32(x,2) ^ ROTR32(x,13) ^ ROTR32(x,22))
#define Zsigma_256_1(x) (ROTR32(x,6) ^ ROTR32(x,11) ^ ROTR32(x,25))
#define Sigma_256_0(x) (ROTR32(x,7) ^ ROTR32(x,18) ^ SHR(x,3))
#define Sigma_256_1(x) (ROTR32(x,17) ^ ROTR32(x,19) ^ SHR(x,10))
/* SHA256 constants */
static const UINT32 SHA256_K[64] = {
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
};
static const UINT32 SHA256_DefaultHashValue[8] = {
0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL,
0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL
};
#endif /* SHA256_SUPPORT */
#ifdef SHA1_SUPPORT
/*
========================================================================
Routine Description:
Initial SHA1_CTX_STRUC
Arguments:
pSHA_CTX Pointer to SHA1_CTX_STRUC
Return Value:
None
Note:
None
========================================================================
*/
VOID RT_SHA1_Init (
IN SHA1_CTX_STRUC *pSHA_CTX)
{
NdisMoveMemory(pSHA_CTX->HashValue, SHA1_DefaultHashValue,
sizeof(SHA1_DefaultHashValue));
NdisZeroMemory(pSHA_CTX->Block, SHA1_BLOCK_SIZE);
pSHA_CTX->MessageLen = 0;
pSHA_CTX->BlockLen = 0;
} /* End of RT_SHA1_Init */
/*
========================================================================
Routine Description:
SHA1 computation for one block (512 bits)
Arguments:
pSHA_CTX Pointer to SHA1_CTX_STRUC
Return Value:
None
Note:
None
========================================================================
*/
VOID RT_SHA1_Hash (
IN SHA1_CTX_STRUC *pSHA_CTX)
{
UINT32 W_i,t;
UINT32 W[80];
UINT32 a,b,c,d,e,T,f_t = 0;
/* Prepare the message schedule, {W_i}, 0 < t < 15 */
NdisMoveMemory(W, pSHA_CTX->Block, SHA1_BLOCK_SIZE);
for (W_i = 0; W_i < 16; W_i++) {
W[W_i] = cpu2be32(W[W_i]); /* Endian Swap */
} /* End of for */
for (W_i = 16; W_i < 80; W_i++) {
W[W_i] = ROTL32((W[W_i - 3] ^ W[W_i - 8] ^ W[W_i - 14] ^ W[W_i - 16]),1);
} /* End of for */
/* SHA256 hash computation */
/* Initialize the working variables */
a = pSHA_CTX->HashValue[0];
b = pSHA_CTX->HashValue[1];
c = pSHA_CTX->HashValue[2];
d = pSHA_CTX->HashValue[3];
e = pSHA_CTX->HashValue[4];
/* 80 rounds */
for (t = 0;t < 20;t++) {
f_t = Ch(b,c,d);
T = ROTL32(a,5) + f_t + e + SHA1_K[0] + W[t];
e = d;
d = c;
c = ROTL32(b,30);
b = a;
a = T;
} /* End of for */
for (t = 20;t < 40;t++) {
f_t = Parity(b,c,d);
T = ROTL32(a,5) + f_t + e + SHA1_K[1] + W[t];
e = d;
d = c;
c = ROTL32(b,30);
b = a;
a = T;
} /* End of for */
for (t = 40;t < 60;t++) {
f_t = Maj(b,c,d);
T = ROTL32(a,5) + f_t + e + SHA1_K[2] + W[t];
e = d;
d = c;
c = ROTL32(b,30);
b = a;
a = T;
} /* End of for */
for (t = 60;t < 80;t++) {
f_t = Parity(b,c,d);
T = ROTL32(a,5) + f_t + e + SHA1_K[3] + W[t];
e = d;
d = c;
c = ROTL32(b,30);
b = a;
a = T;
} /* End of for */
/* Compute the i^th intermediate hash value H^(i) */
pSHA_CTX->HashValue[0] += a;
pSHA_CTX->HashValue[1] += b;
pSHA_CTX->HashValue[2] += c;
pSHA_CTX->HashValue[3] += d;
pSHA_CTX->HashValue[4] += e;
NdisZeroMemory(pSHA_CTX->Block, SHA1_BLOCK_SIZE);
pSHA_CTX->BlockLen = 0;
} /* End of RT_SHA1_Hash */
/*
========================================================================
Routine Description:
The message is appended to block. If block size > 64 bytes, the SHA1_Hash
will be called.
Arguments:
pSHA_CTX Pointer to SHA1_CTX_STRUC
message Message context
messageLen The length of message in bytes
Return Value:
None
Note:
None
========================================================================
*/
VOID RT_SHA1_Append (
IN SHA1_CTX_STRUC *pSHA_CTX,
IN const UINT8 Message[],
IN UINT MessageLen)
{
UINT appendLen = 0;
UINT diffLen = 0;
while (appendLen != MessageLen) {
diffLen = MessageLen - appendLen;
if ((pSHA_CTX->BlockLen + diffLen) < SHA1_BLOCK_SIZE) {
NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen,
Message + appendLen, diffLen);
pSHA_CTX->BlockLen += diffLen;
appendLen += diffLen;
}
else
{
NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen,
Message + appendLen, SHA1_BLOCK_SIZE - pSHA_CTX->BlockLen);
appendLen += (SHA1_BLOCK_SIZE - pSHA_CTX->BlockLen);
pSHA_CTX->BlockLen = SHA1_BLOCK_SIZE;
RT_SHA1_Hash(pSHA_CTX);
} /* End of if */
} /* End of while */
pSHA_CTX->MessageLen += MessageLen;
} /* End of RT_SHA1_Append */
/*
========================================================================
Routine Description:
1. Append bit 1 to end of the message
2. Append the length of message in rightmost 64 bits
3. Transform the Hash Value to digest message
Arguments:
pSHA_CTX Pointer to SHA1_CTX_STRUC
Return Value:
digestMessage Digest message
Note:
None
========================================================================
*/
VOID RT_SHA1_End (
IN SHA1_CTX_STRUC *pSHA_CTX,
OUT UINT8 DigestMessage[])
{
UINT index;
UINT64 message_length_bits;
/* Append bit 1 to end of the message */
NdisFillMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, 1, 0x80);
/* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */
if (pSHA_CTX->BlockLen > 55)
RT_SHA1_Hash(pSHA_CTX);
/* End of if */
/* Append the length of message in rightmost 64 bits */
message_length_bits = pSHA_CTX->MessageLen*8;
message_length_bits = cpu2be64(message_length_bits);
NdisMoveMemory(&pSHA_CTX->Block[56], &message_length_bits, 8);
RT_SHA1_Hash(pSHA_CTX);
/* Return message digest, transform the UINT32 hash value to bytes */
for (index = 0; index < 5;index++)
pSHA_CTX->HashValue[index] = cpu2be32(pSHA_CTX->HashValue[index]);
/* End of for */
NdisMoveMemory(DigestMessage, pSHA_CTX->HashValue, SHA1_DIGEST_SIZE);
} /* End of RT_SHA1_End */
/*
========================================================================
Routine Description:
SHA1 algorithm
Arguments:
message Message context
messageLen The length of message in bytes
Return Value:
digestMessage Digest message
Note:
None
========================================================================
*/
VOID RT_SHA1 (
IN const UINT8 Message[],
IN UINT MessageLen,
OUT UINT8 DigestMessage[])
{
SHA1_CTX_STRUC sha_ctx;
NdisZeroMemory(&sha_ctx, sizeof(SHA1_CTX_STRUC));
RT_SHA1_Init(&sha_ctx);
RT_SHA1_Append(&sha_ctx, Message, MessageLen);
RT_SHA1_End(&sha_ctx, DigestMessage);
} /* End of RT_SHA1 */
#endif /* SHA1_SUPPORT */
#ifdef SHA256_SUPPORT
/*
========================================================================
Routine Description:
Initial SHA256_CTX_STRUC
Arguments:
pSHA_CTX Pointer to SHA256_CTX_STRUC
Return Value:
None
Note:
None
========================================================================
*/
VOID RT_SHA256_Init (
IN SHA256_CTX_STRUC *pSHA_CTX)
{
NdisMoveMemory(pSHA_CTX->HashValue, SHA256_DefaultHashValue,
sizeof(SHA256_DefaultHashValue));
NdisZeroMemory(pSHA_CTX->Block, SHA256_BLOCK_SIZE);
pSHA_CTX->MessageLen = 0;
pSHA_CTX->BlockLen = 0;
} /* End of RT_SHA256_Init */
/*
========================================================================
Routine Description:
SHA256 computation for one block (512 bits)
Arguments:
pSHA_CTX Pointer to SHA256_CTX_STRUC
Return Value:
None
Note:
None
========================================================================
*/
VOID RT_SHA256_Hash (
IN SHA256_CTX_STRUC *pSHA_CTX)
{
UINT32 W_i,t;
UINT32 W[64];
UINT32 a,b,c,d,e,f,g,h,T1,T2;
/* Prepare the message schedule, {W_i}, 0 < t < 15 */
NdisMoveMemory(W, pSHA_CTX->Block, SHA256_BLOCK_SIZE);
for (W_i = 0; W_i < 16; W_i++)
W[W_i] = cpu2be32(W[W_i]); /* Endian Swap */
/* End of for */
/* SHA256 hash computation */
/* Initialize the working variables */
a = pSHA_CTX->HashValue[0];
b = pSHA_CTX->HashValue[1];
c = pSHA_CTX->HashValue[2];
d = pSHA_CTX->HashValue[3];
e = pSHA_CTX->HashValue[4];
f = pSHA_CTX->HashValue[5];
g = pSHA_CTX->HashValue[6];
h = pSHA_CTX->HashValue[7];
/* 64 rounds */
for (t = 0;t < 64;t++) {
if (t > 15) /* Prepare the message schedule, {W_i}, 16 < t < 63 */
W[t] = Sigma_256_1(W[t-2]) + W[t-7] + Sigma_256_0(W[t-15]) + W[t-16];
/* End of if */
T1 = h + Zsigma_256_1(e) + Ch(e,f,g) + SHA256_K[t] + W[t];
T2 = Zsigma_256_0(a) + Maj(a,b,c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
} /* End of for */
/* Compute the i^th intermediate hash value H^(i) */
pSHA_CTX->HashValue[0] += a;
pSHA_CTX->HashValue[1] += b;
pSHA_CTX->HashValue[2] += c;
pSHA_CTX->HashValue[3] += d;
pSHA_CTX->HashValue[4] += e;
pSHA_CTX->HashValue[5] += f;
pSHA_CTX->HashValue[6] += g;
pSHA_CTX->HashValue[7] += h;
NdisZeroMemory(pSHA_CTX->Block, SHA256_BLOCK_SIZE);
pSHA_CTX->BlockLen = 0;
} /* End of RT_SHA256_Hash */
/*
========================================================================
Routine Description:
The message is appended to block. If block size > 64 bytes, the SHA256_Hash
will be called.
Arguments:
pSHA_CTX Pointer to SHA256_CTX_STRUC
message Message context
messageLen The length of message in bytes
Return Value:
None
Note:
None
========================================================================
*/
VOID RT_SHA256_Append (
IN SHA256_CTX_STRUC *pSHA_CTX,
IN const UINT8 Message[],
IN UINT MessageLen)
{
UINT appendLen = 0;
UINT diffLen = 0;
while (appendLen != MessageLen) {
diffLen = MessageLen - appendLen;
if ((pSHA_CTX->BlockLen + diffLen) < SHA256_BLOCK_SIZE) {
NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen,
Message + appendLen, diffLen);
pSHA_CTX->BlockLen += diffLen;
appendLen += diffLen;
}
else
{
NdisMoveMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen,
Message + appendLen, SHA256_BLOCK_SIZE - pSHA_CTX->BlockLen);
appendLen += (SHA256_BLOCK_SIZE - pSHA_CTX->BlockLen);
pSHA_CTX->BlockLen = SHA256_BLOCK_SIZE;
RT_SHA256_Hash(pSHA_CTX);
} /* End of if */
} /* End of while */
pSHA_CTX->MessageLen += MessageLen;
} /* End of RT_SHA256_Append */
/*
========================================================================
Routine Description:
1. Append bit 1 to end of the message
2. Append the length of message in rightmost 64 bits
3. Transform the Hash Value to digest message
Arguments:
pSHA_CTX Pointer to SHA256_CTX_STRUC
Return Value:
digestMessage Digest message
Note:
None
========================================================================
*/
VOID RT_SHA256_End (
IN SHA256_CTX_STRUC *pSHA_CTX,
OUT UINT8 DigestMessage[])
{
UINT index;
UINT64 message_length_bits;
/* Append bit 1 to end of the message */
NdisFillMemory(pSHA_CTX->Block + pSHA_CTX->BlockLen, 1, 0x80);
/* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */
if (pSHA_CTX->BlockLen > 55)
RT_SHA256_Hash(pSHA_CTX);
/* End of if */
/* Append the length of message in rightmost 64 bits */
message_length_bits = pSHA_CTX->MessageLen*8;
message_length_bits = cpu2be64(message_length_bits);
NdisMoveMemory(&pSHA_CTX->Block[56], &message_length_bits, 8);
RT_SHA256_Hash(pSHA_CTX);
/* Return message digest, transform the UINT32 hash value to bytes */
for (index = 0; index < 8;index++)
pSHA_CTX->HashValue[index] = cpu2be32(pSHA_CTX->HashValue[index]);
/* End of for */
NdisMoveMemory(DigestMessage, pSHA_CTX->HashValue, SHA256_DIGEST_SIZE);
} /* End of RT_SHA256_End */
/*
========================================================================
Routine Description:
SHA256 algorithm
Arguments:
message Message context
messageLen The length of message in bytes
Return Value:
digestMessage Digest message
Note:
None
========================================================================
*/
VOID RT_SHA256 (
IN const UINT8 Message[],
IN UINT MessageLen,
OUT UINT8 DigestMessage[])
{
SHA256_CTX_STRUC sha_ctx;
NdisZeroMemory(&sha_ctx, sizeof(SHA256_CTX_STRUC));
RT_SHA256_Init(&sha_ctx);
RT_SHA256_Append(&sha_ctx, Message, MessageLen);
RT_SHA256_End(&sha_ctx, DigestMessage);
} /* End of RT_SHA256 */
#endif /* SHA256_SUPPORT */
/* End of crypt_sha2.c */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,419 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2004, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
ee_flash.c
Abstract:
Miniport generic portion header file
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#ifdef RTMP_FLASH_SUPPORT
#include "rt_config.h"
USHORT EE_FLASH_ID_LIST[]={
#ifdef RT6352
0x6352,
0x7620,
#endif /* RT6352 */
#ifdef MT76x2
#ifdef RTMP_MAC_PCI
0x7612,
0x7662,
#endif /* RTMP_MAC_PCI */
#endif /* MT76x0 */
};
static NDIS_STATUS rtmp_ee_flash_init(PRTMP_ADAPTER pAd, PUCHAR start);
INT rtmp_get_flash_id_num(VOID)
{
return (sizeof(EE_FLASH_ID_LIST) / sizeof(USHORT));
}
/*******************************************************************************
*
* Flash-based EEPROM read/write procedures.
* some chips use the flash memory instead of internal EEPROM to save the
* calibration info, we need these functions to do the read/write.
*
******************************************************************************/
int rtmp_ee_flash_read(
IN PRTMP_ADAPTER pAd,
IN USHORT Offset,
OUT USHORT *pValue)
{
if (!pAd->chipCap.ee_inited)
{
*pValue = 0xffff;
}
else
{
memcpy(pValue, pAd->eebuf + Offset, 2);
}
return (*pValue);
}
int rtmp_ee_flash_write(PRTMP_ADAPTER pAd, USHORT Offset, USHORT Data)
{
if (pAd->chipCap.ee_inited)
{
memcpy(pAd->eebuf + Offset, &Data, 2);
/*rt_nv_commit();*/
/*rt_cfg_commit();*/
#ifdef MULTIPLE_CARD_SUPPORT
DBGPRINT(RT_DEBUG_TRACE, ("rtmp_ee_flash_write:pAd->MC_RowID = %d\n", pAd->MC_RowID));
DBGPRINT(RT_DEBUG_TRACE, ("E2P_OFFSET = 0x%08x\n", pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID]));
if ((pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID]==0x48000) || (pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID]==0x40000))
RtmpFlashWrite(pAd->eebuf, pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID], EEPROM_SIZE);
#else
RtmpFlashWrite(pAd->eebuf, pAd->flash_offset, EEPROM_SIZE);
#endif /* MULTIPLE_CARD_SUPPORT */
}
return 0;
}
VOID rtmp_ee_flash_read_all(PRTMP_ADAPTER pAd, USHORT *Data)
{
if (!pAd->chipCap.ee_inited)
return;
memcpy(Data, pAd->eebuf, EEPROM_SIZE);
}
VOID rtmp_ee_flash_write_all(PRTMP_ADAPTER pAd, USHORT *Data)
{
if (!pAd->chipCap.ee_inited)
return;
memcpy(pAd->eebuf, Data, EEPROM_SIZE);
#ifdef MULTIPLE_CARD_SUPPORT
DBGPRINT(RT_DEBUG_TRACE, ("rtmp_ee_flash_write_all:pAd->MC_RowID = %d\n", pAd->MC_RowID));
DBGPRINT(RT_DEBUG_TRACE, ("E2P_OFFSET = 0x%08x\n", pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID]));
if ((pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID]==0x48000) || (pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID]==0x40000))
RtmpFlashWrite(pAd->eebuf, pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID], EEPROM_SIZE);
#else
RtmpFlashWrite(pAd->eebuf, pAd->flash_offset, EEPROM_SIZE);
#endif /* MULTIPLE_CARD_SUPPORT */
}
static NDIS_STATUS rtmp_ee_flash_reset(RTMP_ADAPTER *pAd, UCHAR *start)
{
PUCHAR src;
RTMP_OS_FS_INFO osFsInfo;
RTMP_OS_FD srcf;
INT retval;
STRING file_path[128];
PSTRING file_name = NULL;
UINT32 chip_id = (pAd->ChipID >> 16);
#ifdef RT_SOC_SUPPORT
#ifdef MULTIPLE_CARD_SUPPORT
STRING BinFilePath[128];
PSTRING pBinFileName = NULL;
UINT32 ChipVerion = (pAd->MACVersion >> 16);
if (rtmp_get_default_bin_file_by_chip(pAd, ChipVerion, &pBinFileName) == TRUE)
{
if (pAd->MC_RowID > 0)
sprintf(BinFilePath, "%s%s", EEPROM_2ND_FILE_DIR, pBinFileName);
else
sprintf(BinFilePath, "%s%s", EEPROM_1ST_FILE_DIR, pBinFileName);
src = BinFilePath;
DBGPRINT(RT_DEBUG_TRACE, ("%s(): src = %s\n", __FUNCTION__, src));
}
else
#endif /* MULTIPLE_CARD_SUPPORT */
#endif /* RT_SOC_SUPPORT */
if (rtmp_get_default_bin_file_by_chip(pAd, chip_id, &file_name) == TRUE) {
sprintf(file_path, "%s%s", EEPROM_FILE_DIR, file_name);
src = file_path;
DBGPRINT(RT_DEBUG_OFF, ("%s()::src = %s\n", __FUNCTION__, src));
}
else
src = EEPROM_DEFAULT_FILE_PATH;
RtmpOSFSInfoChange(&osFsInfo, TRUE);
if (src && *src)
{
srcf = RtmpOSFileOpen(src, O_RDONLY, 0);
if (IS_FILE_OPEN_ERR(srcf))
{
DBGPRINT(RT_DEBUG_TRACE, ("--> Error opening file %s\n", src));
return NDIS_STATUS_FAILURE;
}
else
{
/* The object must have a read method*/
NdisZeroMemory(start, EEPROM_SIZE);
retval = RtmpOSFileRead(srcf, start, EEPROM_SIZE);
if (retval < 0)
{
DBGPRINT(RT_DEBUG_TRACE, ("--> Read %s error %d\n", src, -retval));
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("--> rtmp_ee_flash_reset copy %s to eeprom buffer\n", src));
}
retval = RtmpOSFileClose(srcf);
if (retval)
{
DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src));
}
}
}
RtmpOSFSInfoChange(&osFsInfo, FALSE);
return NDIS_STATUS_SUCCESS;
}
#ifdef LINUX
/* 0 -- Show ee buffer */
/* 1 -- force reset to default */
/* 2 -- Change ee settings */
int Set_EECMD_Proc(
IN PRTMP_ADAPTER pAd,
IN PUCHAR arg)
{
USHORT i;
i = simple_strtol(arg, 0, 10);
switch(i)
{
case 0:
{
USHORT value, k;
for (k = 0; k < EEPROM_SIZE; k+=2)
{
RT28xx_EEPROM_READ16(pAd, k, value);
DBGPRINT(RT_DEBUG_OFF, ("%4.4x ", value));
if (((k+2) % 0x20) == 0)
DBGPRINT(RT_DEBUG_OFF,("\n"));
}
}
break;
case 1:
if (pAd->infType == RTMP_DEV_INF_RBUS)
{
DBGPRINT(RT_DEBUG_OFF, ("EEPROM reset to default......\n"));
DBGPRINT(RT_DEBUG_OFF, ("The last byte of MAC address will be re-generated...\n"));
if (rtmp_ee_flash_reset(pAd, pAd->eebuf) != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR, ("Set_EECMD_Proc: rtmp_ee_flash_reset() failed\n"));
return FALSE;
}
/* Random number for the last bytes of MAC address*/
{
USHORT Addr45;
rtmp_ee_flash_read(pAd, 0x08, &Addr45);
Addr45 = Addr45 & 0xff;
Addr45 = Addr45 | (RandomByte(pAd)&0xf8) << 8;
DBGPRINT(RT_DEBUG_OFF, ("Addr45 = %4x\n", Addr45));
rtmp_ee_flash_write(pAd, 0x08, Addr45);
}
if ((rtmp_ee_flash_read(pAd, 0, &i) != 0x2880) && (rtmp_ee_flash_read(pAd, 0, &i) != 0x2860))
{
DBGPRINT(RT_DEBUG_ERROR, ("Set_EECMD_Proc: invalid eeprom\n"));
return FALSE;
}
}
break;
case 2:
{
USHORT offset, value = 0;
PUCHAR p;
p = arg+2;
offset = simple_strtol(p, 0, 10);
p+=2;
while (*p != '\0')
{
if (*p >= '0' && *p <= '9')
value = (value << 4) + (*p - 0x30);
else if (*p >= 'a' && *p <= 'f')
value = (value << 4) + (*p - 0x57);
else if (*p >= 'A' && *p <= 'F')
value = (value << 4) + (*p - 0x37);
p++;
}
RT28xx_EEPROM_WRITE16(pAd, offset, value);
}
break;
default:
break;
}
return TRUE;
}
#endif /* LINUX */
static BOOLEAN validFlashEepromID(RTMP_ADAPTER *pAd)
{
USHORT eeFlashId;
int listIdx, num_flash_id;
num_flash_id = rtmp_get_flash_id_num();
rtmp_ee_flash_read(pAd, 0, &eeFlashId);
for(listIdx =0 ; listIdx < num_flash_id; listIdx++)
{
if (eeFlashId == EE_FLASH_ID_LIST[listIdx])
return TRUE;
}
return FALSE;
}
static NDIS_STATUS rtmp_ee_flash_init(PRTMP_ADAPTER pAd, PUCHAR start)
{
#ifdef CAL_FREE_IC_SUPPORT
BOOLEAN bCalFree=0;
#endif /* CAL_FREE_IC_SUPPORT */
pAd->chipCap.ee_inited = 1;
if (validFlashEepromID(pAd) == FALSE)
{
if (rtmp_ee_flash_reset(pAd, start) != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_ERROR, ("rtmp_ee_init(): rtmp_ee_flash_init() failed\n"));
return NDIS_STATUS_FAILURE;
}
/* Random number for the last bytes of MAC address*/
{
USHORT Addr45;
rtmp_ee_flash_read(pAd, 0x08, &Addr45);
Addr45 = Addr45 & 0xff;
Addr45 = Addr45 | (RandomByte(pAd)&0xf8) << 8;
#ifdef CAL_FREE_IC_SUPPORT
RTMP_CAL_FREE_IC_CHECK(pAd, bCalFree);
if ( bCalFree == TRUE ) {
RTMP_CAL_FREE_DATA_GET(pAd);
DBGPRINT(RT_DEBUG_TRACE, ("Load Cal Free data from e-fuse.\n"));
}
#endif /* CAL_FREE_IC_SUPPORT */
rtmp_ee_flash_write(pAd, 0x08, Addr45);
DBGPRINT(RT_DEBUG_ERROR, ("The EEPROM in Flash is wrong, use default\n"));
}
if (validFlashEepromID(pAd) == FALSE)
{
DBGPRINT(RT_DEBUG_ERROR, ("rtmp_ee_flash_init(): invalid eeprom\n"));
return NDIS_STATUS_FAILURE;
}
}
return NDIS_STATUS_SUCCESS;
}
NDIS_STATUS rtmp_nv_init(RTMP_ADAPTER *pAd)
{
#ifdef MULTIPLE_CARD_SUPPORT
UCHAR *eepromBuf;
#endif /* MULTIPLE_CARD_SUPPORT */
DBGPRINT(RT_DEBUG_TRACE, ("--> rtmp_nv_init\n"));
/*
if (pAd->chipCap.EEPROMImage == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("pAd->chipCap.EEPROMImage == NULL!!!\n"));
return NDIS_STATUS_FAILURE;
}
*/
/* ASSERT((pAd->eebuf == NULL)); */
pAd->eebuf = pAd->EEPROMImage;
#ifdef MULTIPLE_CARD_SUPPORT
DBGPRINT(RT_DEBUG_OFF, ("rtmp_nv_init:pAd->MC_RowID = %d\n", pAd->MC_RowID));
os_alloc_mem(pAd, &eepromBuf, EEPROM_SIZE);
if (eepromBuf)
{
pAd->eebuf = eepromBuf;
NdisMoveMemory(pAd->eebuf, pAd->chipCap.EEPROM_DEFAULT_BIN, EEPROM_SIZE);
}
else
{
DBGPRINT(RT_DEBUG_ERROR,("rtmp_nv_init:Alloc memory for pAd->MC_RowID[%d] failed! used default one!\n", pAd->MC_RowID));
}
DBGPRINT(RT_DEBUG_OFF, ("E2P_OFFSET = 0x%08x\n", pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID]));
RtmpFlashRead(pAd->eebuf, pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID], EEPROM_SIZE);
#else
RtmpFlashRead(pAd->eebuf, pAd->flash_offset, EEPROM_SIZE);
#endif /* MULTIPLE_CARD_SUPPORT */
return rtmp_ee_flash_init(pAd, pAd->eebuf);
}
INT Set_LoadEepromBufferFromFlash_Proc(RTMP_ADAPTER *pAd, PSTRING arg)
{
UINT bEnable = simple_strtol(arg, 0, 10);
UINT free_blk = 0;
if (bEnable < 0)
return FALSE;
else
{
DBGPRINT(RT_DEBUG_TRACE, ("Load EEPROM buffer from flash, and change to BIN buffer mode\n"));
NdisZeroMemory(pAd->EEPROMImage, MAX_EEPROM_BIN_FILE_SIZE);
RtmpFlashRead(pAd->EEPROMImage, pAd->flash_offset, MAX_EEPROM_BUFFER_SIZE);
/* Change to BIN eeprom buffer mode */
pAd->E2pAccessMode = E2P_BIN_MODE;
RtmpChipOpsEepromHook(pAd, pAd->infType);
return TRUE;
}
}
#endif /* RTMP_FLASH_SUPPORT */

View File

@ -0,0 +1,282 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2004, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
ee_prom.c
Abstract:
Miniport generic portion header file
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#include "rt_config.h"
/* IRQL = PASSIVE_LEVEL*/
static inline VOID RaiseClock(
IN PRTMP_ADAPTER pAd,
IN UINT32 *x)
{
*x = *x | EESK;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
RtmpusecDelay(1); /* Max frequency = 1MHz in Spec. definition */
}
/* IRQL = PASSIVE_LEVEL*/
static inline VOID LowerClock(
IN PRTMP_ADAPTER pAd,
IN UINT32 *x)
{
*x = *x & ~EESK;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
RtmpusecDelay(1);
}
/* IRQL = PASSIVE_LEVEL*/
static inline USHORT ShiftInBits(
IN PRTMP_ADAPTER pAd)
{
UINT32 x,i;
USHORT data=0;
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~( EEDO | EEDI);
for(i=0; i<16; i++)
{
data = data << 1;
RaiseClock(pAd, &x);
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
LowerClock(pAd, &x); /*prevent read failed*/
x &= ~(EEDI);
if(x & EEDO)
data |= 1;
}
return data;
}
/* IRQL = PASSIVE_LEVEL*/
static inline VOID ShiftOutBits(
IN PRTMP_ADAPTER pAd,
IN USHORT data,
IN USHORT count)
{
UINT32 x,mask;
mask = 0x01 << (count - 1);
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~(EEDO | EEDI);
do
{
x &= ~EEDI;
if(data & mask) x |= EEDI;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
RaiseClock(pAd, &x);
LowerClock(pAd, &x);
mask = mask >> 1;
} while(mask);
x &= ~EEDI;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
}
/* IRQL = PASSIVE_LEVEL*/
static inline VOID EEpromCleanup(
IN PRTMP_ADAPTER pAd)
{
UINT32 x;
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~(EECS | EEDI);
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
RaiseClock(pAd, &x);
LowerClock(pAd, &x);
}
static inline VOID EWEN(
IN PRTMP_ADAPTER pAd)
{
UINT32 x;
/* reset bits and set EECS*/
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~(EEDI | EEDO | EESK);
x |= EECS;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
/* kick a pulse*/
RaiseClock(pAd, &x);
LowerClock(pAd, &x);
/* output the read_opcode and six pulse in that order */
ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5);
ShiftOutBits(pAd, 0, 6);
EEpromCleanup(pAd);
}
static inline VOID EWDS(
IN PRTMP_ADAPTER pAd)
{
UINT32 x;
/* reset bits and set EECS*/
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~(EEDI | EEDO | EESK);
x |= EECS;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
/* kick a pulse*/
RaiseClock(pAd, &x);
LowerClock(pAd, &x);
/* output the read_opcode and six pulse in that order */
ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5);
ShiftOutBits(pAd, 0, 6);
EEpromCleanup(pAd);
}
/* IRQL = PASSIVE_LEVEL*/
int rtmp_ee_prom_read16(
IN RTMP_ADAPTER *pAd,
IN USHORT Offset,
OUT USHORT *pValue)
{
UINT32 x;
USHORT data;
Offset /= 2;
/* reset bits and set EECS*/
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~(EEDI | EEDO | EESK);
x |= EECS;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
/* patch can not access e-Fuse issue*/
if (IS_RT2860(pAd))
{
/* kick a pulse*/
RaiseClock(pAd, &x);
LowerClock(pAd, &x);
}
/* output the read_opcode and register number in that order */
ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3);
ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
/* Now read the data (16 bits) in from the selected EEPROM word*/
data = ShiftInBits(pAd);
EEpromCleanup(pAd);
*pValue = data;
return NDIS_STATUS_SUCCESS;
}
int rtmp_ee_prom_write16(
IN RTMP_ADAPTER *pAd,
IN USHORT Offset,
IN USHORT Data)
{
UINT32 x;
Offset /= 2;
EWEN(pAd);
/* reset bits and set EECS*/
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~(EEDI | EEDO | EESK);
x |= EECS;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
/* patch can not access e-Fuse issue*/
if (IS_RT2860(pAd))
{
/* kick a pulse*/
RaiseClock(pAd, &x);
LowerClock(pAd, &x);
}
/* output the read_opcode ,register number and data in that order */
ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3);
ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
ShiftOutBits(pAd, Data, 16); /* 16-bit access*/
/* read DO status*/
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
EEpromCleanup(pAd);
RtmpusecDelay(10000); /*delay for twp(MAX)=10ms*/
EWDS(pAd);
EEpromCleanup(pAd);
return NDIS_STATUS_SUCCESS;
}
INT rtmp_ee_write_to_prom(
IN PRTMP_ADAPTER pAd)
{
USHORT value, offset = 0;
{
for (offset = 0; offset < (EEPROM_SIZE >> 1);)
{
value = ((PUSHORT)pAd->EEPROMImage)[offset];
//RT28xx_EEPROM_WRITE16(pAd, (offset << 1), value);
rtmp_ee_prom_write16(pAd,(offset << 1), value);
offset++;
}
}
return TRUE;
}

View File

@ -0,0 +1,533 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2004, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
eeprom.c
Abstract:
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Name Date Modification logs
*/
#include "rt_config.h"
struct chip_map{
UINT32 ChipVersion;
PSTRING name;
};
struct chip_map RTMP_CHIP_E2P_FILE_TABLE[] = {
#ifdef MT76x2
{0x7602, "MT7602E_EEPROM.bin"},
{0x7612, "MT7612E_EEPROM.bin"},
#endif
#ifdef RT6352
{0x7620, "MT7620_AP_2T2R-4L_V15.BIN"},
#endif
{0, NULL}
};
#ifdef RTMP_FLASH_SUPPORT
extern USHORT EE_FLASH_ID_LIST[];
#endif /* RTMP_FLASH_SUPPORT */
UCHAR RtmpEepromGetDefault(
IN RTMP_ADAPTER *pAd)
{
UCHAR e2p_default = E2P_FLASH_MODE;
#if defined (DRIVER_HAS_MULTI_DEV)
if ( pAd->dev_idx == 0 )
{
if ( RTMPEqualMemory("efuse", CONFIG_RT_FIRST_CARD_EEPROM, 5) )
e2p_default = E2P_EFUSE_MODE;
if ( RTMPEqualMemory("prom", CONFIG_RT_FIRST_CARD_EEPROM, 4) )
e2p_default = E2P_EEPROM_MODE;
if ( RTMPEqualMemory("flash", CONFIG_RT_FIRST_CARD_EEPROM, 5) )
e2p_default = E2P_FLASH_MODE;
goto out;
}
if ( pAd->dev_idx == 1 )
{
if ( RTMPEqualMemory("efuse", CONFIG_RT_SECOND_CARD_EEPROM, 5) )
e2p_default = E2P_EFUSE_MODE;
if ( RTMPEqualMemory("prom", CONFIG_RT_SECOND_CARD_EEPROM, 4) )
e2p_default = E2P_EEPROM_MODE;
if ( RTMPEqualMemory("flash", CONFIG_RT_SECOND_CARD_EEPROM, 5) )
e2p_default = E2P_FLASH_MODE;
goto out;
}
out:
#endif
DBGPRINT(RT_DEBUG_OFF, ("%s::e2p_default=%d\n", __FUNCTION__, e2p_default));
return e2p_default;
}
#if defined(RTMP_EFUSE_SUPPORT) && defined(RTMP_FLASH_SUPPORT)
static VOID RtmpEepromTypeAdjust(RTMP_ADAPTER *pAd, UCHAR *pE2pType)
{
UINT EfuseFreeBlock=0;
eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock);
if (EfuseFreeBlock >= pAd->chipCap.EFUSE_RESERVED_SIZE)
{
DBGPRINT(RT_DEBUG_OFF, ("NVM is efuse and the information is too less to bring up the interface\n"));
DBGPRINT(RT_DEBUG_OFF, ("Force to use Flash mode\n"));
*pE2pType = E2P_FLASH_MODE;
}
else
{
USHORT eeFlashId = 0;
int listIdx, num_flash_id;
BOOLEAN bFound = FALSE;
num_flash_id = rtmp_get_flash_id_num();
rtmp_ee_efuse_read16(pAd, 0, &eeFlashId);
DBGPRINT(RT_DEBUG_OFF, ("%s:: eeFlashId = 0x%x.\n", __FUNCTION__, eeFlashId));
for(listIdx =0 ; listIdx < num_flash_id; listIdx++)
{
if (eeFlashId == EE_FLASH_ID_LIST[listIdx])
{
bFound = TRUE;
break;
}
}
if (bFound == FALSE)
{
*pE2pType = E2P_FLASH_MODE;
pAd->bUseEfuse = FALSE;
}
}
}
#endif /* defined(RTMP_EFUSE_SUPPORT) && defined(RTMP_FLASH_SUPPORT) */
INT RtmpChipOpsEepromHook(
IN RTMP_ADAPTER *pAd,
IN INT infType)
{
RTMP_CHIP_OP *pChipOps = &pAd->chipOps;
UCHAR e2p_type;
UINT32 val;
#ifdef TXBF_SUPPORT
if (pAd->chipCap.FlgITxBfBinWrite)
pAd->E2pAccessMode = E2P_BIN_MODE;
#endif
/* We can't open file here beacuse it could get file open error. */
e2p_type = pAd->E2pAccessMode;
DBGPRINT(RT_DEBUG_OFF, ("%s::e2p_type=%d, inf_Type=%d\n", __FUNCTION__, e2p_type, infType));
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))
return -1;
/* If e2p_type is out of range, get the default mode */
e2p_type = ((e2p_type != 0) && (e2p_type < NUM_OF_E2P_MODE)) ? e2p_type : RtmpEepromGetDefault(pAd);
if (infType == RTMP_DEV_INF_RBUS)
{
e2p_type = E2P_FLASH_MODE;
pChipOps->loadFirmware = NULL;
}
#if defined(RTMP_EFUSE_SUPPORT) && defined(RTMP_FLASH_SUPPORT)
else if (pAd->E2pAccessMode == E2P_NONE)
{
/*
User doesn't set E2pAccessMode in profile, adjust access mode automatically here.
*/
efuse_probe(pAd);
if (pAd->bUseEfuse)
RtmpEepromTypeAdjust(pAd, &e2p_type);
}
#endif /* defined(RTMP_EFUSE_SUPPORT) && defined(RTMP_FLASH_SUPPORT) */
pAd->E2pAccessMode = e2p_type;
switch (e2p_type)
{
case E2P_EEPROM_MODE:
break;
case E2P_BIN_MODE:
{
pChipOps->eeinit = rtmp_ee_load_from_bin;
pChipOps->eeread = rtmp_ee_bin_read16;
pChipOps->eewrite = rtmp_ee_bin_write16;
DBGPRINT(RT_DEBUG_OFF, ("NVM is BIN mode\n"));
return 0;
}
#ifdef RTMP_FLASH_SUPPORT
case E2P_FLASH_MODE:
{
pChipOps->eeinit = rtmp_nv_init;
pChipOps->eeread = rtmp_ee_flash_read;
pChipOps->eewrite = rtmp_ee_flash_write;
pAd->flash_offset = DEFAULT_RF_OFFSET;
#if defined (DRIVER_HAS_MULTI_DEV)
if ( pAd->dev_idx == 0 )
pAd->flash_offset = CONFIG_RT_FIRST_IF_RF_OFFSET;
if ( pAd->dev_idx == 1 )
pAd->flash_offset = CONFIG_RT_SECOND_IF_RF_OFFSET;
#endif
DBGPRINT(RT_DEBUG_OFF, ("NVM is FLASH mode\n"));
return 0;
}
#endif /* RTMP_FLASH_SUPPORT */
#ifdef RTMP_EFUSE_SUPPORT
case E2P_EFUSE_MODE:
default:
{
efuse_probe(pAd);
if (pAd->bUseEfuse)
{
pChipOps->eeinit = eFuse_init;
pChipOps->eeread = rtmp_ee_efuse_read16;
pChipOps->eewrite = rtmp_ee_efuse_write16;
DBGPRINT(RT_DEBUG_OFF, ("NVM is EFUSE mode\n"));
return 0;
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s::hook efuse mode failed\n", __FUNCTION__));
break;
}
}
#endif /* RTMP_EFUSE_SUPPORT */
}
/* Hook functions based on interface types for EEPROM */
switch (infType)
{
#ifdef RTMP_PCI_SUPPORT
case RTMP_DEV_INF_PCI:
case RTMP_DEV_INF_PCIE:
RTMP_IO_READ32(pAd, E2PROM_CSR, &val);
if (((val & 0x30) == 0) && (!IS_RT3290(pAd)))
pAd->EEPROMAddressNum = 6; /* 93C46 */
else
pAd->EEPROMAddressNum = 8; /* 93C66 or 93C86 */
pChipOps->eeinit = NULL;
pChipOps->eeread = rtmp_ee_prom_read16;
pChipOps->eewrite = rtmp_ee_prom_write16;
break;
#endif /* RTMP_PCI_SUPPORT */
default:
DBGPRINT(RT_DEBUG_ERROR, ("%s::hook failed\n", __FUNCTION__));
break;
}
DBGPRINT(RT_DEBUG_OFF, ("NVM is EEPROM mode\n"));
return 0;
}
BOOLEAN rtmp_get_default_bin_file_by_chip(
IN PRTMP_ADAPTER pAd,
IN UINT32 ChipVersion,
OUT PSTRING *pBinFileName)
{
BOOLEAN found = FALSE;
INT i;
DBGPRINT(RT_DEBUG_OFF, ("%s::chip version=0x%04x\n", __FUNCTION__, ChipVersion));
for (i = 0; RTMP_CHIP_E2P_FILE_TABLE[i].ChipVersion != 0; i++ )
{
#ifdef RT6352
if (IS_RT6352(pAd))
{
ChipVersion = 0x7620;
}
#endif
if (RTMP_CHIP_E2P_FILE_TABLE[i].ChipVersion == ChipVersion)
{
*pBinFileName = RTMP_CHIP_E2P_FILE_TABLE[i].name;
DBGPRINT(RT_DEBUG_OFF,
("%s(): Found E2P bin file name:%s\n",
__FUNCTION__, *pBinFileName));
found = TRUE;
break;
}
}
if (found == TRUE)
DBGPRINT(RT_DEBUG_OFF, ("%s::Found E2P bin file name=%s\n", __FUNCTION__, *pBinFileName));
else
DBGPRINT(RT_DEBUG_ERROR, ("%s::E2P bin file name not found\n", __FUNCTION__));
return found;
}
INT rtmp_ee_bin_read16(
IN RTMP_ADAPTER *pAd,
IN USHORT Offset,
OUT USHORT *pValue)
{
DBGPRINT(RT_DEBUG_TRACE, ("%s::Read from EEPROM buffer\n", __FUNCTION__));
NdisMoveMemory(pValue, &(pAd->EEPROMImage[Offset]), 2);
*pValue = le2cpu16(*pValue);
return (*pValue);
}
INT rtmp_ee_bin_write16(
IN RTMP_ADAPTER *pAd,
IN USHORT Offset,
IN USHORT data)
{
DBGPRINT(RT_DEBUG_TRACE, ("%s::Write to EEPROM buffer\n", __FUNCTION__));
data = le2cpu16(data);
NdisMoveMemory(&(pAd->EEPROMImage[Offset]), &data, 2);
return 0;
}
INT rtmp_ee_load_from_bin(
IN PRTMP_ADAPTER pAd)
{
PSTRING src = NULL;
INT ret_val;
RTMP_OS_FD srcf;
RTMP_OS_FS_INFO osFSInfo;
#ifdef RT_SOC_SUPPORT
#ifdef MULTIPLE_CARD_SUPPORT
STRING bin_file_path[128];
PSTRING bin_file_name = NULL;
UINT32 chip_ver = (pAd->MACVersion >> 16);
if (rtmp_get_default_bin_file_by_chip(pAd, chip_ver, &bin_file_name) == TRUE)
{
if (pAd->MC_RowID > 0)
sprintf(bin_file_path, "%s%s", EEPROM_2ND_FILE_DIR, bin_file_name);
else
sprintf(bin_file_path, "%s%s", EEPROM_1ST_FILE_DIR, bin_file_name);
src = bin_file_path;
}
else
#endif /* MULTIPLE_CARD_SUPPORT */
#endif /* RT_SOC_SUPPORT */
src = BIN_FILE_PATH;
DBGPRINT(RT_DEBUG_TRACE, ("%s::FileName=%s\n", __FUNCTION__, src));
RtmpOSFSInfoChange(&osFSInfo, TRUE);
if (src && *src)
{
srcf = RtmpOSFileOpen(src, O_RDONLY, 0);
if (IS_FILE_OPEN_ERR(srcf))
{
DBGPRINT(RT_DEBUG_ERROR, ("%s::Error opening %s\n", __FUNCTION__, src));
return FALSE;
}
else
{
NdisZeroMemory(pAd->EEPROMImage, MAX_EEPROM_BIN_FILE_SIZE);
ret_val = RtmpOSFileRead(srcf, (PSTRING)pAd->EEPROMImage, MAX_EEPROM_BIN_FILE_SIZE);
if (ret_val > 0)
ret_val = NDIS_STATUS_SUCCESS;
else
DBGPRINT(RT_DEBUG_ERROR, ("%s::Read file \"%s\" failed(errCode=%d)!\n", __FUNCTION__, src, ret_val));
}
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s::Error src or srcf is null\n", __FUNCTION__));
return FALSE;
}
ret_val = RtmpOSFileClose(srcf);
if (ret_val)
DBGPRINT(RT_DEBUG_ERROR, ("%s::Error %d closing %s\n", __FUNCTION__, -ret_val, src));
RtmpOSFSInfoChange(&osFSInfo, FALSE);
return TRUE;
}
INT rtmp_ee_write_to_bin(
IN PRTMP_ADAPTER pAd)
{
PSTRING src = NULL;
INT ret_val;
RTMP_OS_FD srcf;
RTMP_OS_FS_INFO osFSInfo;
#ifdef RT_SOC_SUPPORT
#ifdef MULTIPLE_CARD_SUPPORT
STRING bin_file_path[128];
PSTRING bin_file_name = NULL;
UINT32 chip_ver = (pAd->MACVersion >> 16);
if (rtmp_get_default_bin_file_by_chip(pAd, chip_ver, &bin_file_name) == TRUE)
{
if (pAd->MC_RowID > 0)
sprintf(bin_file_path, "%s%s", EEPROM_2ND_FILE_DIR, bin_file_name);
else
sprintf(bin_file_path, "%s%s", EEPROM_1ST_FILE_DIR, bin_file_name);
src = bin_file_path;
}
else
#endif /* MULTIPLE_CARD_SUPPORT */
#endif /* RT_SOC_SUPPORT */
src = BIN_FILE_PATH;
DBGPRINT(RT_DEBUG_TRACE, ("%s::FileName=%s\n", __FUNCTION__, src));
RtmpOSFSInfoChange(&osFSInfo, TRUE);
if (src && *src)
{
srcf = RtmpOSFileOpen(src, O_WRONLY|O_CREAT, 0);
if (IS_FILE_OPEN_ERR(srcf))
{
DBGPRINT(RT_DEBUG_ERROR, ("%s::Error opening %s\n", __FUNCTION__, src));
return FALSE;
}
else
RtmpOSFileWrite(srcf, (PSTRING)pAd->EEPROMImage, MAX_EEPROM_BIN_FILE_SIZE);
}
else
{
DBGPRINT(RT_DEBUG_ERROR, ("%s::Error src or srcf is null\n", __FUNCTION__));
return FALSE;
}
ret_val = RtmpOSFileClose(srcf);
if (ret_val)
DBGPRINT(RT_DEBUG_ERROR, ("%s::Error %d closing %s\n", __FUNCTION__, -ret_val, src));
RtmpOSFSInfoChange(&osFSInfo, FALSE);
return TRUE;
}
INT Set_LoadEepromBufferFromBin_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
UINT bEnable = simple_strtol(arg, 0, 10);
INT result;
#ifdef CAL_FREE_IC_SUPPORT
BOOLEAN bCalFree=0;
#endif /* CAL_FREE_IC_SUPPORT */
if (bEnable < 0)
return FALSE;
else
{
DBGPRINT(RT_DEBUG_TRACE, ("Load EEPROM buffer from BIN, and change to BIN buffer mode\n"));
result = rtmp_ee_load_from_bin(pAd);
if ( result == FALSE )
{
if ( pAd->chipCap.EEPROM_DEFAULT_BIN != NULL )
{
NdisMoveMemory(pAd->EEPROMImage, pAd->chipCap.EEPROM_DEFAULT_BIN,
pAd->chipCap.EEPROM_DEFAULT_BIN_SIZE > MAX_EEPROM_BUFFER_SIZE?MAX_EEPROM_BUFFER_SIZE:pAd->chipCap.EEPROM_DEFAULT_BIN_SIZE);
DBGPRINT(RT_DEBUG_TRACE, ("Load EEPROM Buffer from default BIN.\n"));
}
}
/* Change to BIN eeprom buffer mode */
pAd->E2pAccessMode = E2P_BIN_MODE;
RtmpChipOpsEepromHook(pAd, pAd->infType);
#ifdef CAL_FREE_IC_SUPPORT
RTMP_CAL_FREE_IC_CHECK(pAd, bCalFree);
if ( bCalFree == TRUE ) {
RTMP_CAL_FREE_DATA_GET(pAd);
DBGPRINT(RT_DEBUG_TRACE, ("Load Cal Free data from e-fuse.\n"));
}
#endif /* CAL_FREE_IC_SUPPORT */
return TRUE;
}
}
INT Set_EepromBufferWriteBack_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
UINT e2p_mode = simple_strtol(arg, 0, 10);
if (e2p_mode >= NUM_OF_E2P_MODE)
return FALSE;
switch (e2p_mode)
{
#ifdef RTMP_EFUSE_SUPPORT
case E2P_EFUSE_MODE:
DBGPRINT(RT_DEBUG_OFF, ("Write EEPROM buffer back to eFuse\n"));
rtmp_ee_write_to_efuse(pAd);
break;
#endif /* RTMP_EFUSE_SUPPORT */
#ifdef RTMP_FLASH_SUPPORT
case E2P_FLASH_MODE:
DBGPRINT(RT_DEBUG_OFF, ("Write EEPROM buffer back to Flash\n"));
rtmp_ee_flash_write_all(pAd, (PUSHORT)pAd->EEPROMImage);
break;
#endif /* RTMP_FLASH_SUPPORT */
#ifdef RT65xx
case E2P_EEPROM_MODE:
DBGPRINT(RT_DEBUG_OFF, ("Write EEPROM buffer back to EEPROM\n"));
rtmp_ee_write_to_prom(pAd);
break;
#endif /* RT65xx */
case E2P_BIN_MODE:
DBGPRINT(RT_DEBUG_OFF, ("Write EEPROM buffer back to BIN\n"));
rtmp_ee_write_to_bin(pAd);
break;
default:
DBGPRINT(RT_DEBUG_ERROR, ("%s::do not support this EEPROM access mode\n", __FUNCTION__));
return FALSE;
}
return TRUE;
}

View File

@ -0,0 +1,28 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2004, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
frq_cal.c
Abstract:
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,863 @@
/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Abstract:
All related IEEE802.11r Resource Information Container body.
***************************************************************************/
#ifdef DOT11R_FT_SUPPORT
#include "rt_config.h"
#define TYPE_FUNC
#ifdef CONFIG_STA_SUPPORT
/* ----- RIC Linked List ----- */
/* insert a resource request of a AP */
#define FT_RIC_AP_LIST_INSERT_TAIL(__pAd, __pList, __pEntry) \
{ \
RTMP_SEM_LOCK(&(__pAd)->FT_RicLock); \
insertTailList((__pList), (LIST_ENTRY *)(__pEntry)); \
RTMP_SEM_UNLOCK(&(__pAd)->FT_RicLock); \
}
/* get a resource request from the head of list */
#define FT_RIC_AP_LIST_REMOVE_HEAD(__pAd, __pList, __pEntry) \
{ \
RTMP_SEM_LOCK(&(__pAd)->FT_RicLock); \
__pEntry = (FT_RIC_AP *)removeHeadList((__pList)); \
RTMP_SEM_UNLOCK(&(__pAd)->FT_RicLock); \
}
/* get number of resource request */
#define FT_RIC_AP_LIST_SIZE_GET(__pAd, __pList, __Size) \
{ \
RTMP_SEM_LOCK(&(__pAd)->FT_RicLock); \
__Size = getListSize((__pList)); \
RTMP_SEM_UNLOCK(&(__pAd)->FT_RicLock); \
}
/* get a resource request by AP MAC */
#define FT_RIC_AP_LIST_ENTRY_GET(__pAd, __pList, __pApMac, __FlgIsFound, __pEntry)\
{ \
UINT32 __Size, __IdEntry; \
FT_RIC_AP *__pRscAp; \
RTMP_SEM_LOCK(&(__pAd)->FT_RicLock); \
__Size = getListSize((__pList)); \
__FlgIsFound = FALSE; \
for(__IdEntry=0; __IdEntry<__Size; __IdEntry++) \
{ \
__pRscAp = (FT_RIC_AP *)removeHeadList((__pList)); \
if (memcmp(__pRscAp->AP_MAC, __pApMac, ETH_ALEN) == 0) \
{ \
memcpy(__pEntry, __pRscAp, sizeof(FT_RIC_AP)); \
insertTailList((__pList), (LIST_ENTRY *)(__pRscAp));\
__FlgIsFound = TRUE; \
break; \
} \
insertTailList((__pList), (LIST_ENTRY *)(__pRscAp)); \
} \
RTMP_SEM_UNLOCK(&(__pAd)->FT_RicLock); \
}
/* set status to a resource request by AP MAC */
#define FT_RIC_AP_LIST_ENTRY_SET(__pAd, __pList, __pApMac, __pEntry)\
{ \
UINT32 __Size, __IdEntry; \
FT_RIC_AP *__pRscAp; \
RTMP_SEM_LOCK(&(__pAd)->FT_RicLock); \
__Size = getListSize((__pList)); \
for(__IdEntry=0; __IdEntry<__Size; __IdEntry++) \
{ \
__pRscAp = (FT_RIC_AP *)removeHeadList((__pList)); \
if (memcmp(__pRscAp->AP_MAC, __pApMac, ETH_ALEN) == 0) \
{ \
memcpy(__pRscAp, __pEntry, sizeof(FT_RIC_AP)); \
insertTailList((__pList), (LIST_ENTRY *)(__pRscAp));\
break; \
} \
insertTailList((__pList), (LIST_ENTRY *)(__pRscAp)); \
} \
RTMP_SEM_UNLOCK(&(__pAd)->FT_RicLock); \
}
/* delete a resource request by AP MAC */
#define FT_RIC_AP_LIST_ENTRY_DEL(__pAd, __pList, __pApMac) \
{ \
UINT32 __Size, __IdEntry; \
FT_RIC_AP *__pRscAp; \
RTMP_SEM_LOCK(&(__pAd)->FT_RicLock); \
__Size = getListSize((__pList)); \
for(__IdEntry=0; __IdEntry<__Size; __IdEntry++) \
{ \
__pRscAp = (FT_RIC_AP *)removeHeadList((__pList)); \
if (memcmp(__pRscAp->AP_MAC, __pApMac, ETH_ALEN) == 0) \
{ \
os_free_mem(NULL, __pRscAp); \
break; \
} \
insertTailList((__pList), (LIST_ENTRY *)(__pRscAp)); \
} \
RTMP_SEM_UNLOCK(&(__pAd)->FT_RicLock); \
}
/* clear all resource requests */
#define FT_RIC_AP_LIST_EMPTY(__pAd, __pList) \
{ \
FT_RIC_AP *__pEntry; \
RTMP_SEM_LOCK(&(__pAd)->FT_RicLock); \
__pEntry = (FT_RIC_AP *)removeHeadList((__pList)); \
while(__pEntry != NULL) \
{ \
os_free_mem(NULL, __pEntry); \
__pEntry = (FT_RIC_AP *)removeHeadList((__pList)); \
} \
RTMP_SEM_UNLOCK(&(__pAd)->FT_RicLock); \
}
#endif /* CONFIG_STA_SUPPORT */
/*
========================================================================
Routine Description:
Initialize FT RIC Module.
Arguments:
pAd - WLAN control block pointer
Return Value:
None
Note:
========================================================================
*/
VOID TYPE_FUNC FT_RIC_Init(
IN PRTMP_ADAPTER pAd)
{
DBGPRINT(RT_DEBUG_TRACE, ("ap_ftrc> Initialize FT RIC Module...\n"));
#ifdef CONFIG_STA_SUPPORT
/* allocate control block */
if (pAd->pFT_RIC_Ctrl_BK == NULL)
{
os_alloc_mem(pAd, (UCHAR **)&pAd->pFT_RIC_Ctrl_BK,
sizeof(FT_RIC_CTRL_BLOCK));
if (pAd->pFT_RIC_Ctrl_BK == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("ap_ftrc> Allocate control block fail!\n"));
return;
} /* End of if */
/* init spin lock */
NdisAllocateSpinLock(pAd, &(pAd->FT_RicLock));
/* init resource list */
initList(&(FT_RIC_CB->ResourceList));
} /* End of if */
#endif /* CONFIG_STA_SUPPORT */
} /* End of FT_RIC_Init */
/*
========================================================================
Routine Description:
Release FT RIC Module.
Arguments:
pAd - WLAN control block pointer
Return Value:
None
Note:
========================================================================
*/
VOID TYPE_FUNC FT_RIC_Release(
IN PRTMP_ADAPTER pAd)
{
DBGPRINT(RT_DEBUG_TRACE, ("ap_ftrc> Release FT RIC Module...\n"));
#ifdef CONFIG_STA_SUPPORT
if (pAd->pFT_RIC_Ctrl_BK != NULL)
{
/* free resource list */
FT_RIC_AP_LIST_EMPTY(pAd, &(FT_RIC_CB->ResourceList));
/* free spin lock */
NdisFreeSpinLock(&(pAd->FT_RicLock));
os_free_mem(pAd, pAd->pFT_RIC_Ctrl_BK);
pAd->pFT_RIC_Ctrl_BK = NULL;
} /* End of if */
#endif /* CONFIG_STA_SUPPORT */
} /* End of FT_KDP_Release */
#ifdef CONFIG_STA_SUPPORT
/*
========================================================================
Routine Description:
Start to do resource request for other APs.
Arguments:
pAd - WLAN control block pointer
Return Value:
TRUE - successfully
FALSE - no any resource is needed to request
Note:
1. After the function is called, no any new TSPEC can be issued from us.
========================================================================
*/
BOOLEAN TYPE_FUNC FT_RIC_ResourceRequestStart(
IN PRTMP_ADAPTER pAd)
{
BOOLEAN Status = TRUE;
FT_RIC_AP_LIST_EMPTY(pAd, &FT_RIC_CB->ResourceList);
return Status;
} /* End of FT_RIC_ResourceRequestStart */
/*
========================================================================
Routine Description:
End to do resource request for other APs.
Arguments:
pAd - WLAN control block pointer
*pApMac - the new AP MAC
Return Value:
None
Note:
1. After the function is called, no any new TSPEC can be issued from us.
========================================================================
*/
VOID TYPE_FUNC FT_RIC_ResourceRequestEnd(
IN PRTMP_ADAPTER pAd,
IN UCHAR *pApMac)
{
/* empty all backup resource request entries */
FT_RIC_AP_LIST_EMPTY(pAd, &FT_RIC_CB->ResourceList);
} /* End of FT_RIC_ResourceRequestEnd */
/*
========================================================================
Routine Description:
Issue resource requests.
Arguments:
pAd - WLAN control block pointer
*pApMac - the AP MAC
*pBufReq - the request packet buffer
ReqMaxLen - the maximum remain length of request packet buffer
Return Value:
filled element length
Note:
1. Same resource type for all resource descriptors in the RDIE.
2. Suppose RDIEs are continual.
3. If pDescpBlk != NULL, skip current TSPEC.
4. 11A.11.3 Creation and handling of a resource request (11r D9.0)
(1) In using TSPECs for requesting QoS resources, the TSPECs in the
request need not belong to only active Traffic Streams;
(2) The non-AP STA can send TSPECs for any Traffic Stream that it
intends to use after the transition, and request the same resources
that would be requested by a later ADDTS exchange.
==> We do NOT support the function.
5. Resource request usage for QSTA:
Case 1:
(1) Scan or get neighbor report of other QAPs;
(2) Maybe signal is bad with current AP and good for other QAPs;
-- FT_RIC_ResourceRequestStart()
No new TSPEC can be issued.
-- FT_RIC_ResourceRequest()
Build current TSPEC to the QAP1.
(3) FT confirm to QAP1;
-- FT_RIC_ResourceResponseHandle() for QAP1.
(4) Handle FT ACK from QAP1;
(6) a. Signal is still bad so determining to reassociate a QAP;
b. Maybe signal is good again with current QAP, no roaming is needed;
-- FT_RIC_ResourceRequestEnd(ptr to TSPEC status)
Case 2:
(1) Scan or get neighbor report of other QAPs;
(2) Maybe signal is bad with current AP and good for other QAPs;
-- FT_RIC_ResourceRequestStart()
No new TSPEC can be issued.
-- FT_RIC_ResourceRequest()
Build current TSPEC to the QAP1.
(3) FT confirm to QAP1;
-- FT_RIC_ResourceRequest()
Build current TSPEC to the QAP2.
(4) FT confirm to QAP2;
-- (get success percentage) FT_RIC_ResourceResponseHandle(ptr to TSPEC status) for QAP1.
-- (get success percentage) FT_RIC_ResourceResponseHandle(ptr to TSPEC status) for QAP2.
(5) Handle FT ACK from different QAPs;
(6) a. Signal is still bad so determining to reassociate a QAP;
b. Maybe signal is good again with current QAP, no roaming is needed;
c. Select the best resource allocation;
-- FT_RIC_ResourceRequestEnd(ptr to TSPEC status)
New TSPECs can be issued.
========================================================================
*/
UINT32 TYPE_FUNC FT_RIC_ResourceRequest(
IN PRTMP_ADAPTER pAd,
IN UCHAR *pApMac,
IN UCHAR *pBufReq,
IN UINT32 ReqMaxLen)
{
FT_RIC_DESCP_BLOCK_ACK DescpBlk, *pDescpBlk;
FT_RIC_AP *pRscAp;
UINT32 FilledLen;
/* sanity check */
FT_RIC_AP_LIST_ENTRY_DEL(pAd, &FT_RIC_CB->ResourceList, pApMac);
/* init */
FilledLen = 0;
/* allocate a resource record for the AP */
/* pRscAp = (FT_RIC_AP *)kmallocos(sizeof(FT_RIC_AP), GFP_ATOMIC); */
os_alloc_mem(NULL, (UCHAR **)&pRscAp, sizeof(FT_RIC_AP));
if (pRscAp == NULL)
return 0; /* allocate fail */
/* End of if */
memset(pRscAp, 0, sizeof(FT_RIC_AP));
memcpy(pRscAp->AP_MAC, pApMac, ETH_ALEN);
/* fill BLOCK ACK resource request */
pRscAp->FlgHasBaResource = FALSE;
pDescpBlk = &DescpBlk;
/* try to get and fill BLOCK ACK resource */
/* yet implement */
/* backup the resource record */
if (FilledLen > 0)
{
FT_RIC_AP_LIST_INSERT_TAIL(pAd, &FT_RIC_CB->ResourceList, pRscAp);
}
else
{
} /* End of if */
DBGPRINT(RT_DEBUG_TRACE,
("ft_ric> FilledLen = %d\n", FilledLen));
return FilledLen;
} /* End of FT_RIC_ResourceRequest */
/*
========================================================================
Routine Description:
Handle resource responses.
Arguments:
pAd - WLAN control block pointer
*pApMac - the AP MAC
*pBufRsp - the response packet buffer
RspLen - the maximum remain length of response packet buffer
*pRspStatus - the status report
Return Value:
handled length
Note:
1. Same resource type for all resource descriptors in the RDIE.
2. Suppose RDIEs are continual.
========================================================================
*/
UINT32 TYPE_FUNC FT_RIC_ResourceResponseHandle(
IN PRTMP_ADAPTER pAd,
IN UCHAR *pApMac,
IN UCHAR *pBufRsp,
IN UINT32 RspLen,
OUT FT_RIC_STATUS *pRspStatus)
{
FT_ELM_RIC_DATA_INFO *pElmDataInfoRsp;
UCHAR *pBufRspElm, *pElmRspDescp;
FT_RIC_AP RscAp, *pRscAp;
UINT32 DescpCnt;
UINT32 HandledSize;
UCHAR RDIE_Identifier;
BOOLEAN FlgIsFound;
/* init */
if (pRspStatus == NULL)
return 0;
/* End of if */
memset(pRspStatus, 0, sizeof(FT_RIC_STATUS));
pRscAp = &RscAp;
/* sanity check resource request */
FT_RIC_AP_LIST_ENTRY_GET(pAd, &FT_RIC_CB->ResourceList, \
pApMac, FlgIsFound, pRscAp);
if (FlgIsFound == FALSE)
{
/* no any resource requset is sent to the AP */
DBGPRINT(RT_DEBUG_TRACE,
("ft_ric> No any request resource is found!\n"));
return 0;
} /* End of if */
/* init */
pBufRspElm = pBufRsp;
HandledSize = 0;
memcpy(pRspStatus->AP_MAC, pApMac, sizeof(pRspStatus->AP_MAC));
pRspStatus->FlgHasBaResource = FALSE;
pRspStatus->FlgIsBaAccepted = FALSE;
pRspStatus->TspecNumberOfRequested = 0;
/* handle all RDIEs */
/*
The non-AP STA shall construct the RIC with a number of
Resource Requests, each delineated by an RDIE.
*/
while(HandledSize < RspLen)
{
/* sanity check the RDIE */
pElmDataInfoRsp = (FT_ELM_RIC_DATA_INFO *)pBufRspElm;
if (pElmDataInfoRsp->ElmID != FT_ELM_ID_RIC_DATA_INFO)
break;
/* End of if */
/* parsing the RIC descriptors */
/*
The Resource Count shall be set to the number of alternative
Resource Descriptors that follow.
*/
RDIE_Identifier = pElmDataInfoRsp->RDIE_Identifier;
DescpCnt = pElmDataInfoRsp->RD_Count; /* must be 0 or 1 */
HandledSize += FT_ELM_HDR_LEN + pElmDataInfoRsp->ElmLen;
pElmRspDescp = pBufRspElm + FT_ELM_HDR_LEN + pElmDataInfoRsp->ElmLen;
if ((DescpCnt >= 1) &&
((*pElmRspDescp) != FT_ELM_ID_RIC_DATA_INFO) &&
(HandledSize < RspLen))
{
/* only one resource descriptor is accepted is enough */
/*
If there are multiple Resource Descriptors then these
are treated as "choices" by the target AP.
*/
switch(*pElmRspDescp)
{
case FT_ELM_ID_RIC_DESCP_INFO:
/* BLOCK ACK */
DBGPRINT(RT_DEBUG_TRACE,
("ft_ric> A resource BLOCK ACK response is found!\n"));
HandledSize += (FT_ELM_HDR_LEN + *(pElmRspDescp+1));
if ((pRscAp->FlgHasBaResource == TRUE) &&
(RDIE_Identifier == pRscAp->RDIE_IdentifierBA))
{
if (pElmDataInfoRsp->StatusCode == 0)
{
pRspStatus->FlgHasBaResource = TRUE;
pRspStatus->FlgIsBaAccepted = TRUE;
} /* End of if */
}
else
pRspStatus->UnknownRDIE ++;
/* End of if */
break;
default:
HandledSize += (FT_ELM_HDR_LEN + *(pElmRspDescp+1));
break;
} /* End of switch */
/* check next RDIE */
/* one RDIE + one Resource response (status == SUCCESS) */
pElmRspDescp += FT_ELM_HDR_LEN + *(pElmRspDescp+1);
pBufRspElm = pElmRspDescp;
}
else
{
/* only one RDIE (status != SUCCESS) */
BOOLEAN FlgIsHandled = FALSE;
/* check if the RDIE is for BA resource */
if ((pRscAp->FlgHasBaResource == TRUE) &&
(RDIE_Identifier == pRscAp->RDIE_IdentifierBA))
{
pRspStatus->FlgHasBaResource = TRUE;
pRspStatus->FlgIsBaAccepted = FALSE;
FlgIsHandled = TRUE;
}
if (FlgIsHandled == FALSE)
pRspStatus->UnknownRDIE ++;
/* End of if */
/* check next RDIE */
pBufRspElm += (FT_ELM_HDR_LEN + pElmDataInfoRsp->ElmLen);
} /* End of if */
} /* End of while */
/* save content */
FT_RIC_AP_LIST_ENTRY_SET(pAd, &FT_RIC_CB->ResourceList, pApMac, pRscAp);
return HandledSize;
} /* End of FT_RIC_ResourceResponseHandle */
#endif /* CONFIG_STA_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
/*
========================================================================
Routine Description:
Handle the resource request.
Arguments:
pAd - WLAN control block pointer
*pCdb - the source QSTA
*pBufReq - the request packet buffer
ReqLen - the length of request packet buffer
*pBufRsp - the response packet buffer
*pRspLen - the length of response content
Return Value:
non-zero - the frame length we handled
zero - no request is found
Note:
1. The start octet of the buffer is the element ID of RIC request or response.
2. Same resource type for all resource descriptors in the RDIE.
3. Suppose RDIEs are continual.
========================================================================
*/
UINT32 TYPE_FUNC FT_RIC_ResourceRequestHandle(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pCdb,
IN UCHAR *pBufReq,
IN UINT32 ReqLen,
OUT UCHAR *pBufRsp,
OUT UINT32 *pRspLen)
{
FT_ELM_RIC_DATA_INFO *pElmDataInfoReq, *pElmDataInfoRsp;
UCHAR *pBufReqElm, *pElmReqDescp;
UCHAR *pBufRspElm;
ULONG ElmLen, RspLen;
UINT32 DescpCnt;
UINT32 HandledSize;
BOOLEAN FlgIsTspecAccepted;
/* init */
pBufReqElm = pBufReq;
pBufRspElm = pBufRsp;
*pRspLen = 0;
HandledSize = 0;
/* sanity check */
if ((pCdb == NULL) ||
(pBufReq == NULL) ||
(pBufRsp == NULL) ||
(pRspLen == NULL))
{
DBGPRINT(RT_DEBUG_ERROR,
("ft_ric> (ResourceRequestHandle) Error! NULL pointer!\n"));
return 0;
} /* End of if */
/* handle all RDIEs */
/*
The non-AP STA shall construct the RIC with a number of
Resource Requests, each delineated by an RDIE.
*/
while(HandledSize < ReqLen)
{
/* sanity check the RDIE */
pElmDataInfoReq = (FT_ELM_RIC_DATA_INFO *)pBufReqElm;
if (pElmDataInfoReq->ElmID != FT_ELM_ID_RIC_DATA_INFO)
break;
/* End of if */
/* make up reponse */
/*
The RIC Response shall comprise one RDIE for each RDIE in the
RIC Request.
*/
pElmDataInfoRsp = (FT_ELM_RIC_DATA_INFO *)pBufRspElm;
pElmDataInfoRsp->ElmID = FT_ELM_ID_RIC_DATA_INFO;
pElmDataInfoRsp->ElmLen = FT_ELM_LEN_RIC_DATA_INFO;
/*
The RDIE Identifier in the RDIE shall be an arbitrary value
chosen by the non-AP STA that uniquely identifies the RDIE
within the RIC.
*/
pElmDataInfoRsp->RDIE_Identifier = pElmDataInfoReq->RDIE_Identifier;
pBufRspElm += sizeof(FT_ELM_RIC_DATA_INFO);
*pRspLen += sizeof(FT_ELM_RIC_DATA_INFO);
/* parsing the RIC descriptors */
/*
The Resource Count shall be set to the number of alternative
Resource Descriptors that follow.
*/
DescpCnt = pElmDataInfoReq->RD_Count;
FlgIsTspecAccepted = FALSE;
pElmReqDescp = ((UCHAR *)pElmDataInfoReq);
pElmReqDescp += FT_ELM_HDR_LEN + pElmDataInfoReq->ElmLen;
HandledSize += FT_ELM_HDR_LEN + pElmDataInfoReq->ElmLen;
while(DescpCnt > 0)
{
if (FlgIsTspecAccepted == FALSE)
{
/* only one resource descriptor is accepted is enough */
/*
If there are multiple Resource Descriptors then these
are treated as "choices" by the target AP.
*/
switch(*pElmReqDescp)
{
case IE_FT_RIC_DESCRIPTOR:
/* BLOCK ACK */
/* reject the resource */
DBGPRINT(RT_DEBUG_TRACE,
("ft_ric> Handle a resource request BLOCK ACK...\n"));
if (BA_ResourceAllocate(pAd,
pCdb,
pElmReqDescp,
pBufRspElm,
&RspLen) == 0)
{
DBGPRINT(RT_DEBUG_TRACE, ("ft_ric> Accept BA.\n"));
FlgIsTspecAccepted = TRUE;
}
break;
default:
break;
} /* End of switch */
} /* End of if */
/* find the next RD Descriptor element */
ElmLen = *(pElmReqDescp+1);
pElmReqDescp += FT_ELM_HDR_LEN + ElmLen;
HandledSize += FT_ELM_HDR_LEN + ElmLen;
DescpCnt --;
} /* End of while */
/* re-assign the reponse RD Count/status code of RDIE */
if (FlgIsTspecAccepted == TRUE)
{
/*
A resource request is considered successful by a non-AP STA
if the Status Code 0 is returned in each RDIE.
*/
pElmDataInfoRsp->RD_Count = 1;
pElmDataInfoRsp->StatusCode = 0;
pBufRspElm += RspLen;
*pRspLen += RspLen;
DBGPRINT(RT_DEBUG_TRACE,
("ft_ric> Accept a resource request (RspLen: %d).\n", *pRspLen));
}
else
{
/*
Status Code non-zero indicates that the resources could not
be accepted.
In this case the AP may include a single Resource Descriptor
following the RDIE indicating a suggested resource that could
have been accepted.
The Resource Count field shall be set to '0' or '1' depending
whether the suggested Resource Descriptor is attached.
A non-zero Status Code in an RDIE shall not cause a non-zero
Status Code in the auth/assoc frame containing the RIC.
*/
/* we do NOT support suggested Resource Descriptor */
pElmDataInfoRsp->RD_Count = 0; /* 0 or 1, we only support 0 */
pElmDataInfoRsp->StatusCode = FT_STATUS_CODE_RESERVED;
DBGPRINT(RT_DEBUG_TRACE, ("ft_ric> Resource request fails!\n"));
} /* End of if */
/* check next RDIE */
pBufReqElm = pElmReqDescp;
} /* End of while */
return HandledSize;
} /* End of FT_RIC_ResourceRequestHandle */
/*
========================================================================
Routine Description:
Handle the resource request.
Arguments:
pAd - WLAN control block pointer
*pMacEntry - the source QSTA
*pBufReq - the request packet buffer
ReqLen - the length of request packet buffer
*pBufRsp - the response packet buffer
*pRspLen - the length of response content
Return Value:
non-zero - the frame length we handled
zero - no request is found
Note:
1. The start octet of the buffer is the element ID of RIC request or response.
2. Same resource type for all resource descriptors in the RDIE.
3. Suppose RDIEs are continual.
========================================================================
*/
UINT32 BA_ResourceAllocate(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pMacEntry,
IN UCHAR *pBufRscReq,
OUT UCHAR *pBufRscRsp,
OUT ULONG *pBufRspLen)
{
extern BOOLEAN BARecSessionAdd(
IN PRTMP_ADAPTER pAd,
IN MAC_TABLE_ENTRY *pEntry,
IN PFRAME_ADDBA_REQ pFrame);
UINT8 IEId = IE_FT_RIC_DESCRIPTOR;
UINT8 RicType = FT_RIC_TYPE_BA;
UINT8 Len = 7;
UINT16 Status = 1;
BA_PARM BaParm; /*0 - 2 */
USHORT TimeOutValue;
FRAME_ADDBA_REQ AddreqFrame;
FT_ELM_RIC_DESCP_INFO *pRicDesInfo;
FT_RIC_DESCP_BLOCK_ACK *pRicBaInfo;
if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry))
{
UINT16 Value;
pRicDesInfo = (FT_ELM_RIC_DESCP_INFO *)pBufRscReq;
pRicBaInfo = (FT_RIC_DESCP_BLOCK_ACK *)pRicDesInfo->Container;
Value = le2cpu16(*(UINT16 *)(&pRicBaInfo->BaParm));
NdisMoveMemory((PUCHAR)&AddreqFrame.BaParm, &Value, sizeof(UINT16));
AddreqFrame.TimeOutValue = le2cpu16(pRicBaInfo->TimeOutValue);
AddreqFrame.BaStartSeq.word = le2cpu16(pRicBaInfo->BaStartSeq);
DBGPRINT(RT_DEBUG_OFF, ("Rcv Wcid(%d) AddBAReq\n", pMacEntry->Aid));
if (BARecSessionAdd(pAd, pMacEntry, &AddreqFrame))
Status = 0;
else
Status = 38; /* more parameters have invalid values */
}
else
{
Status = 37; /* the request has been declined. */
}
if (Status != 0)
return Status;
BaParm.BAPolicy = IMMED_BA;
BaParm.AMSDUSupported = 0;
BaParm.TID = AddreqFrame.BaParm.TID;
BaParm.BufSize = min(((UCHAR)AddreqFrame.BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit);
if (BaParm.BufSize == 0)
{
BaParm.BufSize = 64;
}
TimeOutValue = 0;
*(UINT16 *)(&BaParm) = cpu2le16(*(USHORT *)(&BaParm));
Status = cpu2le16(Status);
TimeOutValue = cpu2le16(TimeOutValue);
MakeOutgoingFrame( pBufRscRsp, pBufRspLen,
1, &IEId,
1, &Len,
1, &RicType,
2, &Status,
2, (UCHAR *)&BaParm,
2, &TimeOutValue,
END_OF_ARGS);
return Status;
}
#endif /* CONFIG_AP_SUPPORT */
#endif /* DOT11R_FT_SUPPORT */
/* End of ap_ftrc.c */

View File

@ -0,0 +1,182 @@
/****************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
****************************************************************************
Module Name:
ft_tlv.c
Abstract:
Revision History:
Who When What
--------- ---------- ----------------------------------------------
Fonchi Wu 12-02-2008 created for 11r soft-AP
*/
#ifdef DOT11R_FT_SUPPORT
#include "rt_config.h"
#include "dot11r_ft.h"
VOID FT_InsertMdIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN PUINT8 pMdId,
IN FT_CAP_AND_POLICY FtCapPlc)
{
ULONG TempLen;
UINT8 Length;
UCHAR MDIE = IE_FT_MDIE;
Length = 3;
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &MDIE,
1, &Length,
2, (PUCHAR)pMdId,
1, (PUCHAR)&FtCapPlc.word,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
return;
}
VOID FT_InsertFTIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN UINT8 Length,
IN FT_MIC_CTR_FIELD MICCtr,
IN PUINT8 pMic,
IN PUINT8 pANonce,
IN PUINT8 pSNonce)
{
ULONG TempLen;
UINT16 MICCtrBuf;
UCHAR FTIE = IE_FT_FTIE;
MICCtrBuf = cpu2le16(MICCtr.word);
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &FTIE,
1, &Length,
2, (PUCHAR)&MICCtrBuf,
16, (PUCHAR)pMic,
32, (PUCHAR)pANonce,
32, (PUCHAR)pSNonce,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
}
VOID FT_FTIE_InsertKhIdSubIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN FT_SUB_ELEMENT_ID SubId,
IN PUINT8 pKhId,
IN UINT8 KhIdLen)
{
ULONG TempLen;
if (SubId != FT_R0KH_ID && SubId != FT_R1KH_ID)
{
DBGPRINT(RT_DEBUG_ERROR,("(%s): unknow SubId (%d)\n",
__FUNCTION__, SubId));
return;
}
/* The lenght of R1KHID must only be 6 octects. */
if ((SubId == FT_R1KH_ID) && (KhIdLen != 6))
{
DBGPRINT(RT_DEBUG_ERROR,("(%s): Invalid R1KHID length (%d)\n",
__FUNCTION__, KhIdLen));
return;
}
/* The length of R0KHID must in range of 1 to 48 octects.*/
if ((SubId == FT_R0KH_ID) && ((KhIdLen > 48) && (KhIdLen < 1)))
{
DBGPRINT(RT_DEBUG_ERROR,("(%s): Invalid R0KHID length (%d)\n",
__FUNCTION__, KhIdLen));
}
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &SubId,
1, &KhIdLen,
KhIdLen, (PUCHAR)pKhId,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
}
VOID FT_FTIE_InsertGTKSubIE(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN PUINT8 pGtkSubIe,
IN UINT8 GtkSubIe_len)
{
ULONG TempLen;
UINT8 Length;
UINT8 SubId;
SubId = FT_GTK;
Length = GtkSubIe_len;
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &SubId,
1, &Length,
Length, pGtkSubIe,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
}
VOID FT_InsertTimeoutIntervalIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN FT_TIMEOUT_INTERVAL_TYPE Type,
IN UINT32 TimeOutValue)
{
ULONG TempLen;
UINT8 Length;
UINT8 TimeOutIntervalIE;
UINT8 TimeoutType;
UINT32 TimeoutValueBuf;
Length = 5;
TimeOutIntervalIE = IE_FT_TIMEOUT_INTERVAL;
TimeoutType = Type;
TimeoutValueBuf = cpu2le32(TimeOutValue);
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &TimeOutIntervalIE,
1, &Length,
1, (PUCHAR)&TimeoutType,
4, (PUCHAR)&TimeoutValueBuf,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
}
#endif /* DOT11R_FT_SUPPORT */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,850 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2011, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
hotspot.c
Abstract:
hotspot2.0 features
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#include "rt_config.h"
extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN];
void wext_hotspot_onoff_event(PNET_DEV net_dev, int onoff)
{
struct hs_onoff *hotspot_onoff;
u16 buflen = 0;
char *buf;
buflen = sizeof(*hotspot_onoff);
os_alloc_mem(NULL, (UCHAR **)&buf, buflen);
NdisZeroMemory(buf, buflen);
hotspot_onoff = (struct hs_onoff *)buf;
hotspot_onoff->ifindex = RtmpOsGetNetIfIndex(net_dev);
hotspot_onoff->hs_onoff = onoff;
RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM,
OID_802_11_HS_ONOFF, NULL, (PUCHAR)buf, buflen);
os_free_mem(NULL, buf);
}
void HotspotOnOffEvent(PNET_DEV net_dev, int onoff)
{
wext_hotspot_onoff_event(net_dev, onoff);
}
static void wext_hotspot_ap_reload_event(PNET_DEV net_dev)
{
struct hs_onoff *hotspot_onoff;
u16 buflen = 0;
char *buf;
buflen = sizeof(*hotspot_onoff);
os_alloc_mem(NULL, (UCHAR **)&buf, buflen);
NdisZeroMemory(buf, buflen);
hotspot_onoff = (struct hs_onoff *)buf;
hotspot_onoff->ifindex = RtmpOsGetNetIfIndex(net_dev);
RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM,
OID_802_11_HS_AP_RELOAD, NULL, (PUCHAR)buf, buflen);
os_free_mem(NULL, buf);
}
void HotspotAPReload(PNET_DEV net_dev)
{
wext_hotspot_ap_reload_event(net_dev);
}
#ifdef CONFIG_AP_SUPPORT
BOOLEAN HSIPv4Check(
IN PRTMP_ADAPTER pAd,
PUSHORT pWcid,
PNDIS_PACKET pPacket,
PUCHAR pSrcBuf,
UINT16 srcPort,
UINT16 dstPort)
{
UCHAR apidx = RTMP_GET_PACKET_NET_DEVICE(pPacket);
MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx];
if ((pMbss->HotSpotCtrl.HotSpotEnable)
#ifdef CONFIG_HOTSPOT_R2
|| (pMbss->HotSpotCtrl.bASANEnable)
#endif
)
{
if (srcPort == 0x43 && dstPort == 0x44)
{
//UCHAR *pTargetIPAddr = pSrcBuf + 24;
/* Client hardware address */
UCHAR *pTargetMACAddr = pSrcBuf + 36;
/* Convert group-address DHCP packets to individually-addressed 802.11 frames */
if (*pWcid == MCAST_WCID && pMbss->HotSpotCtrl.DGAFDisable)
{
UCHAR Index;
PUCHAR pSrcBufOriginal = GET_OS_PKT_DATAPTR(pPacket);
for (Index = 0; Index < MAC_ADDR_LEN; Index++)
{
DBGPRINT(RT_DEBUG_OFF, ("Original source address(%d) = %02x\n",Index, pSrcBufOriginal[Index]));
pSrcBufOriginal[Index] = pTargetMACAddr[Index];
DBGPRINT(RT_DEBUG_OFF, ("Source address(%d) = %02x\n", Index, pSrcBuf[Index]));
}
DBGPRINT(RT_DEBUG_OFF, ("Convert broadcast dhcp to unicat frame when dgaf disable\n"));
DBGPRINT(RT_DEBUG_OFF, ("pSrcBufOriginal:(%02x:%02x:%02x:%02x:%02x:%02x)\n", PRINT_MAC(pSrcBufOriginal)));
if (!ApAllowToSendPacket(pAd, &pAd->ApCfg.MBSSID[apidx].wdev, pPacket, (UCHAR *)pWcid))
return FALSE;
RTMP_SET_PACKET_WCID(pPacket, *pWcid);
}
}
}
return TRUE;
}
static BOOLEAN IsICMPv4EchoPacket(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pData)
{
UINT16 ProtoType;
UCHAR *Pos = pData;
NdisMoveMemory(&ProtoType, pData, 2);
ProtoType = OS_NTOHS(ProtoType);
Pos += 2;
if (ProtoType == ETH_P_IP)
{
Pos += 9;
if (*Pos == 0x01)
{
Pos += 11;
if (*Pos == 0x08)
{
Pos++;
if (*Pos == 0x00)
{
DBGPRINT(RT_DEBUG_OFF, ("ICMPv4Echp Packet\n"));
return TRUE;
}
}
}
}
return FALSE;
}
BOOLEAN L2FilterInspection(
IN PRTMP_ADAPTER pAd,
IN PHOTSPOT_CTRL pHSCtrl,
IN PUCHAR pData)
{
if (IsICMPv4EchoPacket(pAd, pData))
{
if (pHSCtrl->ICMPv4Deny)
return TRUE;
else
return FALSE;
}
return FALSE;
}
BOOLEAN ProbeReqforHSAP(
IN PRTMP_ADAPTER pAd,
IN UCHAR APIndex,
IN struct _PEER_PROBE_REQ_PARAM *ProbeReqParam)
{
PHOTSPOT_CTRL pHSCtrl;
pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl;
if (pHSCtrl->HotSpotEnable && ProbeReqParam->IsIWIE)
{
if (ProbeReqParam->IsHessid && pHSCtrl->IsHessid)
{
if(NdisEqualMemory(ProbeReqParam->Hessid, pHSCtrl->Hessid, MAC_ADDR_LEN) ||
NdisEqualMemory(ProbeReqParam->Hessid, BROADCAST_ADDR, MAC_ADDR_LEN))
;
else
return FALSE;
}
if ((ProbeReqParam->AccessNetWorkType == pHSCtrl->AccessNetWorkType) ||
(ProbeReqParam->AccessNetWorkType == 0x0f))
return TRUE;
else
return FALSE;
}
else
return TRUE;
}
inline INT Set_HotSpot_DGAF(
IN PRTMP_ADAPTER pAd,
UCHAR Disable)
{
POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
UCHAR APIndex = pObj->ioctl_if;
PHOTSPOT_CTRL pHSCtrl;
pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl;
pHSCtrl->DGAFDisable = Disable;
return 0;
}
INT Set_HotSpot_Param(
IN PRTMP_ADAPTER pAd,
UINT32 Param,
UINT32 Value)
{
POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
UCHAR APIndex = pObj->ioctl_if;
PHOTSPOT_CTRL pHSCtrl;
PWNM_CTRL pWNMCtrl;
PGAS_CTRL pGASCtrl;
pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl;
pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl;
pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl;
switch (Param) {
case PARAM_DGAF_DISABLED:
pHSCtrl->DGAFDisable = Value;
break;
case PARAM_PROXY_ARP:
pWNMCtrl->ProxyARPEnable = Value;
break;
case PARAM_L2_FILTER:
pHSCtrl->L2Filter = Value;
break;
case PARAM_ICMPV4_DENY:
pHSCtrl->ICMPv4Deny = Value;
break;
case PARAM_MMPDU_SIZE:
pHSCtrl->MMPDUSize = Value;
break;
case PARAM_EXTERNAL_ANQP_SERVER_TEST:
pGASCtrl->ExternalANQPServerTest = Value;
break;
case PARAM_GAS_COME_BACK_DELAY:
pGASCtrl->cb_delay = Value;
break;
#ifdef CONFIG_HOTSPOT_R2
case PARAM_WNM_NOTIFICATION:
pWNMCtrl->WNMNotifyEnable = Value;
break;
case PARAM_QOSMAP:
pHSCtrl->QosMapEnable = Value;
break;
#endif
default:
DBGPRINT(RT_DEBUG_ERROR, ("Unknow Parameter:%d\n", Param));
break;
}
return 0;
}
#endif /* CONFIG_AP_SUPPORT */
VOID HSCtrlRemoveAllIE(PHOTSPOT_CTRL pHSCtrl)
{
/* Remove all IE from daemon */
if (pHSCtrl->P2PIELen)
{
pHSCtrl->P2PIELen = 0;
os_free_mem(NULL, pHSCtrl->P2PIE);
}
if (pHSCtrl->HSIndicationIELen)
{
pHSCtrl->HSIndicationIELen = 0;
os_free_mem(NULL, pHSCtrl->HSIndicationIE);
}
if (pHSCtrl->InterWorkingIELen)
{
pHSCtrl->InterWorkingIELen = 0;
os_free_mem(NULL, pHSCtrl->InterWorkingIE);
}
if (pHSCtrl->AdvertisementProtoIELen)
{
pHSCtrl->AdvertisementProtoIELen = 0;
os_free_mem(NULL, pHSCtrl->AdvertisementProtoIE);
}
if (pHSCtrl->QosMapSetIELen)
{
pHSCtrl->AdvertisementProtoIELen = 0;
os_free_mem(NULL, pHSCtrl->QosMapSetIE);
}
if (pHSCtrl->RoamingConsortiumIELen)
{
pHSCtrl->RoamingConsortiumIELen = 0;
os_free_mem(NULL, pHSCtrl->RoamingConsortiumIE);
}
}
#ifdef CONFIG_AP_SUPPORT
VOID Clear_Hotspot_All_IE(
IN PRTMP_ADAPTER pAd)
{
POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
UCHAR APIndex = pObj->ioctl_if;
PHOTSPOT_CTRL pHSCtrl;
pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl;
HSCtrlRemoveAllIE(pHSCtrl);
}
#endif
INT Set_HotSpot_OnOff(
IN PRTMP_ADAPTER pAd,
IN UINT8 OnOff,
IN UINT8 EventTrigger,
IN UINT8 EventType)
{
UCHAR *Buf;
HSCTRL_EVENT_DATA *Event;
UINT32 Len = 0;
#ifdef CONFIG_AP_SUPPORT
POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie;
UCHAR APIndex = pObj->ioctl_if;
#endif /* CONFIG_AP_SUPPORT */
os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event));
if (!Buf)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__));
return FALSE;
}
NdisZeroMemory(Buf, sizeof(*Event));
Event = (HSCTRL_EVENT_DATA *)Buf;
#ifdef CONFIG_STA_SUPPORT
Event->ControlIndex = 0;
#endif /*CONFIG_STA_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
Event->ControlIndex = APIndex;
#endif /* CONFIG_STA_SUPPORT */
Len += 1;
Event->EventTrigger = EventTrigger;
Len += 1;
Event->EventType = EventType;
Len += 1;
if (OnOff)
MlmeEnqueue(pAd, HSCTRL_STATE_MACHINE, HSCTRL_ON, Len, Buf, 0);
else
MlmeEnqueue(pAd, HSCTRL_STATE_MACHINE, HSCTRL_OFF, Len, Buf, 0);
os_free_mem(NULL, Buf);
return TRUE;
}
enum HSCTRL_STATE HSCtrlCurrentState(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
PHOTSPOT_CTRL pHSCtrl;
#ifdef CONFIG_AP_SUPPORT
PHSCTRL_EVENT_DATA Event = (PHSCTRL_EVENT_DATA)Elem->Msg;
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
pHSCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].HotSpotCtrl;
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
pHSCtrl = &pAd->StaCfg.HotSpotCtrl;
#endif /* CONFIG_STA_SUPPORT */
return pHSCtrl->HSCtrlState;
}
VOID HSCtrlSetCurrentState(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem,
IN enum HSCTRL_STATE State)
{
PHOTSPOT_CTRL pHSCtrl;
#ifdef CONFIG_AP_SUPPORT
PHSCTRL_EVENT_DATA Event = (PHSCTRL_EVENT_DATA)Elem->Msg;
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
pHSCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].HotSpotCtrl;
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
pHSCtrl = &pAd->StaCfg.HotSpotCtrl;
#endif /* CONFIG_STA_SUPPORT */
pHSCtrl->HSCtrlState = State;
}
static VOID HSCtrlOn(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
PHOTSPOT_CTRL pHSCtrl;
PGAS_CTRL pGASCtrl;
PNET_DEV NetDev;
HSCTRL_EVENT_DATA *Event = (HSCTRL_EVENT_DATA *)Elem->Msg;
printk("%s\n", __FUNCTION__);
#ifdef CONFIG_STA_SUPPORT
NetDev = pAd->net_dev;
pHSCtrl = &pAd->StaCfg.HotSpotCtrl;
pGASCtrl = &pAd->StaCfg.GASCtrl;
#endif /* CONFIG_STA_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
NetDev = pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.if_dev;
pHSCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].HotSpotCtrl;
pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl;
#endif /* CONFIG_AP_SUPPORT */
RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock);
DlListInit(&pGASCtrl->GASPeerList);
RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock);
pHSCtrl->HotSpotEnable = 1;
pHSCtrl->HSDaemonReady = 1;
#ifdef CONFIG_AP_SUPPORT
APMakeAllBssBeacon(pAd);
APUpdateAllBeaconFrame(pAd);
#endif /* CONFIG_AP_SUPPORT */
HSCtrlSetCurrentState(pAd, Elem, HSCTRL_IDLE);
/* Send indication to daemon */
if (Event->EventTrigger) {
switch (Event->EventType) {
case HS_ON_OFF_BASE:
HotspotOnOffEvent(NetDev, 1);
break;
case HS_AP_RELOAD:
HotspotAPReload(NetDev);
break;
default:
DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow event type(%d)\n", __FUNCTION__, Event->EventType));
break;
}
}
}
static VOID HSCtrlInit(
IN PRTMP_ADAPTER pAd)
{
PHOTSPOT_CTRL pHSCtrl;
#ifdef CONFIG_AP_SUPPORT
UCHAR APIndex;
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
pHSCtrl = &pAd->StaCfg.HotSpotCtrl;
NdisZeroMemory(pHSCtrl, sizeof(*pHSCtrl));
pHSCtrl->HotSpotEnable = 0;
pHSCtrl->HSCtrlState = HSCTRL_IDLE;
#endif /* CONFIG_STA_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++)
{
pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl;
NdisZeroMemory(pHSCtrl, sizeof(*pHSCtrl));
pHSCtrl->HotSpotEnable = 0;
pHSCtrl->HSCtrlState = HSCTRL_IDLE;
}
#endif /* CONFIG_AP_SUPPORT */
}
VOID HSCtrlExit(
IN PRTMP_ADAPTER pAd)
{
PHOTSPOT_CTRL pHSCtrl;
#ifdef CONFIG_AP_SUPPORT
UCHAR APIndex;
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
pHSCtrl = &pAd->StaCfg.HotSpotCtrl;
/* Remove all IE */
HSCtrlRemoveAllIE(pHSCtrl);
#endif /* CONFIG_STA_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++)
{
pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl;
/* Remove all IE */
HSCtrlRemoveAllIE(pHSCtrl);
}
#endif /* CONFIG_AP_SUPPORT */
}
VOID HSCtrlHalt(
IN PRTMP_ADAPTER pAd)
{
PHOTSPOT_CTRL pHSCtrl;
#ifdef CONFIG_AP_SUPPORT
UCHAR APIndex;
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
pHSCtrl = &pAd->StaCfg.HotSpotCtrl;
pHSCtrl->HotSpotEnable = 0;
#endif /* CONFIG_STA_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++)
{
pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl;
pHSCtrl->HotSpotEnable = 0;
}
#endif /* CONFIG_AP_SUPPORT */
}
static VOID HSCtrlOff(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
PHOTSPOT_CTRL pHSCtrl;
PNET_DEV NetDev;
HSCTRL_EVENT_DATA *Event = (HSCTRL_EVENT_DATA *)Elem->Msg;
#ifdef CONFIG_DOT11V_WNM
PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl;
#endif
UCHAR tmp;
printk("%s\n", __FUNCTION__);
#ifdef CONFIG_AP_SUPPORT
NetDev = pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.if_dev;
pHSCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].HotSpotCtrl;
#ifdef CONFIG_HOTSPOT_R2
pHSCtrl->bASANEnable = 0;
pHSCtrl->QLoadTestEnable = 0;
#endif
#endif /* CONFIG_AP_SUPPORT */
pHSCtrl->HotSpotEnable = 0;
pHSCtrl->HSDaemonReady = 0;
pHSCtrl->DGAFDisable = 0;
pHSCtrl->L2Filter = 0;
pHSCtrl->ICMPv4Deny = 0;
#ifdef CONFIG_DOT11V_WNM
pWNMCtrl->ProxyARPEnable = 0;
#ifdef CONFIG_HOTSPOT_R2
pWNMCtrl->WNMNotifyEnable = 0;
pHSCtrl->QosMapEnable = 0;
for(tmp = 0;tmp<21;tmp++)
{
pHSCtrl->DscpException[tmp] = 0xff;
pHSCtrl->DscpException[tmp] |= (0xff << 8);
}
for(tmp = 0;tmp<8;tmp++)
{
pHSCtrl->DscpRange[tmp] = 0xff;
pHSCtrl->DscpRange[tmp] |= (0xff << 8);
}
#endif
#endif
#ifdef CONFIG_AP_SUPPORT
APMakeAllBssBeacon(pAd);
APUpdateAllBeaconFrame(pAd);
#endif /* CONFIG_AP_SUPPORT */
HSCtrlSetCurrentState(pAd, Elem, HSCTRL_IDLE);
if (Event->EventTrigger) {
switch (Event->EventType) {
case HS_ON_OFF_BASE:
HotspotOnOffEvent(NetDev, 0);
break;
case HS_AP_RELOAD:
HotspotAPReload(NetDev);
break;
default:
DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow event type(%d)\n", __FUNCTION__, Event->EventType));
break;
}
}
}
BOOLEAN HotSpotEnable(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem,
IN INT Type)
{
PHOTSPOT_CTRL pHSCtrl = NULL;
#ifdef CONFIG_AP_SUPPORT
UCHAR APIndex;
PGAS_EVENT_DATA Event;
GAS_FRAME *GASFrame;
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_AP_SUPPORT
if (Type == GAS_STATE_MESSAGES)
{
Event = (PGAS_EVENT_DATA)Elem->Msg;
pHSCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].HotSpotCtrl;
}
else if (Type == ACTION_STATE_MESSAGES)
{
GASFrame = (GAS_FRAME *)Elem->Msg;
for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++)
{
if (MAC_ADDR_EQUAL(GASFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid))
{
pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl;
break;
}
}
if (!pHSCtrl)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__));
return FALSE;
}
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
pHSCtrl = &pAd->StaCfg.HotSpotCtrl;
#endif /* CONFIG_STA_SUPPORT */
return pHSCtrl->HotSpotEnable;
}
VOID HSCtrlStateMachineInit(
IN PRTMP_ADAPTER pAd,
IN STATE_MACHINE *S,
OUT STATE_MACHINE_FUNC Trans[])
{
DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__));
HSCtrlInit(pAd);
StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_HSCTRL_STATE, MAX_HSCTRL_MSG, (STATE_MACHINE_FUNC)Drop, HSCTRL_IDLE, HSCTRL_MACHINE_BASE);
StateMachineSetAction(S, HSCTRL_IDLE, HSCTRL_ON, (STATE_MACHINE_FUNC)HSCtrlOn);
StateMachineSetAction(S, HSCTRL_IDLE, HSCTRL_OFF, (STATE_MACHINE_FUNC)HSCtrlOff);
}
BOOLEAN hotspot_rx_snoop(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, RX_BLK *pRxBlk)
{
BOOLEAN drop = FALSE;
BOOLEAN FoundProxyARPEntry;
MULTISSID_STRUCT *pMbss = pEntry->pMbss;
PUCHAR pData = NdisEqualMemory(SNAP_802_1H, pRxBlk->pData, 6) ? (pRxBlk->pData + 6) : pRxBlk->pData;
UCHAR Offset = 0;
/* Check if Proxy ARP Candidate for IPv4 */
if (IsIPv4ProxyARPCandidate(pAd, pData))
{
FoundProxyARPEntry = IPv4ProxyARP(pAd, pMbss, pData, FALSE);
if (FoundProxyARPEntry) {
DBGPRINT(RT_DEBUG_TRACE, ("Find proxy entry for IPv4\n"));
drop = TRUE;
goto done;
}
}
/* Check if Neighbor solicitation during duplicate address detection procedure */
if (IsIpv6DuplicateAddrDetect(pAd, pData, &Offset))
{
/* Proxy MAC address/IPv6 mapping */
//AddIPv6ProxyARPEntry(pAd, pMbss, pEntry->Addr, (pData + 50));
DBGPRINT(RT_DEBUG_OFF, ("AddIPv6ProxyARPEntry:offset=%d\n", Offset));
AddIPv6ProxyARPEntry(pAd, pMbss, pEntry->Addr, (pData + Offset));
DBGPRINT(RT_DEBUG_ERROR, ("Drop IPv6 DAD\n"));
drop = TRUE;
goto done;
}
/* Check if Router solicitation */
if (IsIPv6RouterSolicitation(pAd, pData))
{
/* Proxy MAC address/IPv6 mapping for link local address */
AddIPv6ProxyARPEntry(pAd, pMbss, pEntry->Addr, (pData + 10));
}
//JERRY: add to parse DHCPv6 solicit to check proxy arp entry
if (IsIPv6DHCPv6Solicitation(pAd, pData))
{
AddIPv6ProxyARPEntry(pAd, pMbss, pEntry->Addr, (pData + 10));
}
/* Check if Proxy ARP Candidate for IPv6 */
if (IsIPv6ProxyARPCandidate(pAd, pData))
{
FoundProxyARPEntry = IPv6ProxyARP(pAd, pMbss, pData, FALSE);
if (FoundProxyARPEntry) {
DBGPRINT(RT_DEBUG_TRACE, ("Find proxy entry for IPv6\n"));
drop = TRUE;
goto done;
} else {
/* Proxy MAC address/IPv6 mapping */
AddIPv6ProxyARPEntry(pAd, pMbss, pEntry->Addr, (pData + 10));
}
}
if (!pEntry->pMbss->HotSpotCtrl.DGAFDisable)
{
if (IsGratuitousARP(pAd, pData, pRxBlk->pHeader->Addr3, pMbss))
{
DBGPRINT(RT_DEBUG_TRACE, ("Drop Gratutious ARP\n"));
drop = TRUE;
goto done;
}
if (IsUnsolicitedNeighborAdver(pAd, pData))
{
DBGPRINT(RT_DEBUG_TRACE, ("Drop unsoclicited neighbor advertisement packet\n"));
drop = TRUE;
goto done;
}
}
done:
return drop;
}
BOOLEAN hotspot_rx_l2_filter(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, RX_BLK *pRxBlk)
{
MULTISSID_STRUCT *pMbss = pEntry->pMbss;
BOOLEAN drop = FALSE;
PUCHAR pData = NdisEqualMemory(SNAP_802_1H, pRxBlk->pData, 6) ? (pRxBlk->pData + 6) : pRxBlk->pData;
if (pEntry->pMbss->HotSpotCtrl.L2Filter == L2FilterBuiltIn)
{
BOOLEAN NeedDrop = FALSE;
NeedDrop = L2FilterInspection(pAd, &pMbss->HotSpotCtrl, pData);
if (NeedDrop)
{
DBGPRINT(RT_DEBUG_OFF, ("Drop Filter BuiltIn packet\n"));
drop = TRUE;
goto done;
}
}
else if (pMbss->HotSpotCtrl.L2Filter == L2FilterExternal)
{
UINT16 Index;
BOOLEAN NeedSendToExternal;
MULTISSID_STRUCT *pMbss = pEntry->pMbss;
PUCHAR pData = NdisEqualMemory(SNAP_802_1H, pRxBlk->pData, 6) ? (pRxBlk->pData + 6) : pRxBlk->pData;
NeedSendToExternal = L2FilterInspection(pAd, &pMbss->HotSpotCtrl, pData);
if (NeedSendToExternal)
{
/* Change to broadcast DS */
DBGPRINT(RT_DEBUG_OFF, ("Change to broadcast under L2FilterExternal\n"));
for (Index = 0; Index < MAC_ADDR_LEN; Index++)
DBGPRINT(RT_DEBUG_OFF, ("DA[%d] = %x\n", Index, pRxBlk->pHeader->Addr3[Index]));
pRxBlk->pHeader->Addr3[0] = 0xf0;
pRxBlk->pHeader->Addr3[1] = 0xde;
pRxBlk->pHeader->Addr3[2] = 0xf1;
pRxBlk->pHeader->Addr3[3] = 0x70;
pRxBlk->pHeader->Addr3[4] = 0x86;
pRxBlk->pHeader->Addr3[5] = 0x52;
}
}
/* Check if TDLS/DLS frame */
if (IsTDLSPacket(pAd, pData))
{
DBGPRINT(RT_DEBUG_OFF, ("Drop TDLS Packet\n"));
drop = TRUE;
}
done:
return drop;
}
BOOLEAN hotspot_rx_handler(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, RX_BLK *pRxBlk)
{
BOOLEAN drop = FALSE;
if (pEntry->pMbss->WNMCtrl.ProxyARPEnable)
drop = hotspot_rx_snoop(pAd, pEntry, pRxBlk);
if ((drop == FALSE) && (pEntry->pMbss->HotSpotCtrl.L2Filter != L2FilterDisable))
drop = hotspot_rx_l2_filter(pAd, pEntry, pRxBlk);
if (drop == TRUE) {
RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
}
return drop;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2009, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
misc.c
Abstract:
Handling Misc Problem
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Sean Wang 2009-08-12 Create
John Li 2009-11-30 Modified
*/
#include "rt_config.h"
#include "misc.h"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,657 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 5F., No.36, Taiyuan St., Jhubei City,
* Hsinchu County 302,
* Taiwan, R.O.C.
*
* (c) Copyright 2002-2009, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
mwds.c
Abstract:
This is MWDS feature used to process those 4-addr of connected APClient or STA.
Revision History:
Who When What
--------- ---------- ----------------------------------------------
*/
#ifdef MWDS
#include "rt_config.h"
VOID MWDSConnEntryListInit(
IN PRTMP_ADAPTER pAd)
{
if(pAd->ApCfg.bMWDSAPInit)
return;
NdisAllocateSpinLock(pAd, &pAd->ApCfg.MWDSConnEntryLock);
DlListInit(&pAd->ApCfg.MWDSConnEntryList);
}
VOID MWDSConnEntryListClear(
IN PRTMP_ADAPTER pAd)
{
PMWDS_CONNECT_ENTRY pConnEntry = NULL,pConnEntryTmp = NULL;
PDL_LIST pMWDSConnEntryList = &pAd->ApCfg.MWDSConnEntryList;
if(!pAd->ApCfg.bMWDSAPInit)
return;
DlListForEachSafe(pConnEntry, pConnEntryTmp, pMWDSConnEntryList, MWDS_CONNECT_ENTRY, List)
{
if(pConnEntry)
{
DlListDel(&pConnEntry->List);
os_free_mem(NULL, pConnEntry);
}
}
NdisFreeSpinLock(&pAd->ApCfg.MWDSConnEntryLock);
}
BOOLEAN MWDSConnEntryLookupByWCID(
IN PRTMP_ADAPTER pAd,
IN UCHAR wcid)
{
ULONG idx;
PDL_LIST pMWDSConnEntryList = &pAd->ApCfg.MWDSConnEntryList;
PMWDS_CONNECT_ENTRY pConnEntry = NULL;
BOOLEAN bFound = FALSE;
if(MWDSGetConnEntryCount(pAd) == 0)
return FALSE;
DlListForEach(pConnEntry, pMWDSConnEntryList, MWDS_CONNECT_ENTRY, List)
{
if(pConnEntry &&
pConnEntry->Valid &&
(pConnEntry->wcid == wcid))
{
bFound = TRUE;
break;
}
}
return bFound;
}
BOOLEAN MWDSConnEntryLookupByAddr(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pMac)
{
ULONG idx;
PDL_LIST pMWDSConnEntryList = &pAd->ApCfg.MWDSConnEntryList;
PMWDS_CONNECT_ENTRY pConnEntry = NULL;
PMAC_TABLE_ENTRY pEntry = NULL;
BOOLEAN bFound = FALSE;
if(MWDSGetConnEntryCount(pAd) == 0 || pMac == NULL)
return FALSE;
DlListForEach(pConnEntry, pMWDSConnEntryList, MWDS_CONNECT_ENTRY, List)
{
if(pConnEntry && pConnEntry->Valid && VALID_WCID(pConnEntry->wcid))
{
pEntry = &pAd->MacTab.Content[pConnEntry->wcid];
if(MAC_ADDR_EQUAL(pMac,pEntry->Addr))
{
bFound = TRUE;
break;
}
}
}
return bFound;
}
VOID MWDSConnEntryUpdate(
IN PRTMP_ADAPTER pAd,
IN UCHAR wcid)
{
PMWDS_CONNECT_ENTRY pNewConnEntry = NULL;
if(MWDSConnEntryLookupByWCID(pAd, wcid))
return;
os_alloc_mem(pAd, (UCHAR **)&pNewConnEntry, sizeof(MWDS_CONNECT_ENTRY));
if(pNewConnEntry)
{
NdisZeroMemory(pNewConnEntry, sizeof(MWDS_CONNECT_ENTRY));
pNewConnEntry->Valid = 1;
pNewConnEntry->wcid = wcid;
RTMP_SEM_LOCK(&pAd->ApCfg.MWDSConnEntryLock);
DlListAddTail(&pAd->ApCfg.MWDSConnEntryList,&pNewConnEntry->List);
RTMP_SEM_UNLOCK(&pAd->ApCfg.MWDSConnEntryLock);
}
else
DBGPRINT(RT_DEBUG_ERROR, ("%s: Fail to alloc memory for pNewConnEntry", __FUNCTION__));
}
VOID MWDSConnEntryDelete(
IN PRTMP_ADAPTER pAd,
IN UCHAR wcid)
{
PMWDS_CONNECT_ENTRY pConnEntry = NULL;
PDL_LIST pMWDSConnEntryList = &pAd->ApCfg.MWDSConnEntryList;
if(MWDSGetConnEntryCount(pAd) == 0)
return;
RTMP_SEM_LOCK(&pAd->ApCfg.MWDSConnEntryLock);
DlListForEach(pConnEntry, pMWDSConnEntryList, MWDS_CONNECT_ENTRY, List)
{
if(pConnEntry &&
pConnEntry->Valid &&
(pConnEntry->wcid == wcid))
{
DlListDel(&pConnEntry->List);
os_free_mem(NULL, pConnEntry);
RoutingTabSetAllFree(pAd, wcid, ROUTING_ENTRY_MWDS);
break;
}
}
RTMP_SEM_UNLOCK(&pAd->ApCfg.MWDSConnEntryLock);
}
INT MWDSGetConnEntryCount(
IN PRTMP_ADAPTER pAd )
{
int count = 0;
if(!pAd->ApCfg.bMWDSAPInit)
return 0;
count = DlListLen(&pAd->ApCfg.MWDSConnEntryList);
return count;
}
BOOLEAN ISMWDSValid(
IN PRTMP_ADAPTER pAd)
{
if(!pAd->ApCfg.bMWDSAPInit || (MWDSGetConnEntryCount(pAd) == 0))
return FALSE;
return TRUE;
}
VOID MWDSProxyEntryDelete(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pMac)
{
if(!ISMWDSValid(pAd))
return;
RoutingTabSetOneFree(pAd, pMac, ROUTING_ENTRY_MWDS);
}
BOOLEAN MWDSProxyLookup(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pMac,
IN BOOLEAN bUpdateAliveTime,
OUT UCHAR *pWcid)
{
UCHAR Wcid;
if(!ISMWDSValid(pAd))
return FALSE;
if(RoutingTabLookup(pAd, pMac, bUpdateAliveTime, &Wcid) != NULL)
{
*pWcid = Wcid;
return TRUE;
}
else
return FALSE;
}
VOID MWDSProxyTabUpdate(
IN PRTMP_ADAPTER pAd,
IN UCHAR wcid,
IN PUCHAR pMac)
{
UCHAR ProxyAPWcid = 0;
BOOLEAN bFound = FALSE;
PROUTING_ENTRY pRoutingEntry = NULL;
if(!ISMWDSValid(pAd))
return;
if(!VALID_WCID(wcid) || !pMac)
return;
pRoutingEntry = RoutingTabLookup(pAd, pMac, TRUE, &ProxyAPWcid);
bFound = (pRoutingEntry != NULL)?TRUE:FALSE;
if(bFound)
{
if(ROUTING_ENTRY_TEST_FLAG(pRoutingEntry, ROUTING_ENTRY_MWDS))
{
/* Mean the target change to other ProxyAP */
if((ProxyAPWcid != wcid))
RoutingTabSetOneFree(pAd, pMac, ROUTING_ENTRY_MWDS);
else
return;
}
else
{
/* Assign MWDS falg to this one if found. */
SET_ROUTING_ENTRY(pRoutingEntry, ROUTING_ENTRY_MWDS);
}
}
if(!bFound)
{
/* Allocate a new one if not found. */
pRoutingEntry = RoutingTabGetFree(pAd);
if (pRoutingEntry)
{
SET_ROUTING_ENTRY(pRoutingEntry, ROUTING_ENTRY_MWDS);
RoutingEntrySet(pAd, wcid, pMac, pRoutingEntry);
}
}
}
VOID MWDSProxyTabMaintain(
IN PRTMP_ADAPTER pAd)
{
if(!ISMWDSValid(pAd))
return;
RoutingTabMaintain(pAd);
}
PNDIS_PACKET MWDSClonePacket(
IN PRTMP_ADAPTER pAd,
IN PNDIS_PACKET pPacket)
{
PNDIS_PACKET pPacketClone = NULL;
OS_PKT_CLONE(pAd, pPacket, pPacketClone, GFP_ATOMIC);
if (pPacketClone == NULL)
return NULL;
return pPacketClone;
}
void MWDSSendClonePacket(
IN PRTMP_ADAPTER pAd,
IN PNDIS_PACKET pPacket,
IN PUCHAR pExcludeMac)
{
PNDIS_PACKET pPacketClone = NULL;
PDL_LIST pMWDSConnEntryList = &pAd->ApCfg.MWDSConnEntryList;
PMWDS_CONNECT_ENTRY pConnEntry = NULL;
PROUTING_ENTRY pRoutingEntry = NULL;
PMAC_TABLE_ENTRY pEntry = NULL;
BOOLEAN bFound = FALSE;
UCHAR Wcid = 0;
if(pPacket && (MWDSGetConnEntryCount(pAd) > 0))
{
if(pExcludeMac)
{
pRoutingEntry = RoutingTabLookup(pAd,pExcludeMac,FALSE,&Wcid);
if(pRoutingEntry && ROUTING_ENTRY_TEST_FLAG(pRoutingEntry, ROUTING_ENTRY_MWDS))
bFound = TRUE;
else
bFound = FALSE;
}
DlListForEach(pConnEntry, pMWDSConnEntryList, MWDS_CONNECT_ENTRY, List)
{
if (pConnEntry && pConnEntry->Valid && VALID_WCID(pConnEntry->wcid))
{
if(bFound && (Wcid == pConnEntry->wcid))
continue;
OS_PKT_CLONE(pAd, pPacket, pPacketClone, GFP_ATOMIC);
if (pPacketClone == NULL)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pPacketClone", __FUNCTION__));
return;
}
pEntry = &pAd->MacTab.Content[pConnEntry->wcid];
RTMP_SET_PACKET_WCID(pPacketClone, pEntry->wcid);
RTMP_SET_PACKET_WDEV(pPacketClone, pEntry->wdev->wdev_idx);
pAd->RalinkCounters.PendingNdisPacketCount++;
APSendPacket(pAd, pPacketClone);
}
}
}
}
BOOLEAN MWDSARPLookupUpdate(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pData)
{
if(!ISMWDSValid(pAd))
return FALSE;
RoutingTabARPLookupUpdate(pAd, pData);
return TRUE;
}
INT MWDSEnable(
IN PRTMP_ADAPTER pAd,
IN UCHAR ifIndex,
IN BOOLEAN isAP)
{
if(isAP)
{
if(ifIndex < HW_BEACON_MAX_NUM)
pAd->ApCfg.MBSSID[ifIndex].bSupportMWDS = TRUE;
MWDSAPUP(pAd);
}
#ifdef APCLI_SUPPORT
else
{
if(ifIndex < MAX_APCLI_NUM)
pAd->ApCfg.ApCliTab[ifIndex].bSupportMWDS = TRUE;
}
#endif /* APCLI_SUPPORT */
return TRUE;
}
INT MWDSDisable(
IN PRTMP_ADAPTER pAd,
IN UCHAR ifIndex,
IN BOOLEAN isAP)
{
if(isAP)
{
if(ifIndex < HW_BEACON_MAX_NUM)
pAd->ApCfg.MBSSID[ifIndex].bSupportMWDS = FALSE;
MWDSAPDown(pAd);
}
#ifdef APCLI_SUPPORT
else
{
if(ifIndex < MAX_APCLI_NUM)
pAd->ApCfg.ApCliTab[ifIndex].bSupportMWDS = FALSE;
}
#endif /* APCLI_SUPPORT */
return TRUE;
}
INT MWDSAPUP(
IN PRTMP_ADAPTER pAd)
{
MWDSConnEntryListInit(pAd);
RoutingTabInit(pAd, ROUTING_ENTRY_MWDS);
pAd->ApCfg.bMWDSAPInit = TRUE;
return TRUE;
}
INT MWDSAPDown(
IN PRTMP_ADAPTER pAd)
{
MWDSConnEntryListClear(pAd);
RoutingTabDestory(pAd, ROUTING_ENTRY_MWDS);
pAd->ApCfg.bMWDSAPInit = FALSE;
return TRUE;
}
INT Set_Enable_MWDS_Proc(
IN PRTMP_ADAPTER pAd,
IN BOOLEAN Enable,
IN BOOLEAN isAP)
{
POS_COOKIE pObj;
UCHAR ifIndex;
pObj = (POS_COOKIE) pAd->OS_Cookie;
if(isAP)
{
ifIndex = pObj->ioctl_if;
}
#ifdef APCLI_SUPPORT
else
{
if (pObj->ioctl_if_type != INT_APCLI)
return FALSE;
ifIndex = pObj->ioctl_if;
}
#endif /* APCLI_SUPPORT */
if (Enable)
MWDSEnable(pAd,ifIndex,isAP);
else
MWDSDisable(pAd,ifIndex,isAP);
return TRUE;
}
INT Set_Ap_MWDS_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
UCHAR Enable;
Enable = simple_strtol(arg, 0, 10);
return Set_Enable_MWDS_Proc(pAd,Enable,TRUE);
}
INT Set_ApCli_MWDS_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
UCHAR Enable;
Enable = simple_strtol(arg, 0, 10);
return Set_Enable_MWDS_Proc(pAd,Enable,FALSE);
}
INT Set_Ap_MWDS_Show_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
POS_COOKIE pObj;
UCHAR ifIndex;
BOOLEAN bEnable;
pObj = (POS_COOKIE) pAd->OS_Cookie;
ifIndex = pObj->ioctl_if;
#ifdef SMART_MESH
PSMART_MESH_CFG pSmartMeshCfg = NULL;
PNTGR_IE pNtgr_IE = NULL;
#endif /* SMART_MESH */
if(ifIndex < HW_BEACON_MAX_NUM)
{
#ifdef SMART_MESH
pSmartMeshCfg = &pAd->ApCfg.MBSSID[ifIndex].SmartMeshCfg;
#endif /* SMART_MESH */
}
else
return FALSE;
#ifdef SMART_MESH
if(pSmartMeshCfg)
{
pNtgr_IE = &pSmartMeshCfg->Ntgr_IE;
if((pNtgr_IE->private[0]&0x1))
bEnable = TRUE;
else
bEnable = FALSE;
}
else
#endif /* SMART_MESH */
{
bEnable = FALSE;
}
DBGPRINT(RT_DEBUG_OFF,("%d\n", bEnable));
return TRUE;
}
INT Set_ApCli_MWDS_Show_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
POS_COOKIE pObj;
UCHAR ifIndex;
BOOLEAN bEnable, bSupportMWDS;
pObj = (POS_COOKIE) pAd->OS_Cookie;
ifIndex = pObj->ioctl_if;
#ifdef SMART_MESH
PSMART_MESH_CFG pSmartMeshCfg = NULL;
PNTGR_IE pNtgr_IE = NULL;
#endif /* SMART_MESH */
if((pObj->ioctl_if_type == INT_APCLI) && (ifIndex < MAX_APCLI_NUM))
{
#ifdef SMART_MESH
pSmartMeshCfg = &pAd->ApCfg.ApCliTab[ifIndex].SmartMeshCfg;
#endif /* SMART_MESH */
bSupportMWDS = pAd->ApCfg.ApCliTab[ifIndex].bSupportMWDS;
}
else
return FALSE;
#ifdef SMART_MESH
if(pSmartMeshCfg)
{
pNtgr_IE = &pSmartMeshCfg->Ntgr_IE;
if(bSupportMWDS && (pNtgr_IE->private[0]&0x1))
bEnable = TRUE;
else
bEnable = FALSE;
}
else
#endif /* SMART_MESH */
{
bEnable = bSupportMWDS;
}
DBGPRINT(RT_DEBUG_OFF,("%d\n", bEnable));
return TRUE;
}
INT Set_APProxy_Status_Show_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
INT32 i,count=0;
UINT32 ip_addr=0;
ULONG Now=0, AliveTime=0;
PDL_LIST pMWDSConnEntryList = &pAd->ApCfg.MWDSConnEntryList;
PMWDS_CONNECT_ENTRY pConnEntry = NULL;
PROUTING_ENTRY pRoutingEntry = NULL, *RoutingEntryList[ROUTING_POOL_SIZE];
UCHAR *pProxyMac = NULL, ProxyMacIP[64];
if((MWDSGetConnEntryCount(pAd) == 0))
return TRUE;
NdisGetSystemUpTime(&Now);
DlListForEach(pConnEntry, pMWDSConnEntryList, MWDS_CONNECT_ENTRY, List)
{
if (pConnEntry && pConnEntry->Valid && VALID_WCID(pConnEntry->wcid))
{
count = 0;
pProxyMac = pAd->MacTab.Content[pConnEntry->wcid].Addr;
DBGPRINT(RT_DEBUG_OFF,("Proxy Mac: %02X:%02X:%02X:%02X:%02X:%02X\n", PRINT_MAC(pProxyMac)));
if(GetRoutingEntryAll(pAd, pConnEntry->wcid, ROUTING_ENTRY_MWDS,
ROUTING_POOL_SIZE, &RoutingEntryList, &count))
{
for (i = 0; i < count; i++)
{
pRoutingEntry = RoutingEntryList[i];
if(!pRoutingEntry)
continue;
if(pRoutingEntry->KeepAliveTime >= Now)
AliveTime = ((pRoutingEntry->KeepAliveTime - Now) / OS_HZ);
else
AliveTime = 0;
if(pRoutingEntry->IPAddr != 0)
{
ip_addr = pRoutingEntry->IPAddr;
sprintf(ProxyMacIP, "%d.%d.%d.%d", (ip_addr & 0xff), ((ip_addr & (0xff << 8)) >> 8),
((ip_addr & (0xff << 16)) >> 16), ((ip_addr & (0xff << 24)) >> 24));
}
else
strcpy(ProxyMacIP,"0.0.0.0");
DBGPRINT(RT_DEBUG_OFF,("\tMAC: %02X:%02X:%02X:%02X:%02X:%02X\tIP: %s\tAgeOut: %lus\tRetry: (%d,%d)\n",
PRINT_MAC(pRoutingEntry->Mac), ProxyMacIP, AliveTime,
pRoutingEntry->RetryKeepAlive,ROUTING_ENTRY_MAX_RETRY));
}
DBGPRINT(RT_DEBUG_OFF,("Total Count = %d\n\n",count));
}
}
}
return TRUE;
}
VOID rtmp_read_MWDS_from_file(
IN PRTMP_ADAPTER pAd,
PSTRING tmpbuf,
PSTRING buffer)
{
PSTRING tmpptr = NULL;
#ifdef CONFIG_AP_SUPPORT
/* ApMWDS */
if(RTMPGetKeyParameter("ApMWDS", tmpbuf, 256, buffer, TRUE))
{
INT Value;
UCHAR i=0;
Value = (INT) simple_strtol(tmpbuf, 0, 10);
for (i = 0, tmpptr = rstrtok(tmpbuf,";"); tmpptr; tmpptr = rstrtok(NULL,";"), i++)
{
if (i >= pAd->ApCfg.BssidNum)
break;
if (Value == 0)
{
MWDSDisable(pAd,i,TRUE);
}
else
{
MWDSEnable(pAd,i,TRUE);
}
DBGPRINT(RT_DEBUG_TRACE, ("ApMWDS=%d\n", Value));
}
}
#endif /* CONFIG_AP_SUPPORT */
#ifdef APCLI_SUPPORT
/* ApCliMWDS */
if(RTMPGetKeyParameter("ApCliMWDS", tmpbuf, 256, buffer, TRUE))
{
INT Value;
UCHAR i=0;
Value = (INT) simple_strtol(tmpbuf, 0, 10);
for (i = 0, tmpptr = rstrtok(tmpbuf,";"); tmpptr; tmpptr = rstrtok(NULL,";"), i++)
{
if (i >= MAX_APCLI_NUM)
break;
if (Value == 0)
{
MWDSDisable(pAd,i,FALSE);
}
else
{
MWDSEnable(pAd,i,FALSE);
}
DBGPRINT(RT_DEBUG_TRACE, ("ApCliMWDS=%d\n", Value));
}
}
#endif /* APCLI_SUPPORT */
}
#endif /* MWDS */

View File

@ -0,0 +1,133 @@
#ifdef BLOCK_NET_IF
#include "rt_config.h"
#include "netif_block.h"
static NETIF_ENTRY freeNetIfEntryPool[FREE_NETIF_POOL_SIZE];
static LIST_HEADER freeNetIfEntryList;
void initblockQueueTab(
IN PRTMP_ADAPTER pAd)
{
int i;
initList(&freeNetIfEntryList);
for (i = 0; i < FREE_NETIF_POOL_SIZE; i++)
insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)&freeNetIfEntryPool[i]);
for (i=0; i < NUM_OF_TX_RING; i++)
initList(&pAd->blockQueueTab[i].NetIfList);
return;
}
BOOLEAN blockNetIf(
IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry,
IN PNET_DEV pNetDev)
{
PNETIF_ENTRY pNetIfEntry = NULL;
if ((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(&freeNetIfEntryList)) != NULL)
{
RTMP_OS_NETDEV_STOP_QUEUE(pNetDev);
pNetIfEntry->pNetDev = pNetDev;
insertTailList(&pBlockQueueEntry->NetIfList, (PLIST_ENTRY)pNetIfEntry);
pBlockQueueEntry->SwTxQueueBlockFlag = TRUE;
DBGPRINT(RT_DEBUG_TRACE, ("RTMP_OS_NETDEV_STOP_QUEUE(%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(pNetDev)));
}
else
return FALSE;
return TRUE;
}
VOID releaseNetIf(
IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry)
{
PNETIF_ENTRY pNetIfEntry = NULL;
PLIST_HEADER pNetIfList = &pBlockQueueEntry->NetIfList;
while((pNetIfEntry = (PNETIF_ENTRY)removeHeadList(pNetIfList)) != NULL)
{
PNET_DEV pNetDev = pNetIfEntry->pNetDev;
RTMP_OS_NETDEV_WAKE_QUEUE(pNetDev);
insertTailList(&freeNetIfEntryList, (PLIST_ENTRY)pNetIfEntry);
DBGPRINT(RT_DEBUG_TRACE, ("RTMP_OS_NETDEV_WAKE_QUEUE(%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(pNetDev)));
}
pBlockQueueEntry->SwTxQueueBlockFlag = FALSE;
return;
}
VOID StopNetIfQueue(
IN PRTMP_ADAPTER pAd,
IN UCHAR QueIdx,
IN PNDIS_PACKET pPacket)
{
PNET_DEV NetDev = NULL, wdev_NetDev= NULL;
UCHAR IfIdx = 0;
BOOLEAN valid = FALSE;
IfIdx = RTMP_GET_PACKET_WDEV(pPacket);
if ((IfIdx < WDEV_NUM_MAX) && (pAd->wdev_list[IfIdx] != NULL)) {
wdev_NetDev = pAd->wdev_list[IfIdx]->if_dev;
}
#ifdef APCLI_SUPPORT
if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_APCLI)
{
IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_APCLI) % MAX_APCLI_NUM;
NetDev = pAd->ApCfg.ApCliTab[IfIdx].wdev.if_dev;
}
else
#endif /* APCLI_SUPPORT */
#ifdef WDS_SUPPORT
if (RTMP_GET_PACKET_NET_DEVICE(pPacket) >= MIN_NET_DEVICE_FOR_WDS)
{
IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_WDS) % MAX_WDS_ENTRY;
NetDev = pAd->WdsTab.WdsEntry[IfIdx].wdev.if_dev;
}
else
#endif /* WDS_SUPPORT */
{
#ifdef MBSS_SUPPORT
if (pAd->OpMode == OPMODE_AP)
{
IfIdx = (RTMP_GET_PACKET_NET_DEVICE(pPacket) - MIN_NET_DEVICE_FOR_MBSSID) % MAX_MBSSID_NUM(pAd);
NetDev = pAd->ApCfg.MBSSID[IfIdx].wdev.if_dev;
}
else
{
IfIdx = MAIN_MBSSID;
NetDev = pAd->net_dev;
}
#else
IfIdx = MAIN_MBSSID;
NetDev = pAd->net_dev;
#endif
}
/* WMM support 4 software queues.*/
/* One software queue full doesn't mean device have no capbility to transmit packet.*/
/* So disable block Net-If queue function while WMM enable.*/
#ifdef CONFIG_AP_SUPPORT
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
valid = (pAd->ApCfg.MBSSID[IfIdx].wdev.bWmmCapable == TRUE) ? FALSE : TRUE;
#endif /* CONFIG_AP_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
{
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
valid = (pAd->CommonCfg.bWmmCapable == TRUE) ? FALSE : TRUE;
}
#endif /* CONFIG_STA_SUPPORT */
if (valid)
blockNetIf(&pAd->blockQueueTab[QueIdx], NetDev);
return;
}
#endif /* BLOCK_NET_IF */

View File

@ -0,0 +1,944 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2006, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
wsc_v2.c
*/
#include "rt_config.h"
#ifdef WSC_NFC_SUPPORT
extern UINT8 WPS_DH_G_VALUE[1];
extern UINT8 WPS_DH_P_VALUE[192];
typedef struct _NFC_CMD_INFO {
USHORT vendor_id;
UCHAR action;
UCHAR type;
USHORT data_len;
UCHAR data[0];
} NFC_CMD_INFO;
/*
Packet Type: PACKET_OTHERHOST
Packet Protocol: 0x6605
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Vendor Id | Action | Type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length | Data¡K¡K
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
Vendor: 0x14C3
Action: b¡¦<7:6>: 0x0 ¡V To NFC, 0x1 ¡V From NFC
b¡¦<5:0>: 0x00 ¡V Get, 0x01 - Set
Type:
0 ¡V Command Result (1 byte)
1 - Configuration (WSC TLV)
2 ¡V Password (32 bytes)
3 ¡V IP address (4 bytes)
4 ¡V RTSP port (4 bytes)
5 ¡V NFC Status (1 byte)
b'0: 1 - ON, 0 - OFF
b'1: 1 - nfc device detect
6 ¡V Wireless Radio Status (1byte)
*/
#define ETH_MTK_NFC 0x6605
#define NFC_VENDOR_ID 0x14C3
VOID NfcCommand(
IN PRTMP_ADAPTER pAd,
IN UCHAR Action,
IN UCHAR Type,
IN SHORT DataLen,
IN PUCHAR pData)
{
PNET_DEV pNetDev = pAd->net_dev;
UCHAR *pBuffer = NULL;
USHORT len;
USHORT vendor_id = NFC_VENDOR_ID, type = ETH_MTK_NFC, net_type;
UCHAR Header802_3[LENGTH_802_3];
UCHAR SrcMacAddr[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x66, 0x05};
struct wifi_dev *wdev;
MULTISSID_STRUCT *pMbss;
len = sizeof(vendor_id) + sizeof(Action) + sizeof(Type) + sizeof(USHORT) + LENGTH_802_3;
if (DataLen > 0)
len += DataLen;
os_alloc_mem(pAd, (UCHAR **)&pBuffer, (len*sizeof(UCHAR)));
if (pBuffer == NULL)
return;
pMbss = &pAd->ApCfg.MBSSID[0];
wdev = &pMbss->wdev;
NdisZeroMemory(pBuffer, len);
NdisZeroMemory(&Header802_3[0], LENGTH_802_3);
NdisMoveMemory(&Header802_3[0], wdev->bssid, MAC_ADDR_LEN);
NdisMoveMemory((&Header802_3[0] + MAC_ADDR_LEN), &SrcMacAddr[0], MAC_ADDR_LEN);
net_type = htons(type);
NdisMoveMemory((&Header802_3[0] + MAC_ADDR_LEN * 2), &net_type, LENGTH_802_3_TYPE);
//hex_dump("Header802_3", &Header802_3[0], LENGTH_802_3);
NdisMoveMemory(pBuffer, &Header802_3[0], LENGTH_802_3);
NdisMoveMemory(pBuffer+LENGTH_802_3, &vendor_id, sizeof(vendor_id));
NdisMoveMemory(pBuffer+LENGTH_802_3+sizeof(vendor_id), &Action, sizeof(Action));
NdisMoveMemory(pBuffer+LENGTH_802_3+sizeof(vendor_id)+sizeof(Action), &Type, sizeof(Type));
NdisMoveMemory(pBuffer+LENGTH_802_3+sizeof(vendor_id)+sizeof(Action)+sizeof(Type), &DataLen, sizeof(USHORT));
if ((DataLen > 0) && (pData != NULL))
NdisMoveMemory(pBuffer+LENGTH_802_3+sizeof(vendor_id)+sizeof(Action)+sizeof(Type)+sizeof(USHORT), pData, DataLen);
hex_dump("NfcCommand", pBuffer, len);
RtmpOSNotifyRawData(pNetDev, pBuffer, len, 0, ETH_MTK_NFC);
os_free_mem(NULL,pBuffer);
return;
}
VOID NfcGenRandomPasswd(
IN PRTMP_ADAPTER pAd,
IN PWSC_CTRL pWscCtrl)
{
UCHAR idx = 0;
NdisZeroMemory(&pWscCtrl->NfcPasswd[0], 32);
for (idx = 0; idx < NFC_DEV_PASSWD_LEN; idx++)
{
pWscCtrl->NfcPasswd[idx] = RandomByte(pAd);
}
pWscCtrl->NfcPasswdLen = NFC_DEV_PASSWD_LEN;
return;
}
#define NFC_WSC_TLV_SIZE 512
INT NfcBuildWscProfileTLV(
IN PRTMP_ADAPTER pAd,
IN PWSC_CTRL pWscCtrl,
OUT UCHAR *pbuf,
OUT USHORT *pBufLen)
{
INT Status = NDIS_STATUS_SUCCESS;
PWSC_CREDENTIAL pCredential = NULL;
UCHAR apidx = pWscCtrl->EntryIfIdx;
UCHAR *TB = NULL;
UCHAR *pData = NULL, *pSrcData = NULL;
INT CerLen = 0;
USHORT AuthType = 0;
USHORT EncrType = 0;
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscCtrl->RegData;
INT Len = 0, templen = 0;
struct wifi_dev *wdev;
MULTISSID_STRUCT *pMbss;
#ifdef WSC_V2_SUPPORT
PWSC_TLV pWscTLV = &pWscCtrl->WscV2Info.ExtraTlv;
#endif /* WSC_V2_SUPPORT */
os_alloc_mem(pAd, (UCHAR **)&pData, (NFC_WSC_TLV_SIZE*sizeof(UCHAR)));
if (pData == NULL)
{
return NDIS_STATUS_RESOURCES;
}
os_alloc_mem(pAd, (UCHAR **)&TB, (256*sizeof(UCHAR)));
if (TB == NULL)
{
os_free_mem(NULL, pData);
return NDIS_STATUS_RESOURCES;
}
pMbss = &pAd->ApCfg.MBSSID[apidx];
wdev = &pMbss->wdev;
pSrcData = pData;
NdisZeroMemory(pData, NFC_WSC_TLV_SIZE);
NdisZeroMemory(&TB[0], 256);
WscCreateProfileFromCfg(pAd, REGISTRAR_ACTION | AP_MODE, pWscCtrl, &pWscCtrl->WscProfile);
pCredential = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0];
// Credential
CerLen += AppendWSCTLV(WSC_ID_NW_INDEX, &TB[0], (PUCHAR)"1", 0);
AuthType = cpu2be16(pCredential->AuthType);
EncrType = cpu2be16(pCredential->EncrType);
CerLen += AppendWSCTLV(WSC_ID_SSID, &TB[CerLen], pCredential->SSID.Ssid, pCredential->SSID.SsidLength);
CerLen += AppendWSCTLV(WSC_ID_AUTH_TYPE, &TB[CerLen], (UINT8 *)&AuthType, 0);
CerLen += AppendWSCTLV(WSC_ID_ENCR_TYPE, &TB[CerLen], (UINT8 *)&EncrType, 0);
CerLen += AppendWSCTLV(WSC_ID_NW_KEY_INDEX, &TB[CerLen], &pCredential->KeyIndex, 0);
CerLen += AppendWSCTLV(WSC_ID_NW_KEY, &TB[CerLen], pCredential->Key, pCredential->KeyLength);
CerLen += AppendWSCTLV(WSC_ID_MAC_ADDR, &TB[CerLen], wdev->bssid, 0);
// Prepare plain text
// Reguired attribute item in M8 if Enrollee is STA.
templen = AppendWSCTLV(WSC_ID_CREDENTIAL, pData, TB, CerLen);
pData += templen;
Len += templen;
/* Optional items. RF_Band, AP_Channel, MAC_Address */
UCHAR RF_Band;
if (pAd->CommonCfg.Channel > 14)
RF_Band = 0x02; /* 5.0GHz */
else
RF_Band = 0x01; /* 2.4GHz */
templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, &RF_Band, 0);
pData += templen;
Len += templen;
USHORT Channel = 0;
Channel = pAd->CommonCfg.Channel;
#ifdef RT_BIG_ENDIAN
Channel = SWAP16(Channel);
#endif /* RT_BIG_ENDIAN */
templen = AppendWSCTLV(WSC_ID_AP_CHANNEL, pData, (UINT8 *)&Channel, 0);
pData += templen;
Len += templen;
templen = AppendWSCTLV(WSC_ID_MAC_ADDR, pData, wdev->bssid, 0);
pData += templen;
Len += templen;
#ifdef WSC_V2_SUPPORT
if (pWscCtrl->WscV2Info.bEnableWpsV2)
{
/* Version2 */
WscGenV2Msg(pWscCtrl,
FALSE,
NULL,
0,
&pData,
&Len);
/* Extra attribute that is not defined in WSC Sepc. */
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
{
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
pData += templen;
Len += templen;
}
}
#endif // WSC_V2_SUPPORT //
hex_dump("NfcBuildWscProfileTLV - pData", pSrcData, Len);
if (pbuf && (Len < NFC_WSC_TLV_SIZE))
{
NdisMoveMemory(pbuf, pSrcData, Len);
*pBufLen = (USHORT)Len;
hex_dump("NfcBuildWscProfileTLV", pbuf, *pBufLen);
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("%s: (Len=%d)\n", __FUNCTION__, Len));
Status = NDIS_STATUS_RESOURCES;
}
os_free_mem(NULL, pSrcData);
os_free_mem(NULL, TB);
return Status;
}
INT NfcBuildOOBDevPasswdTLV(
IN PRTMP_ADAPTER pAd,
IN PWSC_CTRL pWscCtrl,
IN UCHAR HandoverType,
OUT UCHAR *pbuf,
OUT USHORT *pBufLen)
{
INT Status = NDIS_STATUS_SUCCESS;
UCHAR *TB = NULL;
PUCHAR pData = NULL, pSrcData = NULL;
USHORT PasswdID = 0, len;
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscCtrl->RegData;
INT Len = 0, templen = 0;
INT DH_Len = 0, idx;
UCHAR HashData[SHA256_DIGEST_SIZE];
INT nfc_dev_passwd_len=0;
#ifdef WSC_V2_SUPPORT
PWSC_TLV pWscTLV = &pWscCtrl->WscV2Info.ExtraTlv;
#endif /* WSC_V2_SUPPORT */
os_alloc_mem(pAd, (UCHAR **)&pData, (NFC_WSC_TLV_SIZE*sizeof(UCHAR)));
if (pData == NULL)
{
return NDIS_STATUS_RESOURCES;
}
os_alloc_mem(pAd, (UCHAR **)&TB, (128*sizeof(UCHAR)));
if (pData == NULL)
{
os_free_mem(NULL, pData);
return NDIS_STATUS_RESOURCES;
}
DH_Len = sizeof(pWscCtrl->RegData.Pke);
/*
Enrollee 192 random bytes for DH key generation
*/
for (idx = 0; idx < 192; idx++)
pWscCtrl->RegData.EnrolleeRandom[idx] = RandomByte(pAd);
NdisZeroMemory(pWscCtrl->RegData.Pke, sizeof(pWscCtrl->RegData.Pke));
RT_DH_PublicKey_Generate (
WPS_DH_G_VALUE, sizeof(WPS_DH_G_VALUE),
WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE),
pWscCtrl->RegData.EnrolleeRandom, sizeof(pWscCtrl->RegData.EnrolleeRandom),
pWscCtrl->RegData.Pke, (UINT *) &DH_Len);
/* Need to prefix zero padding */
if((DH_Len != sizeof(pWscCtrl->RegData.Pke)) &&
(DH_Len < sizeof(pWscCtrl->RegData.Pke)))
{
UCHAR TempKey[192];
INT DiffCnt;
DiffCnt = sizeof(pWscCtrl->RegData.Pke) - DH_Len;
NdisFillMemory(&TempKey, DiffCnt, 0);
NdisCopyMemory(&TempKey[DiffCnt], pWscCtrl->RegData.Pke, DH_Len);
NdisCopyMemory(pWscCtrl->RegData.Pke, TempKey, sizeof(TempKey));
DH_Len += DiffCnt;
DBGPRINT(RT_DEBUG_TRACE, ("%s: Do zero padding!\n", __func__));
}
/* For Handover case, We may as Registrar
So keep the same public key for Registrar */
RTMPMoveMemory(pWscCtrl->RegData.Pkr, pWscCtrl->RegData.Pke, DH_Len);
hex_dump("Pkr", pWscCtrl->RegData.Pkr, DH_Len);
hex_dump("Pke", pWscCtrl->RegData.Pkr, DH_Len);
RT_SHA256(&pWscCtrl->RegData.Pke[0], 192, &HashData[0]);
RTMPMoveMemory(&pWscCtrl->NfcPasswdHash[0], &HashData[0], NFC_DEV_PASSWD_HASH_LEN);
hex_dump("NfcBuildOOBDevPasswdTLV - Public Key HashData", &HashData[0], 20);
if (HandoverType == TYPE_PASSWDHO_S || HandoverType == TYPE_PASSWDHO_R)
{
PasswdID = DEV_PASS_ID_NFC_HANDOVER;
pWscCtrl->NfcPasswdID = cpu2be16(PasswdID);
NdisZeroMemory(&pWscCtrl->NfcPasswd[0], 32);
pWscCtrl->NfcPasswdLen = NFC_DEV_PASSWD_LEN;
}
else
{
PasswdID = (RandomByte(pAd) << 8) + RandomByte(pAd);
if (PasswdID < 0x10)
PasswdID = 0x10;
pWscCtrl->NfcPasswdID = cpu2be16(PasswdID);
NfcGenRandomPasswd(pAd, pWscCtrl);
hex_dump("NfcBuildOOBDevPasswdTLV - NfcPasswd", &pWscCtrl->NfcPasswd[0], NFC_DEV_PASSWD_LEN);
}
pSrcData = pData;
NdisZeroMemory(pData, NFC_WSC_TLV_SIZE);
NdisZeroMemory(&TB[0], 128);
if (HandoverType == TYPE_PASSWDHO_R || HandoverType == TYPE_PASSWDHO_S)
{
/* Reserv for "Length of WSC attribute" */
pData += 2;
}
hex_dump("NfcBuildOOBDevPasswdTLV - 1 pSrcData", pSrcData, Len);
NdisMoveMemory(&TB[0], &HashData[0], NFC_DEV_PASSWD_HASH_LEN);
NdisMoveMemory(&TB[20], &pWscCtrl->NfcPasswdID, sizeof(pWscCtrl->NfcPasswdID));
if (HandoverType == TYPE_PASSWORD)
{
/* New SPEC Handover remove this part. */
NdisMoveMemory(&TB[22], &pWscCtrl->NfcPasswd[0], NFC_DEV_PASSWD_LEN);
nfc_dev_passwd_len = NFC_DEV_PASSWD_LEN;
}
templen = AppendWSCTLV(WSC_ID_OOB_DEV_PWD, pData, &TB[0], NFC_DEV_PASSWD_HASH_LEN+sizeof(PasswdID)+nfc_dev_passwd_len);
pData += templen;
Len += templen;
hex_dump("NfcBuildOOBDevPasswdTLV - 2 pSrcData", pSrcData, Len);
if (HandoverType == TYPE_PASSWDHO_S) /* Build for Handover Select Message */
{
templen = AppendWSCTLV(WSC_ID_SSID, pData, pAd->ApCfg.MBSSID[0].Ssid, pAd->ApCfg.MBSSID[0].SsidLen);
pData += templen;
Len += templen;
/* Optional items. RF_Band, AP_Channel and MAC_Address */
UCHAR RF_Band;
if (pAd->CommonCfg.Channel > 14)
RF_Band = 0x02; /* 5.0GHz */
else
RF_Band = 0x01; /* 2.4GHz */
templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, &RF_Band, 0);
pData += templen;
Len += templen;
USHORT Channel = 0;
Channel = pAd->CommonCfg.Channel;
#ifdef RT_BIG_ENDIAN
Channel = SWAP16(Channel);
#endif /* RT_BIG_ENDIAN */
templen = AppendWSCTLV(WSC_ID_AP_CHANNEL, pData, (UINT8 *)&Channel, 0);
pData += templen;
Len += templen;
templen = AppendWSCTLV(WSC_ID_MAC_ADDR, pData, pAd->CommonCfg.Bssid, 0);
pData += templen;
Len += templen;
}
else if (HandoverType == TYPE_PASSWDHO_R) /* Build for Handover Request Message */
{
templen = AppendWSCTLV(WSC_ID_UUID_E, pData, &pWscCtrl->Wsc_Uuid_E[0], 0);
pData += templen;
Len += templen;
}
#ifdef WSC_V2_SUPPORT
if (pWscCtrl->WscV2Info.bEnableWpsV2)
{
/* Version2 */
WscGenV2Msg(pWscCtrl,
FALSE,
NULL,
0,
&pData,
&Len);
/* Extra attribute that is not defined in WSC Sepc. */
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
{
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
pData += templen;
Len += templen;
}
}
#endif // WSC_V2_SUPPORT //
if (HandoverType == TYPE_PASSWDHO_R || HandoverType == TYPE_PASSWDHO_S)
{
/*Assign for "Length of WSC attribute" */
len = cpu2be16(Len);
memcpy(pSrcData, &len, 2);
hex_dump("NfcBuildOOBDevPasswdTLV - pSrcData", pSrcData, Len+2);
}
else
hex_dump("NfcBuildOOBDevPasswdTLV - pSrcData", pSrcData, Len);
if (pbuf && (Len < NFC_WSC_TLV_SIZE))
{
if (HandoverType == TYPE_PASSWDHO_R || HandoverType == TYPE_PASSWDHO_S)
{
NdisMoveMemory(pbuf, pSrcData, Len+2);
*pBufLen = (USHORT)Len+2;
}
else
{
NdisMoveMemory(pbuf, pSrcData, Len);
*pBufLen = (USHORT)Len;
}
hex_dump("NfcBuildOOBDevPasswdTLV", pbuf, *pBufLen);
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("%s: (Len=%d)\n", __FUNCTION__, Len));
Status = NDIS_STATUS_RESOURCES;
}
os_free_mem(NULL, pSrcData);
os_free_mem(NULL, TB);
return Status;
}
static BOOLEAN NfcProcessPasswdTV(
IN PRTMP_ADAPTER pAdapter,
IN PUCHAR pPlainData,
IN INT PlainLength,
IN PWSC_CTRL pWscCtrl,
IN UCHAR bHandOver)
{
USHORT WscType, WscLen;
PUCHAR pData;
INT DH_Len = 0, idx;
pData = pPlainData;
hex_dump("NfcProcessPasswdTV - PlainData", pPlainData, PlainLength);
// Start to process WSC IEs within credential
if (bHandOver)
{
pData +=2; /* Skip length of WSC attribute */
PlainLength -= 2;
}
while (PlainLength > 4)
{
WSC_IE TLV_Recv;
memcpy((UINT8 *)&TLV_Recv, pData, 4);
WscType = be2cpu16(TLV_Recv.Type);
WscLen = be2cpu16(TLV_Recv.Length);
pData += 4;
PlainLength -= 4;
// Parse M2 WSC type and store to RegData structure
switch (WscType)
{
case WSC_ID_OOB_DEV_PWD:
hex_dump("NfcProcessPasswdTV - WSC_ID_OOB_DEV_PWD", pData, WscLen);
NdisMoveMemory(&pWscCtrl->PeerNfcPasswdHash[0], pData, NFC_DEV_PASSWD_HASH_LEN);
NdisMoveMemory(&pWscCtrl->PeerNfcPasswdID, pData+20, sizeof(pWscCtrl->PeerNfcPasswdID));
pWscCtrl->PeerNfcPasswdLen = WscLen - 2 - NFC_DEV_PASSWD_HASH_LEN;
if (pWscCtrl->PeerNfcPasswdLen > NFC_DEV_PASSWD_LEN)
{
DBGPRINT(RT_DEBUG_TRACE, ("%s --> PeerNfcPasswdLen(%d) > NFC_DEV_PASSWD_LEN(%d)\n",
__FUNCTION__, pWscCtrl->PeerNfcPasswdLen, NFC_DEV_PASSWD_LEN));
pWscCtrl->PeerNfcPasswdLen = NFC_DEV_PASSWD_LEN;
}
if (bHandOver== TRUE)
{
if (pWscCtrl->PeerNfcPasswdID != DEV_PASS_ID_NFC_HANDOVER)
DBGPRINT(RT_DEBUG_TRACE, ("%s --> PeerNfcPasswdID(%04x) it should 0x0007 \n",
__FUNCTION__, pWscCtrl->PeerNfcPasswdID));
}
NdisMoveMemory(&pWscCtrl->PeerNfcPasswd[0], pData+20+sizeof(pWscCtrl->PeerNfcPasswdID), pWscCtrl->PeerNfcPasswdLen);
hex_dump("PeerNfcPasswd", pWscCtrl->PeerNfcPasswd, pWscCtrl->PeerNfcPasswdLen);
if (bHandOver==FALSE)
{
/* Due to M3 & M4 use the same WscGenPSK1 function,
need copy to NfcPasswd, too */
NdisMoveMemory(&pWscCtrl->NfcPasswd[0], &pWscCtrl->PeerNfcPasswd[0], pWscCtrl->PeerNfcPasswdLen);
pWscCtrl->NfcPasswdLen = pWscCtrl->PeerNfcPasswdLen;
}
break;
case WSC_ID_UUID_E:
NdisMoveMemory(pWscCtrl->RegData.PeerInfo.Uuid, pData, WscLen);
break;
case WSC_ID_SSID:
hex_dump("NfcProcessPasswdTV - WSC_ID_SSID", pData, WscLen);
break;
case WSC_ID_VENDOR_EXT:
hex_dump("NfcProcessPasswdTV - WSC_ID_VENDOR_EXT", pData, WscLen);
break;
default:
DBGPRINT(RT_DEBUG_TRACE, ("%s --> Unknown IE 0x%04x\n", __FUNCTION__, WscType));
break;
}
// Offset to net WSC Ie
pData += WscLen;
PlainLength -= WscLen;
}
DBGPRINT(RT_DEBUG_TRACE, ("%s --> bHandOver=%d", __FUNCTION__, bHandOver));
if (bHandOver== FALSE)
{
DH_Len = sizeof(pWscCtrl->RegData.Pkr);
// Enrollee 192 random bytes for DH key generation
for (idx = 0; idx < 192; idx++)
pWscCtrl->RegData.EnrolleeRandom[idx] = RandomByte(pAdapter);
NdisZeroMemory(pWscCtrl->RegData.Pkr, sizeof(pWscCtrl->RegData.Pkr));
RT_DH_PublicKey_Generate (
WPS_DH_G_VALUE, sizeof(WPS_DH_G_VALUE),
WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE),
pWscCtrl->RegData.EnrolleeRandom, sizeof(pWscCtrl->RegData.EnrolleeRandom),
pWscCtrl->RegData.Pkr, (UINT *) &DH_Len);
/* Need to prefix zero padding */
if((DH_Len != sizeof(pWscCtrl->RegData.Pkr)) &&
(DH_Len < sizeof(pWscCtrl->RegData.Pkr)))
{
UCHAR TempKey[192];
INT DiffCnt;
DiffCnt = sizeof(pWscCtrl->RegData.Pkr) - DH_Len;
NdisFillMemory(&TempKey, DiffCnt, 0);
NdisCopyMemory(&TempKey[DiffCnt], pWscCtrl->RegData.Pkr, DH_Len);
NdisCopyMemory(pWscCtrl->RegData.Pkr, TempKey, sizeof(TempKey));
DH_Len += DiffCnt;
DBGPRINT(RT_DEBUG_TRACE, ("%s: Do zero padding!\n", __func__));
}
hex_dump("Pkr", pWscCtrl->RegData.Pkr, 192);
}
return TRUE;
}
VOID NfcParseRspCommand(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pData,
IN USHORT DataLen)
{
NFC_CMD_INFO *pNfcCmdInfo = NULL;
BOOLEAN bSetFromNfc = FALSE;
PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[0].WscControl;
DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__));
hex_dump("Packet", pData, DataLen);
os_alloc_mem(pAd, (UCHAR **)&pNfcCmdInfo, (DataLen*sizeof(UCHAR)));
if (pNfcCmdInfo)
{
NdisMoveMemory(pNfcCmdInfo, pData, DataLen);
hex_dump("Packet", &pNfcCmdInfo->data[0], pNfcCmdInfo->data_len);
bSetFromNfc = ((pNfcCmdInfo->action & 0x41) == 0x41);
DBGPRINT(RT_DEBUG_TRACE, ("==> vendor_id: 0x%04x, action = 0x%0x, type = %d, data_len = %u, bSetFromNfc = %d\n",
pNfcCmdInfo->vendor_id, pNfcCmdInfo->action, pNfcCmdInfo->type, pNfcCmdInfo->data_len, bSetFromNfc));
switch(pNfcCmdInfo->type)
{
case TYPE_CMD_RESULT:
DBGPRINT(RT_DEBUG_TRACE, ("TYPE_CMD_RESULT(=%d): Command result = %d\n", pNfcCmdInfo->type, pNfcCmdInfo->data[0]));
break;
case TYPE_CONFIGURATION:
DBGPRINT(RT_DEBUG_TRACE, ("TYPE_CONFIGURATION(=%d)\n", pNfcCmdInfo->type));
if (bSetFromNfc)
{
if (pNfcCmdInfo->data_len != 1)
{
/*
Receive Configuration from NFC daemon.
*/
if (WscProcessCredential(pAd, &pNfcCmdInfo->data[0], pNfcCmdInfo->data_len, pWscCtrl) == FALSE)
{
DBGPRINT(RT_DEBUG_TRACE, ("ProcessCredential fail..\n"));
}
else
{
if ((pAd->OpMode == OPMODE_AP) && (pWscCtrl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED))
{
pWscCtrl->WscConfStatus = WSC_SCSTATE_CONFIGURED;
WscBuildBeaconIE(pAd, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, 0, NULL, 0, AP_MODE);
WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, 0, NULL, 0, AP_MODE);
APUpdateAllBeaconFrame(pAd);
}
if (pWscCtrl->WscUpdatePortCfgTimerRunning)
{
BOOLEAN bCancel;
RTMPCancelTimer(&pWscCtrl->WscUpdatePortCfgTimer, &bCancel);
}
else
pWscCtrl->WscUpdatePortCfgTimerRunning = TRUE;
RTMPSetTimer(&pWscCtrl->WscUpdatePortCfgTimer, 1000);
}
}
}
else
{
Set_NfcConfigurationToken_Proc(pAd, "1");
}
break;
case TYPE_PASSWORD:
DBGPRINT(RT_DEBUG_TRACE, ("TYPE_PASSWORD(=%d)\n", pNfcCmdInfo->type));
if (bSetFromNfc)
{
if (pNfcCmdInfo->data_len != 1)
{
/*
Receive Passwd from NFC daemon.
*/
NfcProcessPasswdTV(pAd, &pNfcCmdInfo->data[0], pNfcCmdInfo->data_len, pWscCtrl, FALSE);
WscGetConfWithoutTrigger(pAd, pWscCtrl, FALSE);
pWscCtrl->bTriggerByNFC = TRUE;
pWscCtrl->NfcModel = MODEL_PASSWORD_TOKEN;
}
}
else
{
Set_NfcPasswdToken_Proc(pAd, "1");
}
break;
/* New type for Handover */
case TYPE_PASSWDHO_S:
DBGPRINT(RT_DEBUG_TRACE, ("TYPE_PASSWDHO_S(=%d)\n", pNfcCmdInfo->type));
if (bSetFromNfc)
{
if (pNfcCmdInfo->data_len != 1)
{
/*
Receive Passwd from NFC daemon. "So far" no this case.
Due to AP always as Registrar in handover procedure,
AP only receive "Handover Request Message".
*/
NfcProcessPasswdTV(pAd, &pNfcCmdInfo->data[0], pNfcCmdInfo->data_len, pWscCtrl, TRUE);
WscGetConfWithoutTrigger(pAd, pWscCtrl, FALSE);
pWscCtrl->bTriggerByNFC = TRUE;
pWscCtrl->NfcModel = MODEL_HANDOVER; /* 2 */
}
}
else
{
Set_NfcPasswdToken_Proc(pAd, "2");
}
break;
case TYPE_PASSWDHO_R:
DBGPRINT(RT_DEBUG_TRACE, ("TYPE_PASSWDHO_R(=%d)\n", pNfcCmdInfo->type));
if (bSetFromNfc)
{
if (pNfcCmdInfo->data_len != 1)
{
/*
Receive Passwd from NFC daemon.
*/
NfcProcessPasswdTV(pAd, &pNfcCmdInfo->data[0], pNfcCmdInfo->data_len, pWscCtrl, TRUE);
WscGetConfWithoutTrigger(pAd, pWscCtrl, FALSE);
pWscCtrl->bTriggerByNFC = TRUE;
pWscCtrl->NfcModel = MODEL_HANDOVER; /* 2 */
}
}
else
{
/*
"So far" no this case.
Due to AP always as Registrar in handover procedure,
AP only send "Handover Select Message".
*/
Set_NfcPasswdToken_Proc(pAd, "3");
}
break;
case TYPE_NFC_STATUS:
DBGPRINT(RT_DEBUG_TRACE, ("TYPE_NFC_STATUS(=%d): NFC Status = %d\n", pNfcCmdInfo->type, pNfcCmdInfo->data[0]));
pWscCtrl->NfcStatus = pNfcCmdInfo->data[0];
break;
case TYPE_WIFI_RADIO_STATUS:
DBGPRINT(RT_DEBUG_TRACE, ("TYPE_WIFI_RADIO_STATUS(=%d)\n", pNfcCmdInfo->type));
if (bSetFromNfc)
{
if (pNfcCmdInfo->data[0] == 1)
MlmeRadioOn(pAd);
else
MlmeRadioOff(pAd);
}
else
{
UCHAR RadioStatus = 0;
if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF))
RadioStatus = 0;
else
RadioStatus = 1;
NfcCommand(pAd, 0x01, TYPE_WIFI_RADIO_STATUS, 1, &RadioStatus);
}
break;
default:
DBGPRINT(RT_DEBUG_TRACE, ("Unknow type(=%d)\n", pNfcCmdInfo->type));
break;
}
os_free_mem(NULL, pNfcCmdInfo);
}
DBGPRINT(RT_DEBUG_TRACE, ("<==== %s\n", __FUNCTION__));
return;
}
INT Set_NfcStatus_Proc(
IN RTMP_ADAPTER *pAd,
IN PSTRING arg)
{
UCHAR data = 0;
/*
Action: b¡¦<7:6>: 0x00 ¡V Request, 0x01 ¡V Notify
b¡¦<5:0>: 0x00 ¡V Get, 0x01 - Set
*/
UCHAR action = 1, type = TYPE_NFC_STATUS; /* 5 - NFC Status */
if (simple_strtol(arg, 0, 10) != 0)
data = 1;
data = (UCHAR)simple_strtol(arg, 0, 10);
DBGPRINT(RT_DEBUG_TRACE, ("%s: Set NFC Status(=%d)\n", __FUNCTION__, data));
NfcCommand(pAd, action, type, 1, &data);
return TRUE;
}
INT Set_NfcPasswdToken_Proc(
IN RTMP_ADAPTER *pAd,
IN PSTRING arg)
{
POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl;
PUCHAR pBuf = NULL;
USHORT BufLen = 0;
UCHAR action = 1, type = TYPE_PASSWORD;
UCHAR val=0;
BOOLEAN bHandover=FALSE;
/*
Action: b¡¦<7:6>: 0x00 ¡V Request, 0x01 ¡V Notify
b¡¦<5:0>: 0x00 ¡V Get, 0x01 - Set
*/
val = (UCHAR)simple_strtol(arg, 0, 10);
if (val == 1) /* Password Token */
{
bHandover = FALSE;
type = TYPE_PASSWORD;
}
else if (val == 2) /* Handover Select */
{
bHandover = TRUE;
type = TYPE_PASSWDHO_S;
}
else if (val == 3) /* Handover Request */
{
bHandover = TRUE;
type = TYPE_PASSWDHO_R;
}
os_alloc_mem(pAd, (UCHAR **)&pBuf, (NFC_WSC_TLV_SIZE*sizeof(UCHAR)));
if (pBuf == NULL)
{
return FALSE;
}
DBGPRINT(RT_DEBUG_TRACE, ("%s: NfcBuildOOBDevPasswdTLV value(=%d) type(=%d)\n", __FUNCTION__,val, type));
NfcBuildOOBDevPasswdTLV(pAd, pWscCtrl, type, pBuf, &BufLen);
if (pBuf && (BufLen != 0))
{
pWscCtrl->bTriggerByNFC = TRUE;
if (type ==TYPE_PASSWORD)
pWscCtrl->NfcModel = MODEL_PASSWORD_TOKEN;
else
pWscCtrl->NfcModel = MODEL_HANDOVER;
DBGPRINT(RT_DEBUG_TRACE, ("%s: NfcBuildOOBDevPasswdTLV NfcModel(=%d)\n", __FUNCTION__,pWscCtrl->NfcModel));
NfcCommand(pAd, action, type, BufLen, pBuf);
os_free_mem(NULL, pBuf);
}
return TRUE;
}
INT Set_NfcConfigurationToken_Proc(
IN RTMP_ADAPTER *pAd,
IN PSTRING arg)
{
POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl;
PUCHAR pBuf = NULL;
USHORT BufLen = 0;
/*
Action: b¡¦<7:6>: 0x00 ¡V Request, 0x01 ¡V Notify
b¡¦<5:0>: 0x00 ¡V Get, 0x01 - Set
*/
UCHAR action = 1, type = TYPE_CONFIGURATION;
os_alloc_mem(pAd, (UCHAR **)&pBuf, (NFC_WSC_TLV_SIZE*sizeof(UCHAR)));
if (pBuf == NULL)
{
return FALSE;
}
NfcBuildWscProfileTLV(pAd, pWscCtrl, pBuf, &BufLen);
if (pBuf && (BufLen != 0))
{
NfcCommand(pAd, action, type, BufLen, pBuf);
os_free_mem(NULL, pBuf);
}
if ((pAd->OpMode == OPMODE_AP) && (pWscCtrl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED))
{
pWscCtrl->WscConfStatus = WSC_SCSTATE_CONFIGURED;
WscBuildBeaconIE(pAd, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, 0, NULL, 0,AP_MODE);
WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, 0, NULL, 0,AP_MODE);
APUpdateAllBeaconFrame(pAd);
}
if (pWscCtrl->WscUpdatePortCfgTimerRunning)
{
BOOLEAN bCancel;
RTMPCancelTimer(&pWscCtrl->WscUpdatePortCfgTimer, &bCancel);
}
else
pWscCtrl->WscUpdatePortCfgTimerRunning = TRUE;
RTMPSetTimer(&pWscCtrl->WscUpdatePortCfgTimer, 1000);
return TRUE;
}
INT Get_NfcStatus_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
UCHAR data = 0;
/*
Action: b¡¦<7:6>: 0x0 ¡V To NFC, 0x1 ¡V From NFC
b¡¦<5:0>: 0x0 ¡V Get, 0x01 - Set
*/
UCHAR action = 0, type = TYPE_NFC_STATUS; /* 5 - NFC Status */
NfcCommand(pAd, action, type, 0, NULL);
return TRUE;
}
/*
NfcPasswdCompute:
1 - use hex device passwd to calculate PSK1 & PSK2.
2 - the device password is expressed in hexadecimal using ASCII characters (two characters per octet, uppercase letters only) to caculate PSK1 & PSK2.
*/
INT Set_DoWpsByNFC_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
UCHAR apidx = pObj->ioctl_if, mac_addr[MAC_ADDR_LEN];
BOOLEAN bFromApCli = FALSE;
PWSC_CTRL pWscCtrl;
UINT32 val = 0;
pWscCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl;
val = simple_strtol(arg, 0, 10);
if (val == 0)
pWscCtrl->bTriggerByNFC = FALSE;
else
{
pWscCtrl->bTriggerByNFC = TRUE;
pWscCtrl->NfcPasswdCaculate = val;
}
DBGPRINT(RT_DEBUG_TRACE, ("%s : bTriggerByNFC=%d, NfcPasswdCaculate = %d\n",
__FUNCTION__, pWscCtrl->bTriggerByNFC, pWscCtrl->NfcPasswdCaculate));
return TRUE;
}
INT Set_NfcRegenPK_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
UCHAR apidx = pObj->ioctl_if, mac_addr[MAC_ADDR_LEN];
BOOLEAN bFromApCli = FALSE;
PWSC_CTRL pWscCtrl;
UINT32 val = 0;
pWscCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl;
val = simple_strtol(arg, 0, 10);
if (val == 1)
pWscCtrl->bRegenPublicKey = 1;
else
pWscCtrl->bRegenPublicKey = 0;
DBGPRINT(RT_DEBUG_TRACE, ("%s : bRegenPublicKey=%d, \n",
__FUNCTION__, pWscCtrl->bRegenPublicKey));
}
#endif /* WSC_NFC_SUPPORT */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,484 @@
/****************************************************************************
* Ralink Tech Inc.
* Taiwan, R.O.C.
*
* (c) Copyright 2010, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Abstract:
All related POWER SAVE function body.
***************************************************************************/
#include "rt_config.h"
/*
========================================================================
Routine Description:
This routine is used to do insert packet into power-saveing queue.
Arguments:
pAd: Pointer to our adapter
pPacket: Pointer to send packet
pMacEntry: portint to entry of MacTab. the pMacEntry store attribute of client (STA).
QueIdx: Priority queue idex.
Return Value:
NDIS_STATUS_SUCCESS:If succes to queue the packet into TxSwQueue.
NDIS_STATUS_FAILURE: If failed to do en-queue.
========================================================================
*/
NDIS_STATUS RtmpInsertPsQueue(
RTMP_ADAPTER *pAd,
PNDIS_PACKET pPacket,
MAC_TABLE_ENTRY *pMacEntry,
UCHAR QueIdx)
{
ULONG IrqFlags;
#ifdef UAPSD_SUPPORT
/* put the U-APSD packet to its U-APSD queue by AC ID */
UINT32 ac_id = QueIdx - QID_AC_BE; /* should be >= 0 */
if (UAPSD_MR_IS_UAPSD_AC(pMacEntry, ac_id))
{
UAPSD_PacketEnqueue(pAd, pMacEntry, pPacket, ac_id);
#if defined(DOT11Z_TDLS_SUPPORT)
TDLS_UAPSDP_TrafficIndSend(pAd, pMacEntry->Addr);
#endif /* defined(DOT11Z_TDLS_SUPPORT) */
}
else
#endif /* UAPSD_SUPPORT */
{
if (pMacEntry->PsQueue.Number >= MAX_PACKETS_IN_PS_QUEUE)
{
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
return NDIS_STATUS_FAILURE;
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("legacy ps> queue a packet!\n"));
RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
InsertTailQueue(&pMacEntry->PsQueue, PACKET_TO_QUEUE_ENTRY(pPacket));
RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
}
}
#ifdef CONFIG_AP_SUPPORT
/* mark corresponding TIM bit in outgoing BEACON frame */
#ifdef UAPSD_SUPPORT
if (UAPSD_MR_IS_NOT_TIM_BIT_NEEDED_HANDLED(pMacEntry, QueIdx))
{
/* 1. the station is UAPSD station;
2. one of AC is non-UAPSD (legacy) AC;
3. the destinated AC of the packet is UAPSD AC. */
/* So we can not set TIM bit due to one of AC is legacy AC */
}
else
#endif /* UAPSD_SUPPORT */
{
WLAN_MR_TIM_BIT_SET(pAd, pMacEntry->apidx, pMacEntry->Aid);
}
#endif /* CONFIG_AP_SUPPORT */
return NDIS_STATUS_SUCCESS;
}
/*
==========================================================================
Description:
This routine is used to clean up a specified power-saving queue. It's
used whenever a wireless client is deleted.
==========================================================================
*/
VOID RtmpCleanupPsQueue(RTMP_ADAPTER *pAd, QUEUE_HEADER *pQueue)
{
QUEUE_ENTRY *pQEntry;
PNDIS_PACKET pPacket;
DBGPRINT(RT_DEBUG_TRACE, ("RtmpCleanupPsQueue (0x%08lx)...\n", (ULONG)pQueue));
while (pQueue->Head)
{
DBGPRINT(RT_DEBUG_TRACE,
("RtmpCleanupPsQueue %u...\n",pQueue->Number));
pQEntry = RemoveHeadQueue(pQueue);
/*pPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx); */
pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry);
RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE);
DBGPRINT(RT_DEBUG_TRACE, ("RtmpCleanupPsQueue pkt = %lx...\n", (ULONG)pPacket));
}
}
/*
========================================================================
Description:
This routine frees all packets in PSQ that's destined to a specific DA.
BCAST/MCAST in DTIMCount=0 case is also handled here, just like a PS-POLL
is received from a WSTA which has MAC address FF:FF:FF:FF:FF:FF
========================================================================
*/
VOID RtmpHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT wcid, BOOLEAN isActive)
{
QUEUE_ENTRY *pQEntry;
MAC_TABLE_ENTRY *pMacEntry;
unsigned long IrqFlags;
/*
DBGPRINT(RT_DEBUG_TRACE, ("rcv PS-POLL (AID=%d) from %02x:%02x:%02x:%02x:%02x:%02x\n",
Aid, PRINT_MAC(pAddr)));
*/
pMacEntry = &pAd->MacTab.Content[wcid];
if (RTMPEqualMemory(pMacEntry->Addr, pAddr, MAC_ADDR_LEN))
{
#ifdef DROP_MASK_SUPPORT
/* Disable Drop Mask */
drop_mask_set_per_client(pAd, pMacEntry, FALSE);
#endif /* DROP_MASK_SUPPORT */
#ifdef PS_ENTRY_MAITENANCE
pMacEntry->continuous_ps_count = 0;
#endif /* PS_ENTRY_MAITENANCE */
/* Sta is change to Power Active stat. Reset ContinueTxFailCnt */
pMacEntry->ContinueTxFailCnt = 0;
#ifdef UAPSD_SUPPORT
if (UAPSD_MR_IS_ALL_AC_UAPSD(isActive, pMacEntry))
{
/*
IEEE802.11e spec.
11.2.1.7 Receive operation for STAs in PS mode during the CP
When a non-AP QSTA that is using U-APSD and has all ACs
delivery-enabled detects that the bit corresponding to its AID
is set in the TIM, the non-AP QSTA shall issue a trigger frame
or a PS-Poll frame to retrieve the buffered MSDU or management
frames.
WMM Spec. v1.1a 070601
3.6.2 U-APSD STA Operation
3.6.2.3 In case one or more ACs are not
delivery-enabled ACs, the WMM STA may retrieve MSDUs and
MMPDUs belonging to those ACs by sending PS-Polls to the WMM AP.
In case all ACs are delivery enabled ACs, WMM STA should only
use trigger frames to retrieve MSDUs and MMPDUs belonging to
those ACs, and it should not send PS-Poll frames.
Different definitions in IEEE802.11e and WMM spec.
But we follow the WiFi WMM Spec.
*/
DBGPRINT(RT_DEBUG_TRACE, ("All AC are UAPSD, can not use PS-Poll\n"));
return; /* all AC are U-APSD, can not use PS-Poll */
}
#endif /* UAPSD_SUPPORT */
RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags);
if (isActive == FALSE)
{
if (pMacEntry->PsQueue.Head)
{
#ifdef UAPSD_SUPPORT
UINT32 NumOfOldPsPkt;
NumOfOldPsPkt = pAd->TxSwQueue[QID_AC_BE].Number;
#endif /* UAPSD_SUPPORT */
pQEntry = RemoveHeadQueue(&pMacEntry->PsQueue);
if ( pMacEntry->PsQueue.Number >=1 )
RTMP_SET_PACKET_MOREDATA(RTPKT_TO_OSPKT(pQEntry), TRUE);
InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pQEntry);
#ifdef UAPSD_SUPPORT
/* we need to call RTMPDeQueuePacket() immediately as below */
if (NumOfOldPsPkt != pAd->TxSwQueue[QID_AC_BE].Number)
{
if (RTMP_GET_PACKET_DHCP(RTPKT_TO_OSPKT(pQEntry)) ||
RTMP_GET_PACKET_EAPOL(RTPKT_TO_OSPKT(pQEntry)) ||
RTMP_GET_PACKET_WAI(RTPKT_TO_OSPKT(pQEntry)))
{
/*
These packets will use 1M/6M rate to send.
If you use 1M(2.4G)/6M(5G) to send, no statistics
count in NICUpdateFifoStaCounters().
So we can not count it for UAPSD; Or the SP will
not closed until timeout.
*/
}
else
UAPSD_MR_MIX_PS_POLL_RCV(pAd, pMacEntry);
}
#endif /* UAPSD_SUPPORT */
}
else
{
/*
or transmit a (QoS) Null Frame;
In addtion, in Station Keep Alive mechanism, we need to
send a QoS Null frame to detect the station live status.
*/
BOOLEAN bQosNull = FALSE;
if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE))
bQosNull = TRUE;
RtmpEnqueueNullFrame(pAd, pMacEntry->Addr, pMacEntry->CurrTxRate,
pMacEntry->Aid, pMacEntry->apidx,
bQosNull, TRUE, 0);
}
}
else
{
#ifdef UAPSD_SUPPORT
/* deliver all queued UAPSD packets */
UAPSD_AllPacketDeliver(pAd, pMacEntry);
/* end the SP if exists */
UAPSD_MR_ENTRY_RESET(pAd, pMacEntry);
#endif /* UAPSD_SUPPORT */
while(pMacEntry->PsQueue.Head)
{
pQEntry = RemoveHeadQueue(&pMacEntry->PsQueue);
InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pQEntry);
}
}
if ((pMacEntry->Aid > 0) && (pMacEntry->Aid < MAX_LEN_OF_MAC_TABLE) &&
(pMacEntry->PsQueue.Number == 0))
{
/* clear corresponding TIM bit because no any PS packet */
#ifdef CONFIG_AP_SUPPORT
if(pMacEntry->wdev->wdev_type == WDEV_TYPE_AP)
{
WLAN_MR_TIM_BIT_CLEAR(pAd, pMacEntry->apidx, pMacEntry->Aid);
}
#endif /* CONFIG_AP_SUPPORT */
pMacEntry->PsQIdleCount = 0;
}
RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags);
/*
Dequeue outgoing frames from TxSwQueue0..3 queue and process it
TODO: 2004-12-27 it's not a good idea to handle "More Data" bit here.
because the RTMPDeQueue process doesn't guarantee to de-queue the
desired MSDU from the corresponding TxSwQueue/PsQueue when QOS
in-used. We should consider "HardTransmt" this MPDU using MGMT
queue or things like that.
*/
RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
}
else
{
DBGPRINT(RT_DEBUG_ERROR,("rcv PS-POLL (AID=%d not match) from %02x:%02x:%02x:%02x:%02x:%02x\n",
pMacEntry->Aid, PRINT_MAC(pAddr)));
}
}
/*
==========================================================================
Description:
Update the station current power save mode. Calling this routine also
prove the specified client is still alive. Otherwise AP will age-out
this client once IdleCount exceeds a threshold.
==========================================================================
*/
BOOLEAN RtmpPsIndicate(RTMP_ADAPTER *pAd, UCHAR *pAddr, UCHAR wcid, UCHAR Psm)
{
MAC_TABLE_ENTRY *pEntry;
UCHAR old_psmode;
if (wcid >= MAX_LEN_OF_MAC_TABLE)
return PWR_ACTIVE;
pEntry = &pAd->MacTab.Content[wcid];
old_psmode = pEntry->PsMode;
/*
Change power save mode first because we will call
RTMPDeQueuePacket() in RtmpHandleRxPsPoll().
Or when Psm = PWR_ACTIVE, we will not do Aggregation in
RTMPDeQueuePacket().
*/
pEntry->NoDataIdleCount = 0;
pEntry->PsMode = Psm;
if (old_psmode != Psm) {
DBGPRINT(RT_DEBUG_INFO, ("%s():%02x:%02x:%02x:%02x:%02x:%02x %s!\n",
__FUNCTION__, PRINT_MAC(pAddr),
(Psm == PWR_SAVE ? "Sleep" : "wakes up, act like rx PS-POLL")));
}
if ((old_psmode == PWR_SAVE) && (Psm == PWR_ACTIVE))
{
#ifdef DROP_MASK_SUPPORT
/* Disable Drop Mask */
drop_mask_set_per_client(pAd, pEntry, FALSE);
#endif /* DROP_MASK_SUPPORT */
#ifdef PS_ENTRY_MAITENANCE
pEntry->continuous_ps_count = 0;
#endif /* PS_ENTRY_MAITENANCE */
#ifdef RTMP_MAC_PCI
#ifdef DOT11_N_SUPPORT
/*
When sta wake up, we send BAR to refresh the BA sequence.
TODO:
For RT2870, how to handle BA when STA in PS mode?
*/
SendRefreshBAR(pAd, pEntry);
#endif /* DOT11_N_SUPPORT */
#endif /* RTMP_MAC_PCI */
/* sleep station awakes, move all pending frames from PSQ to TXQ if any */
RtmpHandleRxPsPoll(pAd, pAddr, pEntry->wcid, TRUE);
}
#ifdef DROP_MASK_SUPPORT
else if ((old_psmode == PWR_ACTIVE) && (Psm == PWR_SAVE)) {
/* Enable Drop Mask */
drop_mask_set_per_client(pAd, pEntry, TRUE);
}
#endif /* DROP_MASK_SUPPORT */
#ifdef PS_ENTRY_MAITENANCE
else if((old_psmode == PWR_SAVE) && (Psm == PWR_SAVE)){
pEntry->continuous_ps_count = 0;
}
#endif /* PS_ENTRY_MAITENANCE */
return old_psmode;
}
#ifdef CONFIG_STA_SUPPORT
/*
========================================================================
Routine Description:
Check if PM of any packet is set.
Arguments:
pAd Pointer to our adapter
Return Value:
TRUE can set
FALSE can not set
Note:
========================================================================
*/
BOOLEAN RtmpPktPmBitCheck(RTMP_ADAPTER *pAd)
{
BOOLEAN FlgCanPmBitSet = TRUE;
#ifdef DOT11Z_TDLS_SUPPORT
/* check TDLS condition */
if (pAd->StaCfg.TdlsInfo.TdlsFlgIsKeepingActiveCountDown == TRUE)
FlgCanPmBitSet = FALSE;
#endif /* DOT11Z_TDLS_SUPPORT */
if (FlgCanPmBitSet == TRUE)
return (pAd->StaCfg.Psm == PWR_SAVE);
return FALSE;
}
VOID RtmpPsActiveExtendCheck(RTMP_ADAPTER *pAd)
{
/* count down the TDLS active counter */
#ifdef DOT11Z_TDLS_SUPPORT
if (pAd->StaCfg.TdlsInfo.TdlsPowerSaveActiveCountDown > 0)
{
pAd->StaCfg.TdlsInfo.TdlsPowerSaveActiveCountDown --;
if (pAd->StaCfg.TdlsInfo.TdlsPowerSaveActiveCountDown == 0)
{
/* recover our power save state */
TDLS_RECOVER_POWER_SAVE(pAd);
DBGPRINT(RT_DEBUG_TRACE, ("TDLS PS> Recover PS mode!\n"));
}
}
#endif /* DOT11Z_TDLS_SUPPORT */
}
VOID RtmpPsModeChange(RTMP_ADAPTER *pAd, UINT32 PsMode)
{
if (pAd->StaCfg.BssType == BSS_INFRA)
{
/* reset ps mode */
if (PsMode == Ndis802_11PowerModeMAX_PSP)
{
// do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
// to exclude certain situations.
// MlmeSetPsm(pAd, PWR_SAVE);
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
if (pAd->StaCfg.bWindowsACCAMEnable == FALSE)
pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeMAX_PSP;
pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeMAX_PSP;
pAd->StaCfg.DefaultListenCount = 5;
}
else if (PsMode == Ndis802_11PowerModeFast_PSP)
{
// do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
// to exclude certain situations.
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
if (pAd->StaCfg.bWindowsACCAMEnable == FALSE)
pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeFast_PSP;
pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeFast_PSP;
pAd->StaCfg.DefaultListenCount = 3;
}
else if (PsMode == Ndis802_11PowerModeLegacy_PSP)
{
// do NOT turn on PSM bit here, wait until MlmeCheckForPsmChange()
// to exclude certain situations.
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
if (pAd->StaCfg.bWindowsACCAMEnable == FALSE)
pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeLegacy_PSP;
pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeLegacy_PSP;
#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT)
pAd->StaCfg.DefaultListenCount = 1;
#else
pAd->StaCfg.DefaultListenCount = 3;
#endif // defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) //
}
else
{ //Default Ndis802_11PowerModeCAM
// clear PSM bit immediately
RTMP_SET_PSM_BIT(pAd, PWR_ACTIVE);
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM);
if (pAd->StaCfg.bWindowsACCAMEnable == FALSE)
pAd->StaCfg.WindowsPowerMode = Ndis802_11PowerModeCAM;
pAd->StaCfg.WindowsBatteryPowerMode = Ndis802_11PowerModeCAM;
}
/* change ps mode */
RTMPSendNullFrame(pAd, pAd->CommonCfg.TxRate, TRUE, FALSE);
DBGPRINT(RT_DEBUG_TRACE, ("PSMode=%ld\n", pAd->StaCfg.WindowsPowerMode));
}
}
#endif /* CONFIG_STA_SUPPORT */

View File

@ -0,0 +1,547 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 5F., No.36, Taiyuan St., Jhubei City,
* Hsinchu County 302,
* Taiwan, R.O.C.
*
* (c) Copyright 2002-2009, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************
Module Name:
routing_tab.c
Abstract:
This is a tab used to record all entries behind associated APClinet or STA/PC.
Revision History:
Who When What
--------- ---------- ----------------------------------------------
*/
#ifdef ROUTING_TAB_SUPPORT
#include "rt_config.h"
#include <linux/inetdevice.h>
#include <net/arp.h>
VOID RoutingTabInit(
IN PRTMP_ADAPTER pAd,
IN UINT32 Flag)
{
UINT32 i;
if(pAd->ApCfg.bRoutingTabInit)
{
pAd->ApCfg.RoutingTabFlag |= Flag;
return;
}
if(pAd->ApCfg.pRoutingEntryPool== NULL)
os_alloc_mem(pAd, (UCHAR **)&(pAd->ApCfg.pRoutingEntryPool), sizeof(ROUTING_ENTRY) * ROUTING_POOL_SIZE);
if (pAd->ApCfg.pRoutingEntryPool)
{
NdisZeroMemory(pAd->ApCfg.pRoutingEntryPool, sizeof(ROUTING_ENTRY) * ROUTING_POOL_SIZE);
initList(&pAd->ApCfg.RoutingEntryFreeList);
for (i = 0; i < ROUTING_POOL_SIZE; i++)
insertTailList(&pAd->ApCfg.RoutingEntryFreeList, (PLIST_ENTRY)(pAd->ApCfg.pRoutingEntryPool+i));
for (i = 0; i < ROUTING_HASH_TAB_SIZE; i++)
initList(&pAd->ApCfg.RoutingTab[i]);
NdisAllocateSpinLock(pAd, &pAd->ApCfg.RoutingTabLock);
pAd->ApCfg.RoutingTabFlag |= Flag;
pAd->ApCfg.bRoutingTabInit = TRUE;
}
else
DBGPRINT(RT_DEBUG_ERROR, ("%s: Fail to alloc memory for pAd->ApCfg.pRoutingEntryPool\n", __FUNCTION__));
}
VOID RoutingTabDestory(
IN PRTMP_ADAPTER pAd,
IN UINT32 Flag)
{
if(!pAd->ApCfg.bRoutingTabInit)
return;
RoutingTabClear(pAd, Flag);
pAd->ApCfg.RoutingTabFlag &= ~Flag;
if(pAd->ApCfg.RoutingTabFlag == 0)
{
NdisFreeSpinLock(&pAd->ApCfg.RoutingTabLock);
if (pAd->ApCfg.pRoutingEntryPool)
os_free_mem(NULL, pAd->ApCfg.pRoutingEntryPool);
pAd->ApCfg.pRoutingEntryPool = NULL;
initList(&pAd->ApCfg.RoutingEntryFreeList);
pAd->ApCfg.bRoutingTabInit = FALSE;
}
}
VOID RoutingTabClear(
IN PRTMP_ADAPTER pAd,
IN UINT32 Flag)
{
INT32 i;
PROUTING_ENTRY pRoutingEntry = NULL, pRoutingEntryNext = NULL;
RTMP_SEM_LOCK(&pAd->ApCfg.RoutingTabLock);
for (i = 0; i < ROUTING_HASH_TAB_SIZE; i++)
{
pRoutingEntry = GetRoutingTabHead(pAd, i);
while(pRoutingEntry)
{
pRoutingEntryNext = pRoutingEntry->pNext;
if(pRoutingEntry->Valid && ROUTING_ENTRY_TEST_FLAG(pRoutingEntry, Flag))
{
CLEAR_ROUTING_ENTRY(pRoutingEntry, Flag);
/* If not any entry type, then recycle to free list. */
if(!IS_ROUTING_ENTRY(pRoutingEntry))
{
delEntryList(&pAd->ApCfg.RoutingTab[i], (PLIST_ENTRY)pRoutingEntry);
NdisZeroMemory(pRoutingEntry, sizeof(ROUTING_ENTRY));
insertTailList(&pAd->ApCfg.RoutingEntryFreeList, (PLIST_ENTRY)pRoutingEntry);
}
}
pRoutingEntry = pRoutingEntryNext;
}
}
RTMP_SEM_UNLOCK(&pAd->ApCfg.RoutingTabLock);
}
PROUTING_ENTRY RoutingTabGetFree(
IN PRTMP_ADAPTER pAd)
{
PROUTING_ENTRY pRoutingEntry = NULL;
if(!pAd->ApCfg.bRoutingTabInit)
return NULL;
RTMP_SEM_LOCK(&pAd->ApCfg.RoutingTabLock);
pRoutingEntry = (PROUTING_ENTRY)removeHeadList(&pAd->ApCfg.RoutingEntryFreeList);
RTMP_SEM_UNLOCK(&pAd->ApCfg.RoutingTabLock);
return pRoutingEntry;
}
VOID RoutingTabSetAllFree(
IN PRTMP_ADAPTER pAd,
IN UCHAR Wcid,
IN UINT32 Flag)
{
INT32 i;
PROUTING_ENTRY pRoutingEntry = NULL, pRoutingEntryNext = NULL;
if(!pAd->ApCfg.bRoutingTabInit)
return;
RTMP_SEM_LOCK(&pAd->ApCfg.RoutingTabLock);
for (i = 0; i < ROUTING_HASH_TAB_SIZE; i++)
{
pRoutingEntry = GetRoutingTabHead(pAd, i);
while(pRoutingEntry)
{
pRoutingEntryNext = pRoutingEntry->pNext;
if(pRoutingEntry->Valid && (pRoutingEntry->Wcid == Wcid))
{
CLEAR_ROUTING_ENTRY(pRoutingEntry, Flag);
/* If not any entry type, then recycle to free list. */
if(!IS_ROUTING_ENTRY(pRoutingEntry))
{
delEntryList(&pAd->ApCfg.RoutingTab[i], (PLIST_ENTRY)pRoutingEntry);
NdisZeroMemory(pRoutingEntry, sizeof(ROUTING_ENTRY));
insertTailList(&pAd->ApCfg.RoutingEntryFreeList, (PLIST_ENTRY)pRoutingEntry);
}
}
pRoutingEntry = pRoutingEntryNext;
}
}
RTMP_SEM_UNLOCK(&pAd->ApCfg.RoutingTabLock);
}
VOID RoutingTabSetOneFree(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pMac,
IN UINT32 Flag)
{
INT32 HashId;
PROUTING_ENTRY pRoutingEntry = NULL;
if(!pAd->ApCfg.bRoutingTabInit)
return;
HashId = GetHashID(pMac);
if(HashId < 0)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Hash Id isn't correct!\n", __FUNCTION__));
return;
}
RTMP_SEM_LOCK(&pAd->ApCfg.RoutingTabLock);
pRoutingEntry = GetRoutingTabHead(pAd, HashId);
while (pRoutingEntry)
{
if (pRoutingEntry->Valid && MAC_ADDR_EQUAL(pMac, pRoutingEntry->Mac))
{
CLEAR_ROUTING_ENTRY(pRoutingEntry, Flag);
/* If not any entry type, then recycle to free list. */
if(!IS_ROUTING_ENTRY(pRoutingEntry))
{
delEntryList(&pAd->ApCfg.RoutingTab[HashId], (PLIST_ENTRY)pRoutingEntry);
NdisZeroMemory(pRoutingEntry, sizeof(ROUTING_ENTRY));
insertTailList(&pAd->ApCfg.RoutingEntryFreeList, (PLIST_ENTRY)pRoutingEntry);
}
break;
}
pRoutingEntry = pRoutingEntry->pNext;
}
RTMP_SEM_UNLOCK(&pAd->ApCfg.RoutingTabLock);
}
VOID RoutingEntryRefresh(
IN PRTMP_ADAPTER pAd,
IN PROUTING_ENTRY pRoutingEntry)
{
ULONG Now;
if(!pAd->ApCfg.bRoutingTabInit || !pRoutingEntry)
return;
NdisGetSystemUpTime(&Now);
pRoutingEntry->KeepAliveTime = Now + ROUTING_ENTRY_AGEOUT;
}
VOID RoutingEntrySet(
IN PRTMP_ADAPTER pAd,
IN UCHAR Wcid,
IN PUCHAR pMac,
IN PROUTING_ENTRY pRoutingEntry)
{
INT32 HashId;
if(!pAd->ApCfg.bRoutingTabInit || !pRoutingEntry)
return;
HashId = GetHashID(pMac);
if(HashId < 0)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Hash Id isn't correct!\n", __FUNCTION__));
return;
}
pRoutingEntry->Valid = 1;
pRoutingEntry->Wcid = Wcid;
COPY_MAC_ADDR(&pRoutingEntry->Mac, pMac);
pRoutingEntry->pNext = NULL;
RoutingEntryRefresh(pAd, pRoutingEntry);
RTMP_SEM_LOCK(&pAd->ApCfg.RoutingTabLock);
insertTailList(&pAd->ApCfg.RoutingTab[HashId], (PLIST_ENTRY)pRoutingEntry);
RTMP_SEM_UNLOCK(&pAd->ApCfg.RoutingTabLock);
}
INT32 GetHashID(
IN PUCHAR pMac)
{
INT32 HashId = -1;
if(pMac)
HashId = (*(pMac + 5)&(ROUTING_HASH_TAB_SIZE - 1));
return HashId;
}
PROUTING_ENTRY GetRoutingTabHead(
IN PRTMP_ADAPTER pAd,
IN INT32 Index)
{
if(!pAd->ApCfg.bRoutingTabInit)
return NULL;
if(Index < ROUTING_HASH_TAB_SIZE)
return (PROUTING_ENTRY)pAd->ApCfg.RoutingTab[Index].pHead;
else
return NULL;
}
BOOLEAN GetRoutingEntryAll(
IN PRTMP_ADAPTER pAd,
IN UCHAR Wcid,
IN UINT32 Flag,
IN INT32 BufMaxCount,
OUT const ROUTING_ENTRY **pEntryListBuf,
OUT PUINT32 pCount)
{
INT32 i, Total;
PROUTING_ENTRY pRoutingEntry = NULL;
BOOLEAN bFull = FALSE;
if(!pAd->ApCfg.bRoutingTabInit || !pEntryListBuf)
return FALSE;
RTMP_SEM_LOCK(&pAd->ApCfg.RoutingTabLock);
for (i = 0, Total = 0; i < ROUTING_HASH_TAB_SIZE; i++)
{
pRoutingEntry = GetRoutingTabHead(pAd, i);
while(pRoutingEntry)
{
if(pRoutingEntry->Valid &&
(pRoutingEntry->Wcid == Wcid) &&
ROUTING_ENTRY_TEST_FLAG(pRoutingEntry, Flag))
{
if(Total < BufMaxCount)
*(pEntryListBuf+Total++) = pRoutingEntry;
else
{
bFull = TRUE;
break;
}
}
pRoutingEntry = pRoutingEntry->pNext;
}
if(bFull)
break;
}
RTMP_SEM_UNLOCK(&pAd->ApCfg.RoutingTabLock);
*pCount = Total;
return TRUE;
}
INT RoutingTabGetEntryCount(
IN PRTMP_ADAPTER pAd)
{
int count = 0;
if(!pAd->ApCfg.bRoutingTabInit)
return 0;
count = (ROUTING_POOL_SIZE - getListSize(&pAd->ApCfg.RoutingEntryFreeList));
return count;
}
PROUTING_ENTRY RoutingTabLookup(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pMac,
IN BOOLEAN bUpdateAliveTime,
OUT UCHAR* pWcid)
{
PROUTING_ENTRY pRoutingEntry = NULL;
INT32 HashId;
if(RoutingTabGetEntryCount(pAd) == 0)
return NULL;
HashId = GetHashID(pMac);
if(HashId < 0)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Hash Id isn't correct!\n", __FUNCTION__));
return NULL;
}
pRoutingEntry = GetRoutingTabHead(pAd, HashId);
while (pRoutingEntry)
{
if (pRoutingEntry->Valid && MAC_ADDR_EQUAL(pMac, pRoutingEntry->Mac))
{
if (VALID_WCID(pRoutingEntry->Wcid))
{
if(bUpdateAliveTime)
{
RoutingEntryRefresh(pAd, pRoutingEntry);
pRoutingEntry->RetryKeepAlive = 0;
}
if(pWcid) *pWcid = pRoutingEntry->Wcid;
return pRoutingEntry;
}
else
return NULL;
}
pRoutingEntry = pRoutingEntry->pNext;
}
return NULL;
}
VOID RoutingTabARPLookupUpdate(
IN PRTMP_ADAPTER pAd,
IN PUCHAR pData)
{
UINT16 ProtoType, ArpType;
UCHAR *Pos = pData;
UCHAR *SenderMAC, *SenderIP;
INT32 HashId;
PROUTING_ENTRY pRoutingEntry = NULL;
if(RoutingTabGetEntryCount(pAd) == 0)
return;
NdisMoveMemory(&ProtoType, Pos, 2);
ProtoType = OS_NTOHS(ProtoType);
Pos += 2;
if (ProtoType == 0x0806) /* ETH_P_ARP */
{
//NdisMoveMemory(&ArpType, (Pos+6), 2);
//ArpType = OS_NTOHS(ArpType);
//if(ArpType == 2) /* ARP Response */
{
SenderMAC = Pos + 8;
SenderIP = Pos + 14;
HashId = GetHashID(SenderMAC);
if(HashId < 0)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Hash Id isn't correct!\n", __FUNCTION__));
return;
}
pRoutingEntry = GetRoutingTabHead(pAd, HashId);
while (pRoutingEntry)
{
if (pRoutingEntry->Valid && MAC_ADDR_EQUAL(SenderMAC, pRoutingEntry->Mac))
{
NdisCopyMemory(&pRoutingEntry->IPAddr,SenderIP,4);
return;
}
pRoutingEntry = pRoutingEntry->pNext;
}
}
}
}
INT RoutingEntrySendAliveCheck(
IN PRTMP_ADAPTER pAd,
IN PROUTING_ENTRY pRoutingEntry,
IN UCHAR *pSrcMAC,
IN UINT32 SrcIP)
{
struct sk_buff *skb = NULL;
PMAC_TABLE_ENTRY pEntry = NULL;
if(!pRoutingEntry || !pSrcMAC ||
!VALID_WCID(pRoutingEntry->Wcid) ||
(SrcIP == 0))
return FALSE;
if(RoutingTabGetEntryCount(pAd) == 0)
return FALSE;
pEntry = &pAd->MacTab.Content[pRoutingEntry->Wcid];
skb = arp_create(ARPOP_REQUEST, ETH_P_ARP, pRoutingEntry->IPAddr, pEntry->wdev->if_dev,
SrcIP, BROADCAST_ADDR, pSrcMAC, ZERO_MAC_ADDR);
if(!skb)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for arp request", __FUNCTION__));
return FALSE;
}
RTMP_SET_PACKET_WCID(skb, pRoutingEntry->Wcid);
RTMP_SET_PACKET_WDEV(skb, pEntry->wdev->wdev_idx);
pAd->RalinkCounters.PendingNdisPacketCount++;
APSendPacket(pAd, skb);
return TRUE;
}
VOID RoutingTabMaintain(
IN PRTMP_ADAPTER pAd)
{
UINT32 i,BridgeIP;
ULONG Now;
PROUTING_ENTRY pRoutingEntry = NULL, pRoutingEntryNext = NULL;
BOOLEAN bNeedSend = FALSE, bBridgeFound = FALSE, bNeedDelete = FALSE;
UCHAR BridgeMAC[MAC_ADDR_LEN];
if(RoutingTabGetEntryCount(pAd) == 0)
return;
#ifdef MAC_REPEATER_SUPPORT
if(!MAC_ADDR_EQUAL(pAd->ApCfg.BridgeAddress, ZERO_MAC_ADDR))
{
COPY_MAC_ADDR(BridgeMAC, pAd->ApCfg.BridgeAddress);
bBridgeFound = TRUE;
}
else
#endif /* MAC_REPEATER_SUPPORT */
{
#ifdef LINUX
struct net_device *pBridgeNetDev = NULL;
struct net *net= &init_net;
for_each_netdev(net, pBridgeNetDev)
{
if (pBridgeNetDev->priv_flags == IFF_EBRIDGE)
{
const struct in_device *pBridgeInDev = pBridgeNetDev->ip_ptr;
if (pBridgeInDev)
{
const struct in_ifaddr *ifa = pBridgeInDev->ifa_list;
if (ifa)
{
COPY_MAC_ADDR(BridgeMAC, pBridgeNetDev->dev_addr);
NdisCopyMemory(&BridgeIP, &ifa->ifa_address, 4);
bBridgeFound = TRUE;
break;
}
}
}
}
#endif /* LINUX */
}
if(!bBridgeFound)
return;
NdisGetSystemUpTime(&Now);
RTMP_SEM_LOCK(&pAd->ApCfg.RoutingTabLock);
for (i = 0; i < ROUTING_HASH_TAB_SIZE; i++)
{
pRoutingEntry = GetRoutingTabHead(pAd, i);
while(pRoutingEntry)
{
bNeedDelete = FALSE;
pRoutingEntryNext = pRoutingEntry->pNext;
if (pRoutingEntry->Valid && RTMP_TIME_AFTER(Now, pRoutingEntry->KeepAliveTime))
{
if(bBridgeFound)
{
if(pRoutingEntry->RetryKeepAlive >= ROUTING_ENTRY_MAX_RETRY)
bNeedDelete = TRUE;
else
{
if(RoutingEntrySendAliveCheck(pAd, pRoutingEntry, BridgeMAC, BridgeIP))
bNeedSend = TRUE;
RoutingEntryRefresh(pAd, pRoutingEntry);
pRoutingEntry->RetryKeepAlive++;
}
}
else
bNeedDelete = TRUE;
if(bNeedDelete)
{
delEntryList(&pAd->ApCfg.RoutingTab[i], (PLIST_ENTRY)pRoutingEntry);
NdisZeroMemory(pRoutingEntry, sizeof(ROUTING_ENTRY));
insertTailList(&pAd->ApCfg.RoutingEntryFreeList, (PLIST_ENTRY)pRoutingEntry);
}
}
pRoutingEntry = pRoutingEntryNext;
}
}
RTMP_SEM_UNLOCK(&pAd->ApCfg.RoutingTabLock);
/* Dequeue outgoing frames from TxSwQueue[] and process it */
if(bNeedSend)
RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, MAX_TX_PROCESS);
}
#endif /* ROUTING_TAB_SUPPORT */

View File

@ -0,0 +1,778 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2006, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Abstract:
***************************************************************************/
#ifdef DOT11K_RRM_SUPPORT
#include "rt_config.h"
/*
static CHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
*/
static VOID RRM_QuietOffsetTimeout(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3);
static VOID RRM_QuietTimeout(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3);
DECLARE_TIMER_FUNCTION(RRM_QuietOffsetTimeout);
DECLARE_TIMER_FUNCTION(RRM_QuietTimeout);
BUILD_TIMER_FUNCTION(RRM_QuietOffsetTimeout);
BUILD_TIMER_FUNCTION(RRM_QuietTimeout);
static VOID RRM_QuietOffsetTimeout(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
INT idx;
PRRM_CONFIG pRrmCfg = NULL;
RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) SystemSpecific3;
for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++)
{
pRrmCfg = &pAd->ApCfg.MBSSID[idx].RrmCfg;
if (&pRrmCfg->QuietCB.QuietOffsetTimer == pTimer)
break;
}
/* start Quiet . */
if (idx == pAd->ApCfg.BssidNum)
return;
pRrmCfg = &pAd->ApCfg.MBSSID[idx].RrmCfg;
pRrmCfg->QuietCB.QuietState = RRM_QUIET_SILENT;
RTMPSetTimer(&pRrmCfg->QuietCB.QuietTimer,
pRrmCfg->QuietCB.QuietDuration);
return;
}
static VOID RRM_QuietTimeout(
IN PVOID SystemSpecific1,
IN PVOID FunctionContext,
IN PVOID SystemSpecific2,
IN PVOID SystemSpecific3)
{
INT idx;
PRRM_CONFIG pRrmCfg = NULL;
RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext;
PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) SystemSpecific3;
for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++)
{
pRrmCfg = &pAd->ApCfg.MBSSID[idx].RrmCfg;
if (&pRrmCfg->QuietCB.QuietTimer == pTimer)
break;
}
/* stop Quiet . */
if (idx == pAd->ApCfg.BssidNum)
return;
pRrmCfg = &pAd->ApCfg.MBSSID[idx].RrmCfg;
pRrmCfg->QuietCB.QuietState = RRM_QUIET_IDLE;
return;
}
void RRM_ReadParametersFromFile(
IN PRTMP_ADAPTER pAd,
PSTRING tmpbuf,
PSTRING buffer)
{
INT loop;
PSTRING macptr;
/* RRMEnable */
if (RTMPGetKeyParameter("RRMEnable", tmpbuf, 255, buffer, TRUE))
{
for (loop=0, macptr = rstrtok(tmpbuf,";");
(macptr && loop < MAX_MBSSID_NUM(pAd));
macptr = rstrtok(NULL,";"), loop++)
{
LONG Enable;
Enable = simple_strtol(macptr, 0, 10);
pAd->ApCfg.MBSSID[loop].RrmCfg.bDot11kRRMEnable =
(Enable > 0) ? TRUE : FALSE;
pAd->ApCfg.MBSSID[loop].RrmCfg.bDot11kRRMEnableSet = TRUE;
DBGPRINT(RT_DEBUG_TRACE, ("%s::(bDot11kRRMEnable[%d]=%d)\n",
__FUNCTION__, loop,
pAd->ApCfg.MBSSID[loop].RrmCfg.bDot11kRRMEnable));
}
}
else
{
for (loop = 0; loop < MAX_MBSSID_NUM(pAd); loop++)
pAd->ApCfg.MBSSID[loop].RrmCfg.bDot11kRRMEnable = FALSE;
}
/* Regulatory Class */
if (RTMPGetKeyParameter("RegulatoryClass", tmpbuf, 255, buffer, TRUE))
{
LONG Value;
for (loop=0, macptr = rstrtok(tmpbuf,";");
(macptr && loop < MAX_NUM_OF_REGULATORY_CLASS);
macptr = rstrtok(NULL,";"), loop++)
{
Value = simple_strtol(macptr, 0, 10);
pAd->CommonCfg.RegulatoryClass[loop] = Value;
}
}
return;
}
INT Set_Dot11kRRM_Enable_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
UCHAR ifIndex = pObj->ioctl_if;
ULONG Value;
if (ifIndex >= pAd->ApCfg.BssidNum)
{
DBGPRINT(RT_DEBUG_OFF, ("Unknow If index (%d)", ifIndex));
return -1;
}
Value = (UINT) simple_strtol(arg, 0, 10);
pAd->ApCfg.MBSSID[ifIndex].RrmCfg.bDot11kRRMEnable =
(BOOLEAN)(Value) == 0 ? FALSE : TRUE;
return 1;
}
INT Set_BeaconReq_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
INT Loop;
POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
UCHAR ifIndex = pObj->ioctl_if;
UINT Aid = 1;
UINT ArgIdx;
PSTRING thisChar;
RRM_MLME_BCN_REQ_INFO BcnReq;
ArgIdx = 0;
NdisZeroMemory(&BcnReq, sizeof(RRM_MLME_BCN_REQ_INFO));
while ((thisChar = strsep((char **)&arg, "-")) != NULL)
{
switch(ArgIdx)
{
case 0: /* Aid. */
Aid = (UINT8) simple_strtol(thisChar, 0, 16);
if (!VALID_WCID(Aid))
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid));
return TRUE;
}
break;
case 1: /* Meausre Duration. */
BcnReq.MeasureDuration = (UINT8) simple_strtol(thisChar, 0, 10);
case 2: /* Regulator Class */
BcnReq.RegulatoryClass = (UINT8) simple_strtol(thisChar, 0, 10);
break;
case 3: /* BSSID */
if(strlen(thisChar) != 17)
{
DBGPRINT(RT_DEBUG_ERROR,
("%s: invalid value BSSID.\n", __FUNCTION__));
return TRUE;
}
if(strlen(thisChar) == 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */
{
PSTRING value;
for (Loop=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":"))
{
if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) )
return FALSE; /*Invalid */
AtoH(value, &BcnReq.Bssid[Loop++], 1);
}
if(Loop != 6)
return TRUE;
}
break;
case 4: /* SSID */
BcnReq.pSsid = (PUINT8)thisChar;
BcnReq.SsidLen = strlen(thisChar);
break;
case 5: /* measure channel */
BcnReq.MeasureCh = (UINT8) simple_strtol(thisChar, 0, 10);
break;
case 6: /* measure mode. */
BcnReq.MeasureMode = (UINT8) simple_strtol(thisChar, 0, 10);
if (BcnReq.MeasureMode > RRM_BCN_REQ_MODE_BCNTAB)
{
DBGPRINT(RT_DEBUG_ERROR,
("%s: invalid Measure Mode. %d\n", __FUNCTION__, BcnReq.MeasureMode));
return TRUE;
}
case 7: /* regulatory class. */
{
PSTRING RegClassString;
int RegClassIdx;
RegClassIdx = 0;
while ((RegClassString = strsep((char **)&thisChar, "+")) != NULL)
{
BcnReq.ChRepRegulatoryClass[RegClassIdx] =
(UINT8) simple_strtol(RegClassString, 0, 10);
RegClassIdx++;
}
}
break;
}
ArgIdx++;
}
if (ArgIdx < 7 || ArgIdx > 8)
{
DBGPRINT(RT_DEBUG_ERROR,
("%s: invalid args (%d).\n", __FUNCTION__, ArgIdx));
DBGPRINT(RT_DEBUG_ERROR,
("eg: iwpriv ra0 set BcnReq=<Aid>-<Duration>-<RegulatoryClass>-<BSSID>-<SSID>-<MeasureCh>-<MeasureMode>-<ChRegClass>\n"));
return TRUE;
}
BcnReq.BcnReqCapFlag.field.ReportCondition = TRUE;
if (BcnReq.MeasureCh == 255)
BcnReq.BcnReqCapFlag.field.ChannelRep = TRUE;
else
BcnReq.BcnReqCapFlag.field.ChannelRep = FALSE;
RRM_EnqueueBcnReq(pAd, Aid, ifIndex, &BcnReq);
return TRUE;
}
INT Set_LinkMeasureReq_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
UCHAR ifIndex = pObj->ioctl_if;
UINT Aid = 1;
Aid = simple_strtol(arg, 0, 10);
RRM_EnqueueLinkMeasureReq(pAd, Aid, ifIndex);
return TRUE;
}
INT Set_TxStreamMeasureReq_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie;
UCHAR ifIndex = pObj->ioctl_if;
UINT Aid = 1;
UINT ArgIdx;
PSTRING thisChar;
RRM_MLME_TRANSMIT_REQ_INFO TransmitReq;
PMAC_TABLE_ENTRY pMacEntry;
ArgIdx = 0;
NdisZeroMemory(&TransmitReq, sizeof(RRM_MLME_TRANSMIT_REQ_INFO));
while ((thisChar = strsep((char **)&arg, "-")) != NULL)
{
switch(ArgIdx)
{
case 0: /* Aid. */
Aid = (UINT8) simple_strtol(thisChar, 0, 10);
if (!VALID_WCID(Aid))
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid));
return TRUE;
}
break;
case 1: /* DurationMandotory. */
TransmitReq.bDurationMandatory =
((UINT16)simple_strtol(thisChar, 0, 10) > 0 ? TRUE : FALSE);
break;
case 2: /* Measure Duration */
TransmitReq.MeasureDuration = (UINT16)simple_strtol(thisChar, 0, 10);
break;
case 3: /* TID */
TransmitReq.Tid = (UINT8) simple_strtol(thisChar, 0, 10);
break;
case 4: /* Bin 0 Range */
TransmitReq.BinRange = (UINT8) simple_strtol(thisChar, 0, 10);
break;
case 5: /* Averange Condition */
TransmitReq.ArvCondition =
((UINT8) simple_strtol(thisChar, 0, 10)) > 0 ? 1 : 0;
break;
case 6: /* Consecutive Condition */
TransmitReq.ConsecutiveCondition =
((UINT8) simple_strtol(thisChar, 0, 10)) > 0 ? 1 : 0;
break;
case 7: /* Delay Condition */
TransmitReq.DelayCondition =
((UINT8) simple_strtol(thisChar, 0, 10)) > 0 ? 1 : 0;
break;
case 8: /* Averange Error Threshold */
TransmitReq.AvrErrorThreshold =
(UINT8) simple_strtol(thisChar, 0, 10);
break;
case 9: /* Consecutive Error Threshold */
TransmitReq.ConsecutiveErrorThreshold =
(UINT8) simple_strtol(thisChar, 0, 10);
break;
case 10: /* Delay Threshold */
TransmitReq.DelayThreshold =
(UINT8) simple_strtol(thisChar, 0, 10);
break;
case 11: /* Measure counter */
TransmitReq.MeasureCnt =
(UINT8) simple_strtol(thisChar, 0, 10);
break;
case 12: /* Trigger time out */
TransmitReq.TriggerTimeout =
(UINT8) simple_strtol(thisChar, 0, 10);
break;
}
ArgIdx++;
}
if ((ArgIdx != 13) && (ArgIdx != 5))
{
DBGPRINT(RT_DEBUG_ERROR,
("%s: invalid args (%d).\n", __FUNCTION__, ArgIdx));
DBGPRINT(RT_DEBUG_ERROR,
("eg: iwpriv ra0 set txreq=<Aid>-<DurationMandortory>-<Duration>-<TID>-<BinRange>[-<AvrCond>-<ConsecutiveCond>-<DealyCond>-<AvrErrorThreshold>-<ConsecutiveErrorThreshold>-<DelayThreshold>-<MeasureCnt>-<TriggerTimeout>]\n"));
return TRUE;
}
if (ArgIdx == 5)
TransmitReq.bTriggerReport = 0;
else
TransmitReq.bTriggerReport = 1;
pMacEntry = &pAd->MacTab.Content[Aid];
DBGPRINT(RT_DEBUG_ERROR, ("%s::Aid=%d, PeerMac=%02x:%02x:%02x:%02x:%02x:%02x\n",
__FUNCTION__, Aid, pMacEntry->Addr[0], pMacEntry->Addr[1],
pMacEntry->Addr[2], pMacEntry->Addr[3], pMacEntry->Addr[4], pMacEntry->Addr[5]));
DBGPRINT(RT_DEBUG_ERROR, ("Duration=%d, Tid=%d, Bin 0 Range=%d\n",
TransmitReq.MeasureDuration, TransmitReq.Tid, TransmitReq.BinRange));
DBGPRINT(RT_DEBUG_ERROR, ("ArvCondition=%d, ConsecutiveCondition=%d, DelayCondition=%d\n",
TransmitReq.ArvCondition, TransmitReq.ConsecutiveCondition, TransmitReq.DelayCondition));
DBGPRINT(RT_DEBUG_ERROR, ("AvrErrorThreshold=%d, ConsecutiveErrorThreshold=%d\n",
TransmitReq.AvrErrorThreshold, TransmitReq.ConsecutiveErrorThreshold));
DBGPRINT(RT_DEBUG_ERROR, ("DelayThreshold=%d\n", TransmitReq.DelayThreshold));
DBGPRINT(RT_DEBUG_ERROR, ("MeasureCnt=%d, TriggerTimeout=%d\n",
TransmitReq.MeasureCnt, TransmitReq.TriggerTimeout));
RRM_EnqueueTxStreamMeasureReq(pAd, Aid, ifIndex, &TransmitReq);
return TRUE;
}
INT Set_RRM_Selftest_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
UINT Cmd = 1;
PMAC_TABLE_ENTRY pEntry;
UCHAR StaAddr[MAC_ADDR_LEN] = {0x00,0x0c,0x43,0x00,0x00,0x00};
struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[0/*pEntry->apidx*/].wdev;
Cmd = simple_strtol(arg, 0, 10);
switch(Cmd)
{
case 1: /* insert a STA for RRM Beacon Report request testing. */
pEntry = MacTableInsertEntry(pAd, StaAddr, wdev, 0, OPMODE_AP, TRUE);
pEntry->Sst = SST_ASSOC;
pEntry->CapabilityInfo |= RRM_CAP_BIT;
pEntry->RrmEnCap.field.BeaconActiveMeasureCap = 1;
break;
}
return TRUE;
}
INT RRM_InfoDisplay_Proc(
IN PRTMP_ADAPTER pAd,
IN PSTRING arg)
{
INT loop;
for (loop = 0; loop < pAd->ApCfg.BssidNum; loop++)
{
DBGPRINT(RT_DEBUG_OFF, ("%d: bDot11kRRMEnable=%d\n",
loop, pAd->ApCfg.MBSSID[loop].RrmCfg.bDot11kRRMEnable));
}
DBGPRINT(RT_DEBUG_OFF, ("Country Code=%s\n",
pAd->CommonCfg.CountryCode));
DBGPRINT(RT_DEBUG_OFF, ("Power Constraint=%d\n",
pAd->CommonCfg.PwrConstraint));
DBGPRINT(RT_DEBUG_OFF, ("Regulator Class="));
for (loop = 0; loop < MAX_NUM_OF_REGULATORY_CLASS; loop++)
{
if (pAd->CommonCfg.RegulatoryClass[loop] == 0)
break;
DBGPRINT(RT_DEBUG_OFF, ("%d ",
pAd->CommonCfg.RegulatoryClass[loop]));
}
DBGPRINT(RT_DEBUG_OFF, ("\n"));
DBGPRINT(RT_DEBUG_OFF, ("Regulator TxPowerPercentage=%ld\n",
pAd->CommonCfg.TxPowerPercentage));
return TRUE;
}
VOID RRM_CfgInit(
IN PRTMP_ADAPTER pAd)
{
INT loop;
PRRM_CONFIG pRrmCfg;
for (loop = 0; loop < MAX_MBSSID_NUM(pAd); loop++)
{
pRrmCfg = &pAd->ApCfg.MBSSID[loop].RrmCfg;
pRrmCfg->QuietCB.QuietPeriod = RRM_DEFAULT_QUIET_PERIOD;
pRrmCfg->QuietCB.QuietDuration = RRM_DEFAULT_QUIET_DURATION;
pRrmCfg->QuietCB.QuietOffset = RRM_DEFAULT_QUIET_OFFSET;
RTMPInitTimer(pAd, &pRrmCfg->QuietCB.QuietOffsetTimer, GET_TIMER_FUNCTION(RRM_QuietOffsetTimeout), pAd, FALSE);
RTMPInitTimer(pAd, &pRrmCfg->QuietCB.QuietTimer, GET_TIMER_FUNCTION(RRM_QuietTimeout), pAd, FALSE);
pRrmCfg->QuietCB.QuietState = RRM_QUIET_IDLE;
pRrmCfg->QuietCB.CurAid = 1;
if (pRrmCfg->bDot11kRRMEnableSet == FALSE)
pRrmCfg->bDot11kRRMEnable = FALSE; //set to default off
pRrmCfg->bDot11kRRMNeighborRepTSFEnable = FALSE;
}
return;
}
VOID RRM_QuietUpdata(
IN PRTMP_ADAPTER pAd)
{
INT loop;
PRRM_CONFIG pRrmCfg;
for (loop = 0; loop < pAd->ApCfg.BssidNum; loop++)
{
if (pAd->ApCfg.MBSSID[loop].MSSIDDev == NULL)
continue;
if (!(pAd->ApCfg.MBSSID[loop].MSSIDDev->flags & IFF_UP))
continue;
pRrmCfg = &pAd->ApCfg.MBSSID[loop].RrmCfg;
if (pRrmCfg->bDot11kRRMEnable != TRUE)
continue;
if (pRrmCfg->QuietCB.QuietCnt == pRrmCfg->QuietCB.QuietPeriod)
{
/* issue Bcn Report Request to STAs supported RRM-Bcn Report. */
/* Voice-enterpise doesn't require it in testing-event3 so remove it. */
/*RRM_BcnReortQuery(pAd, loop, pRrmCfg); */
}
if ((pRrmCfg->QuietCB.QuietCnt == 0)
&& (pRrmCfg->QuietCB.QuietState == RRM_QUIET_IDLE))
{
if (pRrmCfg->QuietCB.QuietOffset != 0)
{
/* Start QuietOffsetTimer. */
RTMPSetTimer(&pRrmCfg->QuietCB.QuietOffsetTimer,
pRrmCfg->QuietCB.QuietOffset);
}
else
{
/* Start Quiet Timer. */
pRrmCfg->QuietCB.QuietState = RRM_QUIET_SILENT;
RTMPSetTimer(&pRrmCfg->QuietCB.QuietTimer,
pRrmCfg->QuietCB.QuietDuration);
}
}
RRM_QUIET_CNT_DEC(pRrmCfg->QuietCB.QuietCnt, pRrmCfg->QuietCB.QuietPeriod);
}
return;
}
VOID RRM_PeerNeighborReqAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
PUCHAR pFramePtr = pFr->Octet;
PMAC_TABLE_ENTRY pEntry;
UINT8 DialogToken;
PCHAR pSsid = NULL;
UINT8 SsidLen = 0;
DBGPRINT(RT_DEBUG_TRACE, ("%s::\n", __FUNCTION__));
/* skip Category and action code. */
pFramePtr += 2;
pEntry = MacTableLookup(pAd, pFr->Hdr.Addr2);
if (!pEntry || (pEntry->Sst != SST_ASSOC))
return;
if (RRM_PeerNeighborReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &pSsid, &SsidLen))
{
DBGPRINT(RT_DEBUG_TRACE, ("DialogToken=%x\n", DialogToken));
DBGPRINT(RT_DEBUG_TRACE, ("pSsid=%s\n", pSsid));
DBGPRINT(RT_DEBUG_TRACE, ("SsidLen=%d\n", SsidLen));
RRM_EnqueueNeighborRep(pAd, pEntry, DialogToken, pSsid, SsidLen);
}
return;
}
VOID RRM_BeaconReportHandler(
IN PRTMP_ADAPTER pAd,
IN PRRM_BEACON_REP_INFO pBcnRepInfo,
IN LONG Length)
{
CHAR Rssi;
USHORT LenVIE = 0;
NDIS_802_11_VARIABLE_IEs *pVIE = NULL;
UCHAR VarIE[MAX_VIE_LEN];
ULONG Idx = BSS_NOT_FOUND;
LONG RemainLen = Length;
PRRM_BEACON_REP_INFO pBcnRep;
PUINT8 ptr;
RRM_BEACON_REP_INFO_FIELD BcnReqInfoField;
UINT32 Ptsf;
BCN_IE_LIST *ie_list = NULL;
os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST));
if (ie_list == NULL) {
DBGPRINT(RT_DEBUG_ERROR, ("%s(): Alloc ie_list failed!\n", __FUNCTION__));
return;
}
NdisZeroMemory(ie_list, sizeof(BCN_IE_LIST));
ptr = (PUINT8)pBcnRepInfo;
pBcnRep = (PRRM_BEACON_REP_INFO)ptr;
Ptsf = le2cpu32(pBcnRep->ParentTSF);
BcnReqInfoField.word = pBcnRep->RepFrameInfo;
DBGPRINT(RT_DEBUG_TRACE, ("%s:: ReqClass=%d, Channel=%d\n",
__FUNCTION__, pBcnRep->RegulatoryClass, pBcnRep->ChNumber));
DBGPRINT(RT_DEBUG_TRACE, ("Bssid=%02x:%02x:%02x:%02x:%02x:%02x\n",
PRINT_MAC(pBcnRep->Bssid)));
Rssi = pBcnRep->RCPI + pAd->BbpRssiToDbmDelta;
RemainLen -= sizeof(RRM_BEACON_REP_INFO);
ptr += sizeof(RRM_BEACON_REP_INFO);
/* check option sub element IE. */
while (RemainLen > 0)
{
PRRM_SUBFRAME_INFO pRrmSubFrame;
pRrmSubFrame = (PRRM_SUBFRAME_INFO)ptr;
switch(pRrmSubFrame->SubId)
{
case 1:
if (BcnReqInfoField.field.ReportFrameType == 0)
{
/* Init Variable IE structure */
pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE;
pVIE->Length = 0;
PeerBeaconAndProbeRspSanity(pAd,
pRrmSubFrame->Oct,
pRrmSubFrame->Length,
pBcnRep->ChNumber,
ie_list,
&LenVIE,
pVIE);
}
break;
case 221:
DBGPRINT(RT_DEBUG_TRACE, ("%s:: SubIe: ID=%x, Len=%d\n",
__FUNCTION__, pRrmSubFrame->SubId, pRrmSubFrame->Length));
break;
}
RemainLen -= (pRrmSubFrame->Length + 2);
ptr += (pRrmSubFrame->Length + 2);
/* avoid infinite loop. */
if (pRrmSubFrame->Length == 0)
break;
}
if (NdisEqualMemory(pBcnRep->Bssid, ie_list->Bssid, MAC_ADDR_LEN) == FALSE)
{
DBGPRINT(RT_DEBUG_WARN, ("%s():BcnReq->BSSID not equal ie_list->Bssid!\n", __FUNCTION__));
}
#ifdef AP_SCAN_SUPPORT
Idx = BssTableSetEntry(pAd, &pAd->ScanTab, ie_list, Rssi, LenVIE, pVIE);
if (Idx != BSS_NOT_FOUND)
{
BSS_ENTRY *pBssEntry = &pAd->ScanTab.BssEntry[Idx];
NdisMoveMemory(pBssEntry->PTSF, (PUCHAR)&Ptsf, 4);
pBssEntry->RegulatoryClass = pBcnRep->RegulatoryClass;
pBssEntry->CondensedPhyType = BcnReqInfoField.field.CondensePhyType;
pBssEntry->RSNI = pBcnRep->RSNI;
}
#endif /* AP_SCAN_SUPPORT */
return;
}
VOID RRM_PeerMeasureRepAction(
IN PRTMP_ADAPTER pAd,
IN MLME_QUEUE_ELEM *Elem)
{
PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg;
PUCHAR pFramePtr = pFr->Octet;
ULONG MsgLen = Elem->MsgLen;
PMEASURE_REQ_ENTRY pDialogEntry;
PMAC_TABLE_ENTRY pEntry;
UINT8 DialogToken;
DBGPRINT(RT_DEBUG_TRACE, ("%s::\n", __FUNCTION__));
/* skip Category and action code. */
pFramePtr += 2;
MsgLen -= 2;
/* get DialogToken. */
NdisMoveMemory(&DialogToken, pFramePtr, 1);
pFramePtr += 1;
MsgLen -= 1;
/*
Not a autonomous measure report (non zero DialogToken).
check the dialog token field.
drop it if the dialog token doesn't match.
*/
pDialogEntry = NULL;
if ((DialogToken != 0)
&& ((pDialogEntry = MeasureReqLookUp(pAd, DialogToken)) == NULL))
return;
if (pDialogEntry != NULL)
MeasureReqDelete(pAd, pDialogEntry->DialogToken);
do
{
PEID_STRUCT eid_ptr;
MEASURE_REPORT_MODE ReportMode;
UINT8 ReportType;
PRRM_BEACON_REP_INFO pMeasureRep;
/* Is the STA associated. Dorp the Measure report if it's not. */
pEntry = MacTableLookup(pAd, pFr->Hdr.Addr2);
if (!pEntry || (pEntry->Sst != SST_ASSOC))
break;
eid_ptr = (PEID_STRUCT)pFramePtr;
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_MEASUREMENT_REPORT:
{
LONG BcnRepLen = (LONG)eid_ptr->Len - 3;
NdisMoveMemory(&ReportMode, eid_ptr->Octet + 1, 1);
NdisMoveMemory(&ReportType, eid_ptr->Octet + 2, 1);
pMeasureRep = (PVOID)(eid_ptr->Octet + 3);
if (ReportType == RRM_MEASURE_SUBTYPE_BEACON)
RRM_BeaconReportHandler(pAd, pMeasureRep,
BcnRepLen);
}
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
} while(FALSE);
return;
}
#endif /* DOT11K_RRM_SUPPORT */

View File

@ -0,0 +1,148 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2006, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Abstract:
***************************************************************************/
#ifdef DOT11K_RRM_SUPPORT
#include "rt_config.h"
/*
==========================================================================
Description:
Parametrs:
Return : None.
==========================================================================
*/
BOOLEAN RRM_PeerNeighborReqSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *pMsg,
IN ULONG MsgLen,
OUT PUINT8 pDialogToken,
OUT PCHAR *pSsid,
OUT PUINT8 pSsidLen)
{
PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
PUCHAR pFramePtr = Fr->Octet;
BOOLEAN result = FALSE;
PEID_STRUCT eid_ptr;
PMAC_TABLE_ENTRY pEntry;
MsgLen -= sizeof(HEADER_802_11);
/* skip category and action code. */
pFramePtr += 2;
MsgLen -= 2;
if (pDialogToken == NULL)
return result;
pEntry = MacTableLookup(pAd, Fr->Hdr.Addr2);
if (pEntry->apidx > pAd->ApCfg.BssidNum)
{
return result;
}
*pSsid = pAd->ApCfg.MBSSID[pEntry->apidx].Ssid;
*pSsidLen = pAd->ApCfg.MBSSID[pEntry->apidx].SsidLen;
result = TRUE;
NdisMoveMemory(pDialogToken, pFramePtr, 1);
pFramePtr += 1;
MsgLen -= 1;
eid_ptr = (PEID_STRUCT)pFramePtr;
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
{
switch(eid_ptr->Eid)
{
case RRM_NEIGHBOR_REQ_SSID_SUB_ID:
*pSsid = (PCHAR)eid_ptr->Octet;
*pSsidLen = eid_ptr->Len;
break;
case RRM_NEIGHBOR_REQ_VENDOR_SUB_ID:
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
return result;
}
BOOLEAN RRM_PeerMeasureReportSanity(
IN PRTMP_ADAPTER pAd,
IN VOID *pMsg,
IN ULONG MsgLen,
OUT PUINT8 pDialogToken,
OUT PMEASURE_REPORT_INFO pMeasureReportInfo,
OUT PVOID *pMeasureRep)
{
PFRAME_802_11 Fr = (PFRAME_802_11)pMsg;
PUCHAR pFramePtr = Fr->Octet;
BOOLEAN result = FALSE;
PEID_STRUCT eid_ptr;
/* skip 802.11 header. */
MsgLen -= sizeof(HEADER_802_11);
/* skip category and action code. */
pFramePtr += 2;
MsgLen -= 2;
if (pMeasureReportInfo == NULL)
return result;
NdisMoveMemory(pDialogToken, pFramePtr, 1);
pFramePtr += 1;
MsgLen -= 1;
eid_ptr = (PEID_STRUCT)pFramePtr;
while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen))
{
switch(eid_ptr->Eid)
{
case IE_MEASUREMENT_REPORT:
NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1);
NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1);
NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1);
*pMeasureRep = (PVOID)(eid_ptr->Octet + 3);
result = TRUE;
break;
default:
break;
}
eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len);
}
return result;
}
#endif /* DOT11K_RRM_SUPPORT */

View File

@ -0,0 +1,940 @@
/*
***************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
*
* (c) Copyright 2002-2006, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
***************************************************************************/
/****************************************************************************
Abstract:
***************************************************************************/
#ifdef DOT11K_RRM_SUPPORT
#include "rt_config.h"
#define RTMP_INSERT_IE(_FRAMEBUFER, _TOTALFRAMELEN, _FRAMELEN, _FRAME) {\
ULONG _TempLen; \
MakeOutgoingFrame( (_FRAMEBUFER), &(_TempLen), \
(_FRAMELEN), (_FRAME), \
END_OF_ARGS); \
*(_TOTALFRAMELEN) += (_TempLen); \
}
VOID RRM_InsertBcnReqIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN PUCHAR pBcnReq)
{
RTMP_INSERT_IE(pFrameBuf, pFrameLen, sizeof(RRM_BEACON_REQ_INFO), pBcnReq);
}
VOID RRM_InsertBcnReqSsidSubIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN PUCHAR pSsid,
IN UINT8 SsidLen)
{
ULONG TempLen;
UINT8 SubId = RRM_BCN_REQ_SUBID_SSID;
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &SubId,
1, &SsidLen,
SsidLen, (PUCHAR)pSsid,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
}
VOID RRM_InsertBcnReqRepCndSubIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN UINT8 RepCnd,
IN UINT8 Threshold)
{
ULONG TempLen;
UINT8 Len = 2;
UINT8 SubId = RRM_BCN_REQ_SUBID_BCN_REP_INFO;
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &SubId,
1, &Len,
1, &RepCnd,
1, &Threshold,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
}
VOID RRM_InsertBcnReqRepDetailSubIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN UINT8 Detail)
{
ULONG TempLen;
UINT8 Len = 1;
UINT8 SubId = RRM_BCN_REQ_SUBID_RET_DETAIL;
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &SubId,
1, &Len,
1, &Detail,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
}
/*
==========================================================================
Description:
Insert RRM Enable Capabilitys IE into frame.
Parametrs:
1. frame buffer pointer.
2. frame length.
Return : None.
==========================================================================
*/
VOID RRM_InsertRRMEnCapIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN INT BssIdx)
{
ULONG TempLen;
UINT8 Len = 5;
UINT8 ElementID = IE_RRM_EN_CAP;
RRM_EN_CAP_IE RrmEnCap;
PMULTISSID_STRUCT pMBss = NULL;
if (BssIdx < MAX_MBSSID_NUM(pAd))
pMBss = &pAd->ApCfg.MBSSID[BssIdx];
else
return;
RrmEnCap.field.LinkMeasureCap = 1;
RrmEnCap.field.NeighborRepCap = 1;
RrmEnCap.field.ParallelMeasureCap = 0;
RrmEnCap.field.RepeatMeasureCap = 0;
RrmEnCap.field.BeaconPassiveMeasureCap = 1;
RrmEnCap.field.BeaconActiveMeasureCap = 1;
RrmEnCap.field.BeaconTabMeasureCap = 1;
RrmEnCap.field.BeaconMeasureReportCndCap = 1;
RrmEnCap.field.FrameMeasureCap = 0;
RrmEnCap.field.ChannelLoadMeasureCap = 0;
RrmEnCap.field.NoiseHistogramMeasureCap = 0;
RrmEnCap.field.StatisticMeasureCap = 0;
RrmEnCap.field.LCIMeasureCap = 0;
RrmEnCap.field.LCIAzimuthCap = 0;
RrmEnCap.field.TransmitStreamCap = 1;
RrmEnCap.field.TriggeredTransmitStreamCap = 1;
RrmEnCap.field.APChannelReportCap = 1;
RrmEnCap.field.RRMMibCap = 0;
RrmEnCap.field.OperatingChMaxMeasureDuration = 0;
RrmEnCap.field.NotOperatingChMaxMeasureDuration = 0;
RrmEnCap.field.MeasurePilotCap = 0;
RrmEnCap.field.MeasurePilotTxInfoCap = 0;
RrmEnCap.field.NeighReportTSFOffsetCap =
(pMBss->RrmCfg.bDot11kRRMNeighborRepTSFEnable) ? 1 : 0;
RrmEnCap.field.RCPIMeasureCap = 0;
RrmEnCap.field.RSNIMeasureCap = 0;
RrmEnCap.field.BssAvgAccessDelayCap = 0;
RrmEnCap.field.BssAvaiableAcmCap =
0;
RrmEnCap.field.AntennaInfoCap = 0;
MakeOutgoingFrame(pFrameBuf, &TempLen,
1, &ElementID,
1, &Len,
Len, (PUCHAR)&RrmEnCap.word,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
return;
}
VOID RRM_InsertNeighborRepIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN UINT8 Len,
IN PUINT8 pBssid,
IN RRM_BSSID_INFO BssidInfo,
IN UINT8 RegClass,
IN UINT8 Channel,
IN UINT8 PhyType)
{
ULONG TempLen;
UINT8 IEId = IE_RRM_NEIGHBOR_REP;
RRM_NEIGHBOR_REP_INFO NeighborRepInfo;
COPY_MAC_ADDR(NeighborRepInfo.Bssid, pBssid);
NeighborRepInfo.BssidInfo = BssidInfo.word;
NeighborRepInfo.RegulatoryClass = RegClass;
NeighborRepInfo.ChNum = Channel;
NeighborRepInfo.PhyType = PhyType;
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &IEId,
1, &Len,
sizeof(RRM_NEIGHBOR_REP_INFO), &NeighborRepInfo,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
return;
}
VOID RRM_InsertNeighborTSFOffsetSubIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN UINT16 TSFOffset,
IN UINT16 BcnInterval)
{
ULONG TempLen;
UINT8 Len = 4;
UINT8 SubId = RRM_NEIGHBOR_REP_TSF_INFO_SUB_ID;
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &SubId,
1, &Len,
2, &TSFOffset,
2, &BcnInterval,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
}
VOID RRM_InsertQuietIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN UINT8 QuietCnt,
IN UINT8 QuietPeriod,
IN UINT8 QuietDuration,
IN UINT8 QuietOffset)
{
ULONG TempLen;
UINT8 IEId = IE_QUIET;
QUIET_INFO QuietInfo;
UINT8 Len;
QuietInfo.QuietCnt = QuietCnt;
QuietInfo.QuietPeriod = QuietPeriod;
QuietInfo.QuietDuration = cpu2le16(QuietDuration);
QuietInfo.QuietOffset = cpu2le16(QuietOffset);
Len = 6;
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &IEId,
1, &Len,
Len, &QuietInfo,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
return;
}
VOID RRM_InsertBssACDelayIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen)
{
ULONG TempLen;
UINT8 IEId = IE_BSS_AC_DELAY;
RRM_BSS_AC_DELAY_INFO AcDelayInfo;
UINT8 Len;
Len = 4;
AcDelayInfo.BE_ACDelay = 255;
AcDelayInfo.BK_ACDelay = 255;
AcDelayInfo.VI_ACDelay = 255;
AcDelayInfo.VO_ACDelay = 255;
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &IEId,
1, &Len,
Len, &AcDelayInfo,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
return;
}
VOID RRM_InsertBssAvailableACIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen)
{
INT idx;
ULONG TempLen;
UINT8 IEId = IE_BSS_AVAILABLE_AC;
RRM_BSS_AVAILABLE_AC_INFO AvailableAcInfo;
PRRM_BSS_AVAILABLE_AC_BITMAP pAcBitMap;
UINT8 Len;
pAcBitMap = (PRRM_BSS_AVAILABLE_AC_BITMAP) \
&AvailableAcInfo.AvailableAcBitMap;
pAcBitMap->word = 0;
pAcBitMap->word = cpu2le16(pAcBitMap->word);
/* cacule the total length of the IE. */
Len = 2;
for (idx=0; idx<12; idx++)
{
if (pAcBitMap->word & (0x1 << idx))
Len += 2;
}
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &IEId,
1, &Len,
sizeof(RRM_BSS_AVAILABLE_AC_INFO), &AvailableAcInfo,
END_OF_ARGS);
*pFrameLen += TempLen;
pFrameBuf += TempLen;
return;
}
VOID RRM_InsertRequestIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen)
{
UINT8 RequestIEs[] = { 0, /* SSID */
48, /* RSN IE */
70, /* RRM Capabilities. */
54, /* Mobility Domain. */
221}; /* Vendor Specific. */
ULONG TempLen;
UINT8 IEId = IE_802_11D_REQUEST;
UINT8 Len;
Len = 5;
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &IEId,
1, &Len,
Len, RequestIEs,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
return;
}
VOID RRM_InsertTxStreamReqIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN PUCHAR pBuf)
{
RTMP_INSERT_IE(pFrameBuf, pFrameLen,
sizeof(RRM_TRANSMIT_MEASURE_INFO), pBuf);
}
VOID RRM_InsertTxStreamReqTriggerReportSubIE(
IN PRTMP_ADAPTER pAd,
OUT PUCHAR pFrameBuf,
OUT PULONG pFrameLen,
IN PUCHAR pBuf)
{
ULONG TempLen;
ULONG Len = sizeof(RRM_TRANSMIT_MEASURE_TRIGGER_REPORT);
UINT8 SubId = RRM_TX_STREAM_SUBID_TRIGGER_REPORT;
MakeOutgoingFrame( pFrameBuf, &TempLen,
1, &SubId,
1, &Len,
Len, pBuf,
END_OF_ARGS);
*pFrameLen = *pFrameLen + TempLen;
}
VOID RRM_EnqueueBcnReq(
IN PRTMP_ADAPTER pAd,
IN UINT8 Aid,
IN UINT8 IfIdx,
IN PRRM_MLME_BCN_REQ_INFO pMlmeBcnReq)
{
UINT8 MeasureReqType = RRM_MEASURE_SUBTYPE_BEACON;
MEASURE_REQ_MODE MeasureReqMode;
UINT8 MeasureReqToken = RandomByte(pAd);
RRM_BEACON_REQ_INFO BcnReq;
UINT8 ReportDetail;
UINT8 TotalLen;
HEADER_802_11 ActHdr;
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
ULONG FrameLen;
NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */
if(NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
return;
}
/* build action frame header. */
MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[Aid].Addr,
pAd->ApCfg.MBSSID[IfIdx].wdev.if_addr,
pAd->ApCfg.MBSSID[IfIdx].wdev.bssid);
NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
FrameLen = sizeof(HEADER_802_11);
/*
Action header has a field to indicate total length of packet
but the total length is unknow untial whole packet completd.
So skip the action here and fill it late.
1. skip Catgore (1 octect), Action(1 octect).
2. skip dailog token (1 octect).
3. skip Num Of Repetitions field (2 octects)
3. skip MeasureReqIE (2 + sizeof(MEASURE_REQ_INFO)).
*/
FrameLen += (7 + sizeof(MEASURE_REQ_INFO));
TotalLen = sizeof(MEASURE_REQ_INFO);
/*
Insert Beacon Req IE.
*/
BcnReq.RegulatoryClass = pMlmeBcnReq->RegulatoryClass;
BcnReq.ChNumber = pMlmeBcnReq->MeasureCh;
BcnReq.RandomInterval = cpu2le16((UINT16)RandomByte(pAd) << 8
| (UINT16)RandomByte(pAd));
BcnReq.MeasureDuration = cpu2le16(pMlmeBcnReq->MeasureDuration);
BcnReq.MeasureMode = pMlmeBcnReq->MeasureMode;
COPY_MAC_ADDR(BcnReq.Bssid, pMlmeBcnReq->Bssid);
RRM_InsertBcnReqIE(pAd, (pOutBuffer+FrameLen),
&FrameLen, (PUCHAR)&BcnReq);
TotalLen += sizeof(RRM_BEACON_REQ_INFO);
/* inssert SSID sub field. */
if (pMlmeBcnReq->SsidLen != 0)
{
RRM_InsertBcnReqSsidSubIE(pAd, (pOutBuffer+FrameLen),
&FrameLen, (PUCHAR)pMlmeBcnReq->pSsid, pMlmeBcnReq->SsidLen);
TotalLen += (pMlmeBcnReq->SsidLen + 2); /* SSID sub field. */
}
/* inssert report condition sub field. */
if (pMlmeBcnReq->BcnReqCapFlag.field.ReportCondition == TRUE)
{
RRM_InsertBcnReqRepCndSubIE(pAd, (pOutBuffer+FrameLen), &FrameLen, 0, 0);
TotalLen += (2 + 2); /* SSID sub field. */
}
/* inssert channel report sub field. */
if (pMlmeBcnReq->BcnReqCapFlag.field.ChannelRep == TRUE)
{
ULONG idx;
idx = 0;
while(pMlmeBcnReq->ChRepRegulatoryClass[idx] != 0)
{
ULONG FramelenTmp = FrameLen;
InsertChannelRepIE(pAd, (pOutBuffer+FrameLen), &FrameLen,
(PSTRING)pAd->CommonCfg.CountryCode,
pMlmeBcnReq->ChRepRegulatoryClass[idx]);
TotalLen += (FrameLen - FramelenTmp);
idx ++;
}
}
/* inssert report detail sub field. */
if (BcnReq.MeasureMode == 2)
ReportDetail = 0;
else
ReportDetail = 1;
if (ReportDetail == 1)
{
ULONG FramelenTmp = FrameLen;
RRM_InsertBcnReqRepDetailSubIE(pAd, (pOutBuffer+FrameLen), &FrameLen, 1);
TotalLen += (FrameLen - FramelenTmp);
FramelenTmp = FrameLen;
RRM_InsertRequestIE(pAd, (pOutBuffer+FrameLen), &FrameLen);
TotalLen += (FrameLen - FramelenTmp);
}
else
{
ULONG FramelenTmp = FrameLen;
RRM_InsertBcnReqRepDetailSubIE(pAd, (pOutBuffer+FrameLen), &FrameLen, 0);
TotalLen += (FrameLen - FramelenTmp);
}
/* Insert Action header here. */
{
ULONG tmpLen = sizeof(HEADER_802_11);;
MeasureReqMode.word = 0;
MakeMeasurementReqFrame(pAd, pOutBuffer, &tmpLen,
TotalLen, CATEGORY_RM, RRM_MEASURE_REQ, MeasureReqToken,
MeasureReqMode.word, MeasureReqType, 1);
}
MeasureReqInsert(pAd, MeasureReqToken);
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
if (pOutBuffer)
MlmeFreeMemory(pAd, pOutBuffer);
return;
}
#ifdef CONFIG_STA_SUPPORT
VOID RRM_EnqueueNeighborReq(
IN PRTMP_ADAPTER pAd,
IN PUINT8 pDA,
IN PUINT8 pSsid,
IN UINT8 SsidLen)
{
HEADER_802_11 ActHdr;
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
ULONG FrameLen;
UINT8 DialogToken = RandomByte(pAd);
NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */
if(NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
return;
}
/* build action frame header. */
MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA,
pAd->MlmeAux.Bssid);
NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
FrameLen = sizeof(HEADER_802_11);
/* fill Dialog Token */
InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
if (pOutBuffer)
MlmeFreeMemory(pAd, pOutBuffer);
return;
}
#endif /* CONFIG_STA_SUPPORT */
VOID RRM_EnqueueNeighborRep(
IN PRTMP_ADAPTER pAd,
IN PMAC_TABLE_ENTRY pEntry,
IN UINT8 DialogToken,
IN PCHAR pSsid,
IN UINT8 SsidLen)
{
#define MIN(_x, _y) ((_x) > (_y) ? (_x) : (_y))
INT loop;
HEADER_802_11 ActHdr;
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
ULONG FrameLen;
ULONG PktLen;
if ((pEntry == NULL) || (pEntry->apidx >= pAd->ApCfg.BssidNum))
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid STA.\n", __FUNCTION__));
return;
}
NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */
if(NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
return;
}
/* build action frame header. */
MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pEntry->Addr,
pAd->ApCfg.MBSSID[pEntry->apidx].wdev.if_addr,
pAd->ApCfg.MBSSID[pEntry->apidx].wdev.bssid);
NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
FrameLen = sizeof(HEADER_802_11);
InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
CATEGORY_RM, RRM_NEIGHTBOR_RSP);
/* fill Dialog Token */
InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
#ifdef AP_SCAN_SUPPORT
/* insert NeighborRep IE. */
for (loop = 0; loop < pAd->ScanTab.BssNr; loop++)
{
UINT8 BssMatch = FALSE;
BSS_ENTRY *pBssEntry = &pAd->ScanTab.BssEntry[loop];
/* Discards all remain Bss if the packet length exceed packet buffer size. */
PktLen = FrameLen + sizeof(RRM_NEIGHBOR_REP_INFO)
+ (pAd->ApCfg.MBSSID[pEntry->apidx].RrmCfg.bDot11kRRMNeighborRepTSFEnable == TRUE ? 6 : 0);
if (PktLen >= MGMT_DMA_BUFFER_SIZE)
break;
if (SsidLen != 0)
BssMatch = RTMPEqualMemory(pBssEntry->Ssid, pSsid,
MIN(SsidLen, pBssEntry->SsidLen));
else
BssMatch = TRUE;
if (BssMatch)
{
RRM_BSSID_INFO BssidInfo;
BssidInfo.word = 0;
BssidInfo.field.APReachAble = 3;
BssidInfo.field.Security = 0; /* rrm to do. */
BssidInfo.field.KeyScope = 0; /* "report AP has same authenticator as the AP. */
BssidInfo.field.SepctrumMng = (pBssEntry->CapabilityInfo & (1 << 8))?1:0;
BssidInfo.field.Qos = (pBssEntry->CapabilityInfo & (1 << 9))?1:0;
BssidInfo.field.APSD = (pBssEntry->CapabilityInfo & (1 << 11))?1:0;
BssidInfo.field.RRM = (pBssEntry->CapabilityInfo & RRM_CAP_BIT)?1:0;
BssidInfo.field.DelayBlockAck = (pBssEntry->CapabilityInfo & (1 << 14))?1:0;
BssidInfo.field.ImmediateBA = (pBssEntry->CapabilityInfo & (1 << 15))?1:0;
/*
reference 2012 spec.
802.11-2012.pdf
page#581 (0 is not euqal to no security )
The Security bit, if 1, indicates that the AP identified by this BSSID supports the same security provisioning
as used by the STA in its current association. If the bit is 0, it indicates either that the AP does not support
the same security provisioning or that the security information is not available at this time.
*/
BssidInfo.field.KeyScope = 0; /* "report AP has same authenticator as the AP. */
/*
reference 2012 spec.
802.11-2012.pdf
page#582 (0 means information is not available )
The Key Scope bit, when set, indicates the AP indicated by this BSSID has the same authenticator as the AP
sending the report. If this bit is 0, it indicates a distinct authenticator or the information is not available.
*/
BssidInfo.field.SepctrumMng = (pBssEntry->CapabilityInfo & (1 << 8))?1:0;
BssidInfo.field.Qos = (pBssEntry->CapabilityInfo & (1 << 9))?1:0;
BssidInfo.field.APSD = (pBssEntry->CapabilityInfo & (1 << 11))?1:0;
BssidInfo.field.RRM = (pBssEntry->CapabilityInfo & RRM_CAP_BIT)?1:0;
BssidInfo.field.DelayBlockAck = (pBssEntry->CapabilityInfo & (1 << 14))?1:0;
BssidInfo.field.ImmediateBA = (pBssEntry->CapabilityInfo & (1 << 15))?1:0;
BssidInfo.field.MobilityDomain = (pBssEntry->bHasMDIE )?1:0;
BssidInfo.field.HT = (pBssEntry->HtCapabilityLen != 0)?1:0;
#ifdef DOT11_VHT_AC
BssidInfo.field.VHT = (pBssEntry->vht_cap_len != 0)?1:0;
#endif /* DOT11_VHT_AC */
/*
reference spec:
dot11FrameRprtPhyType OBJECT-TYPE
SYNTAX INTEGER {
fhss(1),
dsss(2),
irbaseband(3),
ofdm(4),
hrdsss(5),
erp(6),
ht(7),
vht(9)
}
*/
if (pBssEntry->Channel > 14) // 5G case
{
if (pBssEntry->HtCapabilityLen != 0) // HT or Higher case
{
#ifdef DOT11_VHT_AC
if (pBssEntry->vht_cap_len != 0)
pBssEntry->CondensedPhyType = 9;
else
#endif /* DOT11_VHT_AC */
pBssEntry->CondensedPhyType = 7;
}
else // OFDM case
{
pBssEntry->CondensedPhyType = 4;
}
}
else // 2.4G case
{
if (pBssEntry->HtCapabilityLen != 0) //HT case
pBssEntry->CondensedPhyType = 7;
else if (ERP_IS_NON_ERP_PRESENT(pBssEntry->Erp)) //ERP case
pBssEntry->CondensedPhyType = 6;
else if (pBssEntry->SupRateLen > 4)// OFDM case (1,2,5.5,11 for CCK 4 Rates)
pBssEntry->CondensedPhyType = 4;
/* no CCK's definition in spec. */
}
RRM_InsertNeighborRepIE(pAd, (pOutBuffer + FrameLen), &FrameLen,
sizeof(RRM_NEIGHBOR_REP_INFO), pBssEntry->Bssid,
BssidInfo, pBssEntry->RegulatoryClass,
pBssEntry->Channel, pBssEntry->CondensedPhyType);
}
/*
shall insert Neighbor Report TSF offset
when the MIB attribute
dot11RRMNeighborReportTSFOffsetEnabled is true.
*/
if (pAd->ApCfg.MBSSID[pEntry->apidx].RrmCfg.bDot11kRRMNeighborRepTSFEnable)
{
UINT32 Ttfs = (UINT32)(pBssEntry->TTSF[3] << 24)
+ (UINT32)(pBssEntry->TTSF[2] << 16)
+ (UINT32)(pBssEntry->TTSF[1] << 8)
+ (UINT32)(pBssEntry->TTSF[0]);
UINT32 Ptfs = (UINT32)(pBssEntry->PTSF[3] << 24)
+ (UINT32)(pBssEntry->PTSF[2] << 16)
+ (UINT32)(pBssEntry->PTSF[1] << 8)
+ (UINT32)(pBssEntry->PTSF[0]);
RRM_InsertNeighborTSFOffsetSubIE(pAd, (pOutBuffer + FrameLen),
&FrameLen, cpu2le16((UINT16)ABS(Ttfs, Ptfs)),
pBssEntry->BeaconPeriod);
}
}
#endif /* AP_SCAN_SUPPORT */
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
if (pOutBuffer)
MlmeFreeMemory(pAd, pOutBuffer);
return;
}
VOID RRM_EnqueueLinkMeasureReq(
IN PRTMP_ADAPTER pAd,
IN UINT8 Aid,
IN UINT8 apidx)
{
UINT8 DialogToken = RandomByte(pAd);
HEADER_802_11 ActHdr;
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
ULONG FrameLen;
PMAC_TABLE_ENTRY pEntry;
if ((apidx >= pAd->ApCfg.BssidNum)
|| (Aid >= MAX_LEN_OF_MAC_TABLE))
{
DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid STA. apidx=%d Aid=%d\n",
__FUNCTION__, apidx, Aid));
return;
}
NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /* Get an unused nonpaged memory */
if(NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
return;
}
pEntry = &pAd->MacTab.Content[Aid];
/* build action frame header. */
MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pEntry->Addr,
pAd->ApCfg.MBSSID[apidx].wdev.if_addr,
pAd->ApCfg.MBSSID[apidx].wdev.bssid);
NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
FrameLen = sizeof(HEADER_802_11);
InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen,
CATEGORY_RM, RRM_LNK_MEASURE_REQ);
/* fill Dialog Token */
InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken);
/* fill Tx Power Used field */
{
ULONG TempLen;
UINT8 TxPwr = RTMP_GetTxPwr(pAd, pAd->CommonCfg.MlmeTransmit);
MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen,
1, &TxPwr,
END_OF_ARGS);
FrameLen += TempLen;
}
/* fill Max Tx Power field */
{
ULONG TempLen;
UINT8 MaxTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel);
MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen,
1, &MaxTxPwr,
END_OF_ARGS);
FrameLen += TempLen;
}
MeasureReqInsert(pAd, DialogToken);
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
if (pOutBuffer)
MlmeFreeMemory(pAd, pOutBuffer);
return;
}
VOID RRM_EnqueueTxStreamMeasureReq(
IN PRTMP_ADAPTER pAd,
IN UINT8 Aid,
IN UINT8 apidx,
IN PRRM_MLME_TRANSMIT_REQ_INFO pMlmeTxMeasureReq)
{
UINT8 MeasureReqType = RRM_MEASURE_SUBTYPE_TX_STREAM;
MEASURE_REQ_MODE MeasureReqMode;
UINT8 MeasureReqToken = RandomByte(pAd);
RRM_TRANSMIT_MEASURE_INFO TxMeasureReq;
RRM_TRANSMIT_MEASURE_TRIGGER_REPORT TriggerReport;
UINT8 TotalLen;
HEADER_802_11 ActHdr;
PUCHAR pOutBuffer = NULL;
NDIS_STATUS NStatus;
ULONG FrameLen;
NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */
if(NStatus != NDIS_STATUS_SUCCESS)
{
DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__));
return;
}
MeasureReqMode.word = 0;
/* build action frame header. */
MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[Aid].Addr,
pAd->ApCfg.MBSSID[apidx].wdev.if_addr,
pAd->ApCfg.MBSSID[apidx].wdev.bssid);
NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11));
FrameLen = sizeof(HEADER_802_11);
/*
Action header has a field to indicate total length of packet
but the total length is unknow untial whole packet completd.
So skip the action here and fill it late.
1. skip Catgore (1 octect), Action(1 octect).
2. skip dailog token (1 octect).
3. skip Num Of Repetitions field (2 octects)
3. skip MeasureReqIE (2 + sizeof(MEASURE_REQ_INFO)).
*/
FrameLen += (7 + sizeof(MEASURE_REQ_INFO));
TotalLen = sizeof(MEASURE_REQ_INFO);
/*
Insert Tx stream Measure Req IE.
*/
/* according to WiFi Voice-enterprise testing req. the RandomInterval shall be zero. */
TxMeasureReq.RandomInterval = 0;
TxMeasureReq.MeasureDuration = cpu2le16(pMlmeTxMeasureReq->MeasureDuration);
COPY_MAC_ADDR(TxMeasureReq.PeerStaMac, pAd->MacTab.Content[Aid].Addr);
TxMeasureReq.TIDField.Rev = 0;
TxMeasureReq.TIDField.TID = pMlmeTxMeasureReq->Tid;
TxMeasureReq.Bin0Range = pMlmeTxMeasureReq->BinRange;
RRM_InsertTxStreamReqIE(pAd, (pOutBuffer+FrameLen),
&FrameLen, (PUCHAR)&TxMeasureReq);
TotalLen += sizeof(RRM_TRANSMIT_MEASURE_INFO);
/* inssert Trigger report sub field. */
if (pMlmeTxMeasureReq->bTriggerReport == 1)
{
PRRM_TRANSMIT_MEASURE_TRIGGER_CONDITION pTiggerCon
= (PRRM_TRANSMIT_MEASURE_TRIGGER_CONDITION)&TriggerReport.TriggerCondition;
pTiggerCon->field.Average = pMlmeTxMeasureReq->ArvCondition;
pTiggerCon->field.Consecutive = pMlmeTxMeasureReq->ConsecutiveCondition;
pTiggerCon->field.Delay = pMlmeTxMeasureReq->DelayCondition;
if (pTiggerCon->field.Average)
TriggerReport.AvrErrorThreshold = pMlmeTxMeasureReq->AvrErrorThreshold;
if (pTiggerCon->field.Consecutive)
TriggerReport.ConsecutiveErrorThreshold = pMlmeTxMeasureReq->ConsecutiveErrorThreshold;
if (pTiggerCon->field.Delay)
TriggerReport.DelayThreshold = pMlmeTxMeasureReq->DelayThreshold;
TriggerReport.TriggerTimeout = pMlmeTxMeasureReq->TriggerTimeout;
TriggerReport.MeasurementCnt = pMlmeTxMeasureReq->MeasureCnt;
RRM_InsertTxStreamReqTriggerReportSubIE(pAd, (pOutBuffer+FrameLen),
&FrameLen, (PUCHAR)&TriggerReport);
TotalLen +=
(sizeof(RRM_TRANSMIT_MEASURE_TRIGGER_REPORT) + 2);
MeasureReqMode.field.Report = 1;
}
/* Insert Action header here. */
{
ULONG tmpLen = sizeof(HEADER_802_11);;
MeasureReqMode.field.Enable = 1;
MeasureReqMode.field.DurationMandatory =
pMlmeTxMeasureReq->bDurationMandatory;
MakeMeasurementReqFrame(pAd, pOutBuffer, &tmpLen,
TotalLen, CATEGORY_RM, RRM_MEASURE_REQ, MeasureReqToken,
MeasureReqMode.word, MeasureReqType, 0xffff);
}
MeasureReqInsert(pAd, MeasureReqToken);
MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen);
if (pOutBuffer)
MlmeFreeMemory(pAd, pOutBuffer);
return;
}
#endif /* DOT11K_RRM_SUPPORT */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,218 @@
/****************************************************************************
Module Name:
rt_os_util.c
Abstract:
All functions provided from UTIL module are put here (OS independent).
Revision History:
Who When What
--------- ---------- ----------------------------------------------
***************************************************************************/
#define RTMP_MODULE_OS
#define RTMP_MODULE_OS_UTIL
/*#include "rt_config.h"
*/
#include "rtmp_comm.h"
#include "rt_os_util.h"
#include "rtmp_osabl.h"
VOID RtmpDrvRateGet(
IN VOID *pReserved,
IN UINT8 MODE,
IN UINT8 ShortGI,
IN UINT8 BW,
IN UINT8 MCS,
IN UINT8 Antenna,
OUT UINT32 *pRate)
{
UINT32 MCS_1NSS = (UINT32) MCS;
*pRate = 0;
DBGPRINT(RT_DEBUG_TRACE,("<==== %s \nMODE: %x shortGI: %x BW: %x MCS: %x Antenna: %x \n"
,__FUNCTION__,MODE,ShortGI,BW,MCS,Antenna));
if((BW >= Rate_BW_MAX) || (ShortGI >= Rate_GI_MAX) || (BW >= Rate_BW_MAX))
{
DBGPRINT(RT_DEBUG_ERROR,("<==== %s MODE: %x shortGI: %x BW: %x MCS: %x Antenna: %x , param error\n",__FUNCTION__,MODE,ShortGI,BW,MCS,Antenna));
return;
}
#ifdef DOT11_VHT_AC
if (MODE >= MODE_VHT)
{
if(MCS_1NSS > 9)
MCS_1NSS %= 16;
*pRate = RalinkRate_VHT_1NSS[BW][ShortGI][MCS_1NSS];
}
else
#endif /* DOT11_VHT_AC */
#ifdef DOT11_N_SUPPORT
if ((MODE >= MODE_HTMIX) && (MODE < MODE_VHT))
{
if(MCS_1NSS > 7)
MCS_1NSS %= 8;
*pRate = RalinkRate_HT_1NSS[BW][ShortGI][MCS_1NSS];
}
else
#endif /* DOT11_N_SUPPORT */
if (MODE == MODE_OFDM)
*pRate = RalinkRate_Legacy[MCS_1NSS+4];
else
*pRate = RalinkRate_Legacy[MCS_1NSS];
*pRate *= 500000;
#if defined(DOT11_VHT_AC) || defined(DOT11_N_SUPPORT)
if (MODE >= MODE_HTMIX)
*pRate *= Antenna;
#endif /* DOT11_VHT_AC */
DBGPRINT(RT_DEBUG_TRACE,("=====> %s \nMODE: %x shortGI: %x BW: %x MCS: %x Antenna: %x Rate = %d\n"
,__FUNCTION__,MODE,ShortGI,BW,MCS_1NSS,Antenna, (*pRate)/1000000));
}
char *rtstrchr(const char * s, int c)
{
for(; *s != (char) c; ++s)
if (*s == '\0')
return NULL;
return (char *) s;
}
VOID RtmpMeshDown(
IN VOID *pDrvCtrlBK,
IN BOOLEAN WaitFlag,
IN BOOLEAN (*RtmpMeshLinkCheck)(IN VOID *pAd))
{
}
#ifdef ETH_CONVERT_SUPPORT
USHORT RtmpOsNetPrivGet(
IN PNET_DEV pDev)
{
return RT_DEV_PRIV_FLAGS_GET(pDev);
}
#endif /* ETH_CONVERT_SUPPORT */
BOOLEAN RtmpOsCmdDisplayLenCheck(
IN UINT32 LenSrc,
IN UINT32 Offset)
{
if (LenSrc > (IW_PRIV_SIZE_MASK - Offset))
return FALSE;
return TRUE;
}
#ifdef WPA_SUPPLICANT_SUPPORT
VOID WpaSendMicFailureToWpaSupplicant(
IN PNET_DEV pNetDev,
IN const PUCHAR src_addr,
IN BOOLEAN bUnicast,
IN INT key_id,
IN const PUCHAR tsc)
{
#ifdef RT_CFG80211_SUPPORT
CFG80211OS_MICFailReport(pNetDev, src_addr, bUnicast, key_id, tsc);
#else
char custom[IW_CUSTOM_MAX] = {0};
snprintf(custom, sizeof(custom), "MLME-MICHAELMICFAILURE.indication");
if(bUnicast)
sprintf(custom, "%s unicast", custom);
RtmpOSWrielessEventSend(pNetDev, RT_WLAN_EVENT_CUSTOM, -1, NULL, (PUCHAR)custom, strlen(custom));
#endif /* RT_CFG80211_SUPPORT */
return;
}
#endif /* WPA_SUPPLICANT_SUPPORT */
#ifdef NATIVE_WPA_SUPPLICANT_SUPPORT
int wext_notify_event_assoc(
IN PNET_DEV pNetDev,
IN UCHAR *ReqVarIEs,
IN UINT32 ReqVarIELen)
{
char custom[IW_CUSTOM_MAX] = {0};
#if WIRELESS_EXT > 17
if (ReqVarIELen <= IW_CUSTOM_MAX)
{
NdisMoveMemory(custom, ReqVarIEs, ReqVarIELen);
RtmpOSWrielessEventSend(pNetDev, RT_WLAN_EVENT_ASSOC_REQ_IE, -1, NULL,
(UCHAR *)custom, ReqVarIELen);
}
else
DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen > MAX_CUSTOM_LEN\n"));
#else
int len;
len = (ReqVarIELen*2) + 17;
if (len <= IW_CUSTOM_MAX)
{
UCHAR idx;
snprintf(custom, sizeof(custom), "ASSOCINFO(ReqIEs=");
for (idx=0; idx<ReqVarIELen; idx++)
sprintf(custom, "%s%02x", custom, ReqVarIEs[idx]);
RtmpOSWrielessEventSend(pNetDev, RT_WLAN_EVENT_CUSTOM, -1, NULL, custom, len);
}
else
DBGPRINT(RT_DEBUG_TRACE, ("len(%d) > MAX_CUSTOM_LEN\n", len));
#endif
return 0;
}
#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */
#ifdef CONFIG_STA_SUPPORT
#ifdef WPA_SUPPLICANT_SUPPORT
#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
VOID SendAssocIEsToWpaSupplicant(
IN PNET_DEV pNetDev,
IN UCHAR *ReqVarIEs,
IN UINT32 ReqVarIELen)
{
STRING custom[IW_CUSTOM_MAX] = {0};
if ((ReqVarIELen + 17) <= IW_CUSTOM_MAX)
{
snprintf(custom, sizeof(custom), "ASSOCINFO_ReqIEs=");
NdisMoveMemory(custom+17, ReqVarIEs, ReqVarIELen);
RtmpOSWrielessEventSend(pNetDev, RT_WLAN_EVENT_CUSTOM, RT_REQIE_EVENT_FLAG, NULL, (PUCHAR)custom, ReqVarIELen + 17);
RtmpOSWrielessEventSend(pNetDev, RT_WLAN_EVENT_CUSTOM, RT_ASSOCINFO_EVENT_FLAG, NULL, NULL, 0);
}
else
DBGPRINT(RT_DEBUG_TRACE, ("pAd->StaCfg.ReqVarIELen + 17 > MAX_CUSTOM_LEN\n"));
return;
}
#endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */
#endif /* WPA_SUPPLICANT_SUPPORT */
#endif /*CONFIG_STA_SUPPORT*/
INT32 RtPrivIoctlSetVal(VOID)
{
return (INT32)RTPRIV_IOCTL_SET;
}
#ifndef RTMP_ANDES_JAY
#endif /* RTMP_ANDES_JAY */

Some files were not shown because too many files have changed in this diff Show More